1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.checks.naming.AbstractNameCheck.MSG_INVALID_PATTERN;
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.Mockito.CALLS_REAL_METHODS;
26 import static org.mockito.Mockito.doThrow;
27 import static org.mockito.Mockito.mock;
28
29 import java.io.File;
30 import java.io.Writer;
31 import java.nio.charset.StandardCharsets;
32 import java.nio.file.Files;
33 import java.nio.file.StandardCopyOption;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Set;
43 import java.util.UUID;
44 import java.util.regex.Matcher;
45 import java.util.regex.Pattern;
46
47 import org.junit.jupiter.api.Test;
48 import org.junit.jupiter.api.io.TempDir;
49 import org.mockito.MockedConstruction;
50 import org.mockito.MockedStatic;
51 import org.mockito.Mockito;
52 import org.mockito.internal.util.Checks;
53
54 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
55 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
56 import com.puppycrawl.tools.checkstyle.api.Configuration;
57 import com.puppycrawl.tools.checkstyle.api.Context;
58 import com.puppycrawl.tools.checkstyle.api.DetailAST;
59 import com.puppycrawl.tools.checkstyle.api.FileContents;
60 import com.puppycrawl.tools.checkstyle.api.FileText;
61 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
62 import com.puppycrawl.tools.checkstyle.checks.NoCodeInFileCheck;
63 import com.puppycrawl.tools.checkstyle.checks.coding.EmptyStatementCheck;
64 import com.puppycrawl.tools.checkstyle.checks.coding.HiddenFieldCheck;
65 import com.puppycrawl.tools.checkstyle.checks.design.OneTopLevelClassCheck;
66 import com.puppycrawl.tools.checkstyle.checks.indentation.CommentsIndentationCheck;
67 import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck;
68 import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocParagraphCheck;
69 import com.puppycrawl.tools.checkstyle.checks.naming.ConstantNameCheck;
70 import com.puppycrawl.tools.checkstyle.checks.naming.MemberNameCheck;
71 import com.puppycrawl.tools.checkstyle.checks.naming.ParameterNameCheck;
72 import com.puppycrawl.tools.checkstyle.checks.naming.TypeNameCheck;
73 import com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAfterCheck;
74 import com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAroundCheck;
75 import com.puppycrawl.tools.checkstyle.filters.SuppressWithNearbyCommentFilter;
76 import com.puppycrawl.tools.checkstyle.filters.SuppressionXpathFilter;
77 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
78 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
79
80
81
82
83
84
85
86
87 public class TreeWalkerTest extends AbstractModuleTestSupport {
88
89 @TempDir
90 public File temporaryFolder;
91
92 @Override
93 protected String getPackageLocation() {
94 return "com/puppycrawl/tools/checkstyle/treewalker";
95 }
96
97 @Test
98 public void testProperFileExtension() throws Exception {
99 final String path = getPath("InputTreeWalkerProperFileExtension.java");
100 final String[] expected = {
101 "10:27: " + getCheckMessage(ConstantNameCheck.class,
102 MSG_INVALID_PATTERN, "k", "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"),
103 };
104 verifyWithInlineConfigParserTwice(path, expected);
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 @Test
130 public void testNoAuditEventsWithoutFilters() throws Exception {
131 final String[] expected = {
132 "10:1: " + getCheckMessage(OneTopLevelClassCheck.class,
133 OneTopLevelClassCheck.MSG_KEY, "InputTreeWalkerInner"),
134 };
135 try (MockedConstruction<TreeWalkerAuditEvent> mocked =
136 Mockito.mockConstruction(TreeWalkerAuditEvent.class, (mock, context) -> {
137 throw new CheckstyleException("No audit events expected");
138 })) {
139 verifyWithInlineConfigParserTwice(getPath("InputTreeWalker.java"), expected);
140 }
141 }
142
143
144
145
146
147 @Test
148 public void testConditionRequiredWithoutOrdinaryChecks() throws Exception {
149 final String[] expected = {
150 "7:5: " + getCheckMessage(JavadocParagraphCheck.class,
151 JavadocParagraphCheck.MSG_REDUNDANT_PARAGRAPH),
152 };
153 final String path = getPath("InputTreeWalkerJavadoc.java");
154 final DetailAST mockAst = mock();
155 final DetailAST realAst = JavaParser.parseFile(new File(path),
156 JavaParser.Options.WITH_COMMENTS);
157
158 doThrow(IllegalStateException.class).when(mockAst).getFirstChild();
159 try (MockedStatic<JavaParser> parser = Mockito.mockStatic(JavaParser.class)) {
160 parser.when(() -> JavaParser.parse(any(FileContents.class))).thenReturn(mockAst);
161
162 parser.when(() -> JavaParser.appendHiddenCommentNodes(mockAst)).thenReturn(realAst);
163
164 verifyWithInlineConfigParserTwice(path, expected);
165 }
166 }
167
168
169
170
171
172 @Test
173 public void testConditionRequiredWithoutCommentChecks() throws Exception {
174 final String[] expected = {
175 "10:1: " + getCheckMessage(OneTopLevelClassCheck.class,
176 OneTopLevelClassCheck.MSG_KEY, "InputTreeWalkerInner"),
177 };
178 try (MockedStatic<JavaParser> parser =
179 Mockito.mockStatic(JavaParser.class, CALLS_REAL_METHODS)) {
180
181 parser.when(() -> JavaParser.appendHiddenCommentNodes(any(DetailAST.class)))
182 .thenThrow(IllegalStateException.class);
183
184 verifyWithInlineConfigParserTwice(getPath("InputTreeWalker.java"), expected);
185 }
186 }
187
188 @Test
189 public void testImproperFileExtension() throws Exception {
190 final String regularFilePath = getPath("InputTreeWalkerImproperFileExtension.java");
191 final File originalFile = new File(regularFilePath);
192 final File tempFile = new File(temporaryFolder, "file.pdf");
193 Files.copy(originalFile.toPath(), tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
194 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
195 verifyWithInlineConfigParserTwice(tempFile.getPath(), expected);
196 }
197
198 @Test
199 public void testAcceptableTokens()
200 throws Exception {
201 final DefaultConfiguration checkConfig =
202 createModuleConfig(HiddenFieldCheck.class);
203 checkConfig.addProperty("tokens", "VARIABLE_DEF, ENUM_DEF, CLASS_DEF, METHOD_DEF,"
204 + "IMPORT");
205 try {
206 execute(checkConfig, getPath("InputTreeWalker.java"));
207 assertWithMessage("CheckstyleException is expected").fail();
208 }
209 catch (CheckstyleException exc) {
210 final String errorMsg = exc.getMessage();
211 final Pattern expected = Pattern.compile(Pattern.quote("cannot initialize module"
212 + " com.puppycrawl.tools.checkstyle.TreeWalker - Token ")
213 + "\"(ENUM_DEF|CLASS_DEF|METHOD_DEF|IMPORT)\""
214 + Pattern.quote(" was not found in Acceptable tokens list in check"
215 + " com.puppycrawl.tools.checkstyle.checks.coding.HiddenFieldCheck"));
216
217 final Matcher errorMsgMatcher = expected.matcher(errorMsg);
218 assertWithMessage("Failure for: " + errorMsg)
219 .that(errorMsgMatcher.matches())
220 .isTrue();
221 }
222 }
223
224 @Test
225 public void testOnEmptyFile() throws Exception {
226 final DefaultConfiguration checkConfig = createModuleConfig(HiddenFieldCheck.class);
227 final String uniqueFileName = "file_" + UUID.randomUUID() + ".java";
228 final File emptyFile = new File(temporaryFolder, uniqueFileName);
229 emptyFile.createNewFile();
230 execute(checkConfig, emptyFile.getPath());
231 final long fileSize = Files.size(emptyFile.toPath());
232 assertWithMessage("File should be empty")
233 .that(fileSize)
234 .isEqualTo(0);
235 }
236
237 @Test
238 public void testWithCheckNotHavingTreeWalkerAsParent() throws Exception {
239 final DefaultConfiguration checkConfig = createModuleConfig(JavadocPackageCheck.class);
240
241 try {
242 final String uniqueFileName = "junit_" + UUID.randomUUID() + ".java";
243 final File filePath = new File(temporaryFolder, uniqueFileName);
244 execute(createTreeWalkerConfig(checkConfig), filePath.toString());
245 assertWithMessage("CheckstyleException is expected").fail();
246 }
247 catch (CheckstyleException exception) {
248 assertWithMessage("Error message is unexpected")
249 .that(exception.getMessage())
250 .contains("TreeWalker is not allowed as a parent of");
251 }
252 }
253
254 @Test
255 public void testSetupChildExceptions() {
256 final TreeWalker treeWalker = new TreeWalker();
257 final PackageObjectFactory factory = new PackageObjectFactory(
258 new HashSet<>(), Thread.currentThread().getContextClassLoader());
259 treeWalker.setModuleFactory(factory);
260
261 final Configuration config = new DefaultConfiguration("java.lang.String");
262 try {
263 treeWalker.setupChild(config);
264 assertWithMessage("Exception is expected").fail();
265 }
266 catch (CheckstyleException exc) {
267 assertWithMessage("Error message is not expected")
268 .that(exc.getMessage())
269 .isEqualTo("TreeWalker is not allowed as a parent of java.lang.String "
270 + "Please review 'Parent Module' section for this Check in "
271 + "web documentation if Check is standard.");
272 }
273 }
274
275 @Test
276 public void testSettersForParameters() throws Exception {
277 final TreeWalker treeWalker = new TreeWalker();
278 final DefaultConfiguration config = new DefaultConfiguration("default config");
279 treeWalker.setTabWidth(1);
280 treeWalker.configure(config);
281
282 final int tabWidth = TestUtil.getInternalState(treeWalker, "tabWidth", Integer.class);
283 assertWithMessage("Invalid setter result")
284 .that(tabWidth)
285 .isEqualTo(1);
286 final Object configuration = TestUtil.getInternalState(treeWalker, "configuration",
287 Object.class);
288 assertWithMessage("Invalid configuration")
289 .that(configuration)
290 .isEqualTo(config);
291 }
292
293 @Test
294 public void testForInvalidCheckImplementation() throws Exception {
295 final DefaultConfiguration checkConfig = createModuleConfig(BadJavaDocCheck.class);
296 final String uniqueFileName = "file_" + UUID.randomUUID() + ".java";
297 final File pathToEmptyFile = new File(temporaryFolder, uniqueFileName);
298
299 try {
300 execute(checkConfig, pathToEmptyFile.toString());
301 assertWithMessage("Exception is expected").fail();
302 }
303 catch (CheckstyleException exc) {
304 assertWithMessage("Error message is unexpected")
305 .that(exc.getMessage())
306 .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle."
307 + "TreeWalker - Check 'com.puppycrawl.tools.checkstyle."
308 + "TreeWalkerTest$BadJavaDocCheck' waits for comment type token "
309 + "('SINGLE_LINE_COMMENT') and should override "
310 + "'isCommentNodesRequired()' method to return 'true'");
311 assertWithMessage("Error message is unexpected")
312 .that(exc.getMessage())
313 .contains("isCommentNodesRequired");
314 }
315 }
316
317 @Test
318 public void testProcessNonJavaFiles() throws Exception {
319 final TreeWalker treeWalker = new TreeWalker();
320 final PackageObjectFactory factory = new PackageObjectFactory(
321 new HashSet<>(), Thread.currentThread().getContextClassLoader());
322 treeWalker.setModuleFactory(factory);
323 treeWalker.configure(new DefaultConfiguration("default config"));
324 final DefaultConfiguration childConfig = createModuleConfig(JavadocParagraphCheck.class);
325 treeWalker.setupChild(childConfig);
326 final File file = new File("input.java");
327 final List<String> lines =
328 new ArrayList<>(Arrays.asList("package com.puppycrawl.tools.checkstyle;", "",
329 "error public class InputTreeWalkerFileWithViolation {}"));
330 final FileText fileText = new FileText(file, lines);
331 treeWalker.setFileContents(new FileContents(fileText));
332 try {
333 treeWalker.processFiltered(file, fileText);
334 assertWithMessage("Exception expected").fail();
335 }
336 catch (CheckstyleException exc) {
337 assertWithMessage("Invalid exception message")
338 .that(exc.getMessage())
339 .isEqualTo("IllegalStateException occurred while parsing file input.java.");
340 }
341 }
342
343 @Test
344 public void testProcessNonJavaFilesWithoutException() throws Exception {
345 final TreeWalker treeWalker = new TreeWalker();
346 treeWalker.setTabWidth(1);
347 treeWalker.configure(new DefaultConfiguration("default config"));
348 final File file = new File(getPath("InputTreeWalkerNotJava.xml"));
349 final FileText fileText = new FileText(file, StandardCharsets.ISO_8859_1.name());
350 treeWalker.processFiltered(file, fileText);
351 final Collection<Checks> checks =
352 TestUtil.getInternalStateCollectionChecks(treeWalker, "ordinaryChecks");
353 assertWithMessage("No checks -> No parsing")
354 .that(checks)
355 .isEmpty();
356 }
357
358 @Test
359 public void testWithCacheWithNoViolation() throws Exception {
360 final String path = getPath("InputTreeWalkerWithCacheWithNoViolation.java");
361 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
362 verifyWithInlineConfigParserTwice(path, expected);
363 }
364
365 @Test
366 public void testProcessWithParserThrowable() throws Exception {
367 final TreeWalker treeWalker = new TreeWalker();
368 treeWalker.configure(createModuleConfig(TypeNameCheck.class));
369 final PackageObjectFactory factory = new PackageObjectFactory(
370 new HashSet<>(), Thread.currentThread().getContextClassLoader());
371 treeWalker.setModuleFactory(factory);
372 treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
373 final File file = new File(temporaryFolder, "file.java");
374 final List<String> lines = new ArrayList<>();
375 lines.add(" classD a {} ");
376 final FileText fileText = new FileText(file, lines);
377 treeWalker.setFileContents(new FileContents(fileText));
378 try {
379 treeWalker.processFiltered(file, fileText);
380 assertWithMessage("Exception is expected").fail();
381 }
382 catch (CheckstyleException exception) {
383 assertWithMessage("Error message is unexpected")
384 .that(exception.getMessage())
385 .contains("occurred while parsing file");
386 }
387 }
388
389 @Test
390 public void testProcessWithRecognitionException() throws Exception {
391 final TreeWalker treeWalker = new TreeWalker();
392 treeWalker.configure(createModuleConfig(TypeNameCheck.class));
393 final PackageObjectFactory factory = new PackageObjectFactory(
394 new HashSet<>(), Thread.currentThread().getContextClassLoader());
395 treeWalker.setModuleFactory(factory);
396 treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
397 final File file = new File(temporaryFolder, "file.java");
398 final List<String> lines = new ArrayList<>();
399 lines.add(" class a%$# {} ");
400 final FileText fileText = new FileText(file, lines);
401 treeWalker.setFileContents(new FileContents(fileText));
402 try {
403 treeWalker.processFiltered(file, fileText);
404 assertWithMessage("Exception is expected").fail();
405 }
406 catch (CheckstyleException exception) {
407 assertWithMessage("Error message is unexpected")
408 .that(exception.getMessage())
409 .contains("IllegalStateException occurred while parsing file");
410 }
411 }
412
413 @Test
414 public void testRequiredTokenIsEmptyIntArray() throws Exception {
415 final File file = new File(temporaryFolder, "file.java");
416 try (Writer writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) {
417 final String configComment =
418 """
419
420
421
422
423
424 """;
425 writer.write(configComment);
426 }
427 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
428 verifyWithInlineConfigParserTwice(file.getPath(), expected);
429 }
430
431 @Test
432 public void testBehaviourWithZeroChecks() throws Exception {
433 final TreeWalker treeWalker = new TreeWalker();
434 final PackageObjectFactory factory = new PackageObjectFactory(
435 new HashSet<>(), Thread.currentThread().getContextClassLoader());
436 treeWalker.setModuleFactory(factory);
437
438 final File file = new File(temporaryFolder, "file.java");
439 final FileText fileText = new FileText(file, new ArrayList<>());
440
441 treeWalker.processFiltered(file, fileText);
442 final Collection<Checks> checks =
443 TestUtil.getInternalStateCollectionChecks(treeWalker, "ordinaryChecks");
444 assertWithMessage("No checks -> No parsing")
445 .that(checks)
446 .isEmpty();
447 }
448
449 @Test
450 public void testBehaviourWithOrdinaryAndCommentChecks() throws Exception {
451 final TreeWalker treeWalker = new TreeWalker();
452 treeWalker.configure(createModuleConfig(TypeNameCheck.class));
453 treeWalker.configure(createModuleConfig(CommentsIndentationCheck.class));
454 final PackageObjectFactory factory = new PackageObjectFactory(
455 new HashSet<>(), Thread.currentThread().getContextClassLoader());
456 treeWalker.setModuleFactory(factory);
457 treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
458 treeWalker.setupChild(createModuleConfig(CommentsIndentationCheck.class));
459 final File file = new File(temporaryFolder, "file.java");
460 final List<String> lines = new ArrayList<>();
461 lines.add(" class a%$# {} ");
462 final FileText fileText = new FileText(file, lines);
463 treeWalker.setFileContents(new FileContents(fileText));
464
465 try {
466 treeWalker.processFiltered(file, fileText);
467 assertWithMessage("file is not compilable, exception is expected").fail();
468 }
469 catch (CheckstyleException exception) {
470 final String message = "IllegalStateException occurred while parsing file";
471 assertWithMessage("Error message is unexpected")
472 .that(exception.getMessage())
473 .contains(message);
474 }
475 }
476
477 @Test
478 public void testSetupChild() throws Exception {
479 final TreeWalker treeWalker = new TreeWalker();
480 final PackageObjectFactory factory = new PackageObjectFactory(
481 new HashSet<>(), Thread.currentThread().getContextClassLoader());
482 treeWalker.setModuleFactory(factory);
483 treeWalker.setTabWidth(99);
484 treeWalker.finishLocalSetup();
485
486 final Configuration config = new DefaultConfiguration(
487 XpathFileGeneratorAstFilter.class.getName());
488
489 treeWalker.setupChild(config);
490
491 final Set<TreeWalkerFilter> filters =
492 TestUtil.getInternalStateSetTreeWalkerFilter(treeWalker, "filters");
493 final int tabWidth = TestUtil.getInternalState(filters.iterator().next(),
494 "tabWidth", Integer.class);
495
496 assertWithMessage("expected tab width")
497 .that(tabWidth)
498 .isEqualTo(99);
499 }
500
501 @Test
502 public void testBehaviourWithChecksAndFilters() throws Exception {
503
504 final String[] expected = {
505 "17:17: " + getCheckMessage(MemberNameCheck.class, "name.invalidPattern", "P",
506 "^[a-z][a-zA-Z0-9]*$"),
507 "12:17: " + getCheckMessage(MemberNameCheck.class, "name.invalidPattern", "I",
508 "^[a-z][a-zA-Z0-9]*$"),
509 };
510
511 verifyWithInlineConfigParserTwice(
512 getPath("InputTreeWalkerSuppressionCommentFilter.java"),
513 expected);
514 }
515
516 @Test
517 public void testMultiCheckOrder() throws Exception {
518
519 final String[] expected = {
520 "13:9: " + getCheckMessage(WhitespaceAfterCheck.class, "ws.notFollowed", "if"),
521 "13:9: " + getCheckMessage(WhitespaceAroundCheck.class, "ws.notFollowed", "if"),
522 };
523
524 verifyWithInlineConfigParserTwice(
525 getPath("InputTreeWalkerMultiCheckOrder.java"),
526 expected);
527 }
528
529 @Test
530 public void testMultiCheckOfSameTypeNoIdResultsInOrderingByHash() throws Exception {
531
532 final String[] expected = {
533 "15:28: " + getCheckMessage(ParameterNameCheck.class,
534 "name.invalidPattern", "V2", "^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"),
535 "17:25: " + getCheckMessage(ParameterNameCheck.class,
536 "name.invalidPattern", "b", "^[a-z][a-z0-9][a-zA-Z0-9]*$"),
537 };
538
539 verifyWithInlineConfigParserTwice(
540 getPath("InputTreeWalkerMultiCheckOrder2.java"),
541 expected);
542 }
543
544 @Test
545 public void testFinishLocalSetupFullyInitialized() {
546 final TreeWalker treeWalker = new TreeWalker();
547 treeWalker.setSeverity("error");
548 treeWalker.setTabWidth(100);
549 treeWalker.finishLocalSetup();
550
551 final Context context = TestUtil.getInternalState(treeWalker, "childContext",
552 Context.class);
553 assertWithMessage("Severity differs from expected")
554 .that(context.get("severity"))
555 .isEqualTo("error");
556 assertWithMessage("Tab width differs from expected")
557 .that(context.get("tabWidth"))
558 .isEqualTo(String.valueOf(100));
559 }
560
561 @Test
562 public void testCheckInitIsCalledInTreeWalker() throws Exception {
563 final DefaultConfiguration checkConfig =
564 createModuleConfig(VerifyInitCheck.class);
565 final String uniqueFileName = "file_" + UUID.randomUUID() + ".pdf";
566 final File file = new File(temporaryFolder, uniqueFileName);
567 execute(checkConfig, file.getPath());
568 assertWithMessage("Init was not called")
569 .that(VerifyInitCheck.isInitWasCalled())
570 .isTrue();
571 }
572
573 @Test
574 public void testCheckDestroyIsCalledInTreeWalker() throws Exception {
575 VerifyDestroyCheck.resetDestroyWasCalled();
576 final DefaultConfiguration checkConfig =
577 createModuleConfig(VerifyDestroyCheck.class);
578 final String uniqueFileName = "file_" + UUID.randomUUID() + ".pdf";
579 final File file = new File(temporaryFolder, uniqueFileName);
580 execute(checkConfig, file.getPath());
581 assertWithMessage("Destroy was not called")
582 .that(VerifyDestroyCheck.isDestroyWasCalled())
583 .isTrue();
584 }
585
586 @Test
587 public void testCommentCheckDestroyIsCalledInTreeWalker() throws Exception {
588 VerifyDestroyCheck.resetDestroyWasCalled();
589 final DefaultConfiguration checkConfig =
590 createModuleConfig(VerifyDestroyCommentCheck.class);
591 final String uniqueFileName = "file_" + UUID.randomUUID() + ".pdf";
592 final File file = new File(temporaryFolder, uniqueFileName);
593 execute(checkConfig, file.getPath());
594 assertWithMessage("Destroy was not called")
595 .that(VerifyDestroyCheck.isDestroyWasCalled())
596 .isTrue();
597 }
598
599 @Test
600 public void testCacheWhenFileExternalResourceContentDoesNotChange() throws Exception {
601 final DefaultConfiguration filterConfig = createModuleConfig(SuppressionXpathFilter.class);
602 filterConfig.addProperty("file", getPath("InputTreeWalkerSuppressionXpathFilter.xml"));
603 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
604 treeWalkerConfig.addChild(filterConfig);
605
606 final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
607 final String uniqueFileName1 = "junit_" + UUID.randomUUID() + ".java";
608 final File cacheFile = new File(temporaryFolder, uniqueFileName1);
609 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
610
611 final String uniqueFileName2 = "file_" + UUID.randomUUID() + ".java";
612 final File filePath = new File(temporaryFolder, uniqueFileName2);
613
614 execute(checkerConfig, filePath.toString());
615
616 execute(checkerConfig, filePath.toString());
617
618 assertWithMessage("External resource is not present in cache")
619 .that(Files.readString(cacheFile.toPath()))
620 .contains("InputTreeWalkerSuppressionXpathFilter.xml");
621 }
622
623 @Test
624 public void testTreeWalkerFilterAbsolutePath() throws Exception {
625
626 final String filePath = "src/test/resources/" + getPackageLocation()
627 + "/InputTreeWalkerSuppressionXpathFilterAbsolute.java";
628
629 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
630 verifyWithInlineConfigParserTwice(filePath, expected);
631 }
632
633 @Test
634 public void testExternalResourceFiltersWithNoExternalResource() throws Exception {
635 final DefaultConfiguration checkConfig = createModuleConfig(EmptyStatementCheck.class);
636 final DefaultConfiguration filterConfig =
637 createModuleConfig(SuppressWithNearbyCommentFilter.class);
638 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
639 treeWalkerConfig.addChild(checkConfig);
640 treeWalkerConfig.addChild(filterConfig);
641
642 final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
643 final String uniqueFileName1 = "junit_" + UUID.randomUUID() + ".java";
644 final File cacheFile = new File(temporaryFolder, uniqueFileName1);
645 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
646 final String uniqueFileName2 = "junit_" + UUID.randomUUID() + ".java";
647 final File filePath = new File(temporaryFolder, uniqueFileName2);
648
649 execute(checkerConfig, filePath.toString());
650
651 final long cacheSize = Files.size(cacheFile.toPath());
652 assertWithMessage("cacheFile should not be empty")
653 .that(cacheSize)
654 .isNotEqualTo(0);
655 }
656
657
658
659
660
661
662 @Test
663 public void testOrderOfCheckExecution() throws Exception {
664
665 final DefaultConfiguration configuration1 = createModuleConfig(AaCheck.class);
666 configuration1.addProperty("id", "2");
667 final DefaultConfiguration configuration2 = createModuleConfig(BbCheck.class);
668 configuration2.addProperty("id", "1");
669
670 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
671 treeWalkerConfig.addChild(configuration2);
672 treeWalkerConfig.addChild(configuration1);
673
674 final List<File> files =
675 Collections.singletonList(new File(getPath("InputTreeWalker2.java")));
676 final Checker checker = createChecker(treeWalkerConfig);
677
678 try {
679 checker.process(files);
680 assertWithMessage("exception is expected").fail();
681 }
682 catch (CheckstyleException exception) {
683 assertWithMessage("wrong order of Check executions")
684 .that(exception.getCause().getMessage())
685 .isEqualTo(AaCheck.class.toString());
686 }
687 }
688
689 @Test
690 public void testSkipFileOnJavaParseExceptionTrue() throws Exception {
691 final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
692 config.addProperty("skipFileOnJavaParseException", "true");
693 config.addProperty("javaParseExceptionSeverity", "ignore");
694 config.addChild(createModuleConfig(ConstantNameCheck.class));
695
696 final File[] files = {
697 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException.java")),
698 new File(getPath("InputTreeWalkerProperFileExtension.java")),
699 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException2.java")),
700 };
701
702 final Checker checker = createChecker(config);
703 final Map<String, List<String>> expectedViolation = new HashMap<>();
704 expectedViolation.put(getPath("InputTreeWalkerProperFileExtension.java"),
705 Collections.singletonList(
706 "10:27: " + getCheckMessage(ConstantNameCheck.class,
707 MSG_INVALID_PATTERN, "k", "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$")));
708 verify(checker, files, expectedViolation);
709 }
710
711
712
713
714
715
716
717
718
719
720 @Test
721 public void testSkipFileOnJavaParseExceptionFalse() throws Exception {
722 final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
723 config.addProperty("skipFileOnJavaParseException", "false");
724 config.addChild(createModuleConfig(ConstantNameCheck.class));
725
726 final String[] files = {
727 getNonCompilablePath("InputTreeWalkerSkipParsingException2.java"),
728 getPath("InputTreeWalkerProperFileExtension.java"),
729 getNonCompilablePath("InputTreeWalkerSkipParsingException.java"),
730 };
731 final Exception ex = TestUtil.getExpectedThrowable(CheckstyleException.class,
732 () -> execute(config, files),
733 "Exception is expected");
734 assertWithMessage("Error message is unexpected")
735 .that(ex.getMessage())
736 .contains("Exception was thrown while processing");
737 }
738
739 @Test
740 public void testSkipFileOnJavaParseExceptionConfigSeverityIgnore() throws Exception {
741 final String path =
742 getNonCompilablePath(
743 "InputTreeWalkerSkipParsingExceptionConfigSeverityIgnore.java");
744 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
745 verifyWithInlineXmlConfig(path, expected);
746 }
747
748 @Test
749 public void testSkipFileOnJavaParseExceptionConfigSeverityDefault() throws Exception {
750 final String path =
751 getNonCompilablePath(
752 "InputTreeWalkerSkipParsingExceptionConfigSeverityDefault.java");
753 final String[] expected = {
754 "1: " + getCheckMessage(TreeWalker.PARSE_EXCEPTION_MSG, "IllegalStateException")
755 + " occurred while parsing file " + path + ".",
756 };
757 verifyWithInlineXmlConfig(path, expected);
758 }
759
760 @Test
761 public void testSkipFileOnJavaParseExceptionSkipChecks() throws Exception {
762 final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
763 config.addProperty("skipFileOnJavaParseException", "true");
764 config.addProperty("javaParseExceptionSeverity", "ignore");
765 config.addChild(createModuleConfig(NoCodeInFileCheck.class));
766
767 final Checker checker = createChecker(config);
768
769 final File[] files = {
770 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException.java")),
771 new File(getPath("InputTreeWalkerProperFileExtension.java")),
772 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException2.java")),
773 };
774 final Map<String, List<String>> expectedViolation = new HashMap<>();
775 expectedViolation.put(getPath("InputTreeWalkerProperFileExtension.java"),
776 new ArrayList<>());
777
778 verify(checker, files, expectedViolation);
779 }
780
781 @Test
782 public void testJavaParseExceptionSeverityDefaultError() throws Exception {
783 final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
784 config.addProperty("skipFileOnJavaParseException", "true");
785 config.addChild(createModuleConfig(NoCodeInFileCheck.class));
786
787 final Checker checker = createChecker(config);
788
789 final File[] files = {
790 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException.java")),
791 new File(getPath("InputTreeWalkerProperFileExtension.java")),
792 };
793
794 final Map<String, List<String>> expectedViolation = new HashMap<>();
795
796 expectedViolation.put(getPath("InputTreeWalkerProperFileExtension.java"),
797 new ArrayList<>());
798 expectedViolation.put(getNonCompilablePath("InputTreeWalkerSkipParsingException.java"),
799 List.of("1: Java specific (TreeWalker-based) modules are skipped due to an "
800 + "exception during parsing - "
801 + "IllegalStateException occurred while parsing file "
802 + getNonCompilablePath("InputTreeWalkerSkipParsingException.java") + "."));
803
804 verify(checker, files, expectedViolation);
805 }
806
807 public static class BadJavaDocCheck extends AbstractCheck {
808
809 @Override
810 public int[] getDefaultTokens() {
811 return getAcceptableTokens();
812 }
813
814 @Override
815 public int[] getAcceptableTokens() {
816 return new int[] {TokenTypes.SINGLE_LINE_COMMENT};
817 }
818
819 @Override
820 public int[] getRequiredTokens() {
821 return getAcceptableTokens();
822 }
823
824 }
825
826 public static class VerifyInitCheck extends AbstractCheck {
827
828 private static boolean initWasCalled;
829
830 @Override
831 public int[] getDefaultTokens() {
832 return CommonUtil.EMPTY_INT_ARRAY;
833 }
834
835 @Override
836 public int[] getAcceptableTokens() {
837 return getDefaultTokens();
838 }
839
840 @Override
841 public int[] getRequiredTokens() {
842 return getDefaultTokens();
843 }
844
845 @Override
846 public void init() {
847 super.init();
848 initWasCalled = true;
849 }
850
851 public static boolean isInitWasCalled() {
852 return initWasCalled;
853 }
854
855 }
856
857 public static class VerifyDestroyCheck extends AbstractCheck {
858
859 private static boolean destroyWasCalled;
860
861 @Override
862 public int[] getDefaultTokens() {
863 return CommonUtil.EMPTY_INT_ARRAY;
864 }
865
866 @Override
867 public int[] getAcceptableTokens() {
868 return getDefaultTokens();
869 }
870
871 @Override
872 public int[] getRequiredTokens() {
873 return getDefaultTokens();
874 }
875
876 @Override
877 public void destroy() {
878 super.destroy();
879 destroyWasCalled = true;
880 }
881
882 public static void resetDestroyWasCalled() {
883 destroyWasCalled = false;
884 }
885
886 public static boolean isDestroyWasCalled() {
887 return destroyWasCalled;
888 }
889
890 }
891
892 public static class VerifyDestroyCommentCheck extends VerifyDestroyCheck {
893
894 @Override
895 public boolean isCommentNodesRequired() {
896 return true;
897 }
898
899 }
900
901 public static class AaCheck extends AbstractCheck {
902
903 @Override
904 public int[] getDefaultTokens() {
905 return new int[0];
906 }
907
908 @Override
909 public int[] getAcceptableTokens() {
910 return new int[0];
911 }
912
913 @Override
914 public int[] getRequiredTokens() {
915 return new int[0];
916 }
917
918 @Override
919 public void beginTree(DetailAST rootAST) {
920 throw new IllegalStateException(AaCheck.class.toString());
921 }
922
923 }
924
925 public static class BbCheck extends AbstractCheck {
926
927 @Override
928 public int[] getDefaultTokens() {
929 return new int[0];
930 }
931
932 @Override
933 public int[] getAcceptableTokens() {
934 return new int[0];
935 }
936
937 @Override
938 public int[] getRequiredTokens() {
939 return new int[0];
940 }
941
942 @Override
943 public void beginTree(DetailAST rootAST) {
944 throw new IllegalStateException(BbCheck.class.toString());
945 }
946
947 }
948
949 public static class RequiredTokenIsEmptyIntArray extends AbstractCheck {
950
951 @Override
952 public int[] getRequiredTokens() {
953 return CommonUtil.EMPTY_INT_ARRAY;
954 }
955
956 @Override
957 public int[] getDefaultTokens() {
958 return new int[] {TokenTypes.ANNOTATION};
959 }
960
961 @Override
962 public int[] getAcceptableTokens() {
963 return CommonUtil.EMPTY_INT_ARRAY;
964 }
965
966 }
967
968 }