|
49 | 49 | import java.nio.file.StandardCopyOption; |
50 | 50 | import java.util.ArrayList; |
51 | 51 | import java.util.Collection; |
| 52 | +import java.util.Comparator; |
52 | 53 | import java.util.List; |
53 | 54 | import java.util.Map; |
54 | 55 | import java.util.Objects; |
@@ -161,28 +162,74 @@ public void verifyIssues() { |
161 | 162 |
|
162 | 163 | private static void verifyIssuesOnLinesInternal( |
163 | 164 | List<Issue> issues, List<IssueExpectation> expectedIssues) { |
164 | | - List<Integer> unexpectedLines = new ArrayList<>(); |
165 | | - List<Integer> expectedLines = |
166 | | - expectedIssues.stream().map(IssueExpectation::getBeginLine).collect(Collectors.toList()); |
| 165 | + List<IssueExpectation> unexpectedIssues = new ArrayList<>(); |
| 166 | + List<IssueExpectation> expectations = new ArrayList<>(expectedIssues); |
167 | 167 |
|
168 | 168 | for (Issue issue : issues) { |
169 | | - IssueLocation issueLocation = issue.primaryLocation(); |
170 | | - |
171 | | - TextRange textRange = issueLocation.textRange(); |
172 | | - if (textRange == null) { |
173 | | - throw new AssertionError( |
174 | | - String.format( |
175 | | - "Expected issues to be raised at line level, not at %s level", |
176 | | - issueLocation.inputComponent().isFile() ? "file" : "project")); |
| 169 | + Optional<IssueExpectation> expectedIssue = findIssue(issue, expectations); |
| 170 | + if (expectedIssue.isPresent()) { |
| 171 | + expectations.remove(expectedIssue.get()); |
| 172 | + } else { |
| 173 | + unexpectedIssues.add(expectationFromIssue(issue)); |
177 | 174 | } |
| 175 | + } |
| 176 | + |
| 177 | + assertIssueMismatchesEmpty(expectations, unexpectedIssues); |
| 178 | + } |
| 179 | + |
| 180 | + private static IssueExpectation expectationFromIssue(Issue issue) { |
| 181 | + int primaryLine = getStartingLine(issue.primaryLocation()); |
| 182 | + List<List<Integer>> actualLines = |
| 183 | + issue.flows().stream() |
| 184 | + .map( |
| 185 | + flow -> |
| 186 | + flow.locations().stream() |
| 187 | + .map(location -> getStartingLine(location) - primaryLine) |
| 188 | + .collect(Collectors.toList())) |
| 189 | + .sorted(Comparator.comparing(list -> list.get(0))) |
| 190 | + .collect(Collectors.toList()); |
| 191 | + return new IssueExpectation(primaryLine, actualLines); |
| 192 | + } |
| 193 | + |
| 194 | + private static Optional<IssueExpectation> findIssue( |
| 195 | + Issue issue, List<IssueExpectation> expectations) { |
| 196 | + int line = getStartingLine(issue.primaryLocation()); |
178 | 197 |
|
179 | | - Integer line = textRange.start().line(); |
180 | | - if (!expectedLines.remove(line)) { |
181 | | - unexpectedLines.add(line); |
| 198 | + for (IssueExpectation expectation : expectations) { |
| 199 | + if (expectation.getBeginLine() != line |
| 200 | + || expectation.getFlowLines().size() != issue.flows().size()) { |
| 201 | + continue; |
| 202 | + } |
| 203 | + List<List<Integer>> expectedLines = |
| 204 | + expectation.getFlowLines().stream() |
| 205 | + .map( |
| 206 | + offsets -> |
| 207 | + offsets.stream().map(offset -> offset + line).collect(Collectors.toList())) |
| 208 | + .collect(Collectors.toList()); |
| 209 | + List<List<Integer>> actualLines = |
| 210 | + issue.flows().stream() |
| 211 | + .map( |
| 212 | + flow -> |
| 213 | + flow.locations().stream() |
| 214 | + .map(CheckVerifierImpl::getStartingLine) |
| 215 | + .collect(Collectors.toList())) |
| 216 | + .collect(Collectors.toList()); |
| 217 | + if (expectedLines.equals(actualLines)) { |
| 218 | + return Optional.of(expectation); |
182 | 219 | } |
183 | 220 | } |
| 221 | + return Optional.empty(); |
| 222 | + } |
184 | 223 |
|
185 | | - assertIssueMismatchesEmpty(expectedLines, unexpectedLines); |
| 224 | + private static int getStartingLine(IssueLocation location) { |
| 225 | + TextRange textRange = location.textRange(); |
| 226 | + if (textRange == null) { |
| 227 | + throw new AssertionError( |
| 228 | + String.format( |
| 229 | + "Expected issues to be raised at line level, not at %s level", |
| 230 | + location.inputComponent().isFile() ? "file" : "project")); |
| 231 | + } |
| 232 | + return textRange.start().line(); |
186 | 233 | } |
187 | 234 |
|
188 | 235 | private void assertQuickFixes( |
@@ -324,17 +371,17 @@ private static boolean textEditMatches( |
324 | 371 | } |
325 | 372 |
|
326 | 373 | private static void assertIssueMismatchesEmpty( |
327 | | - List<Integer> expectedLines, List<Integer> unexpectedLines) { |
328 | | - if (!expectedLines.isEmpty() || !unexpectedLines.isEmpty()) { |
| 374 | + List<IssueExpectation> expectedIssues, List<IssueExpectation> unexpectedIssues) { |
| 375 | + if (!expectedIssues.isEmpty() || !unexpectedIssues.isEmpty()) { |
329 | 376 | StringBuilder message = new StringBuilder("Issues were "); |
330 | | - if (!expectedLines.isEmpty()) { |
331 | | - message.append("expected at ").append(expectedLines); |
| 377 | + if (!expectedIssues.isEmpty()) { |
| 378 | + message.append("expected at ").append(expectedIssues); |
332 | 379 | } |
333 | | - if (!expectedLines.isEmpty() && !unexpectedLines.isEmpty()) { |
| 380 | + if (!expectedIssues.isEmpty() && !unexpectedIssues.isEmpty()) { |
334 | 381 | message.append(", "); |
335 | 382 | } |
336 | | - if (!unexpectedLines.isEmpty()) { |
337 | | - message.append("unexpected at ").append(unexpectedLines); |
| 383 | + if (!unexpectedIssues.isEmpty()) { |
| 384 | + message.append("unexpected at ").append(unexpectedIssues); |
338 | 385 | } |
339 | 386 | throw new AssertionError(message.toString()); |
340 | 387 | } |
|
0 commit comments