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 ex) {
210 final String errorMsg = ex.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 ex) {
267 assertWithMessage("Error message is not expected")
268 .that(ex.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");
283 assertWithMessage("Invalid setter result")
284 .that(tabWidth)
285 .isEqualTo(1);
286 final Object configuration = TestUtil.getInternalState(treeWalker, "configuration");
287 assertWithMessage("Invalid configuration")
288 .that(configuration)
289 .isEqualTo(config);
290 }
291
292 @Test
293 public void testForInvalidCheckImplementation() throws Exception {
294 final DefaultConfiguration checkConfig = createModuleConfig(BadJavaDocCheck.class);
295 final String uniqueFileName = "file_" + UUID.randomUUID() + ".java";
296 final File pathToEmptyFile = new File(temporaryFolder, uniqueFileName);
297
298 try {
299 execute(checkConfig, pathToEmptyFile.toString());
300 assertWithMessage("Exception is expected").fail();
301 }
302 catch (CheckstyleException ex) {
303 assertWithMessage("Error message is unexpected")
304 .that(ex.getMessage())
305 .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle."
306 + "TreeWalker - Check 'com.puppycrawl.tools.checkstyle."
307 + "TreeWalkerTest$BadJavaDocCheck' waits for comment type token "
308 + "('SINGLE_LINE_COMMENT') and should override "
309 + "'isCommentNodesRequired()' method to return 'true'");
310 assertWithMessage("Error message is unexpected")
311 .that(ex.getMessage())
312 .contains("isCommentNodesRequired");
313 }
314 }
315
316 @Test
317 public void testProcessNonJavaFiles() throws Exception {
318 final TreeWalker treeWalker = new TreeWalker();
319 final PackageObjectFactory factory = new PackageObjectFactory(
320 new HashSet<>(), Thread.currentThread().getContextClassLoader());
321 treeWalker.setModuleFactory(factory);
322 treeWalker.configure(new DefaultConfiguration("default config"));
323 final DefaultConfiguration childConfig = createModuleConfig(JavadocParagraphCheck.class);
324 treeWalker.setupChild(childConfig);
325 final File file = new File("input.java");
326 final List<String> lines =
327 new ArrayList<>(Arrays.asList("package com.puppycrawl.tools.checkstyle;", "",
328 "error public class InputTreeWalkerFileWithViolation {}"));
329 final FileText fileText = new FileText(file, lines);
330 treeWalker.setFileContents(new FileContents(fileText));
331 try {
332 treeWalker.processFiltered(file, fileText);
333 assertWithMessage("Exception expected").fail();
334 }
335 catch (CheckstyleException ex) {
336 assertWithMessage("Invalid exception message")
337 .that(ex.getMessage())
338 .isEqualTo("IllegalStateException occurred while parsing file input.java.");
339 }
340 }
341
342 @Test
343 public void testProcessNonJavaFilesWithoutException() throws Exception {
344 final TreeWalker treeWalker = new TreeWalker();
345 treeWalker.setTabWidth(1);
346 treeWalker.configure(new DefaultConfiguration("default config"));
347 final File file = new File(getPath("InputTreeWalkerNotJava.xml"));
348 final FileText fileText = new FileText(file, StandardCharsets.ISO_8859_1.name());
349 treeWalker.processFiltered(file, fileText);
350 final Collection<Checks> checks = TestUtil.getInternalState(treeWalker, "ordinaryChecks");
351 assertWithMessage("No checks -> No parsing")
352 .that(checks)
353 .isEmpty();
354 }
355
356 @Test
357 public void testWithCacheWithNoViolation() throws Exception {
358 final String path = getPath("InputTreeWalkerWithCacheWithNoViolation.java");
359 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
360 verifyWithInlineConfigParserTwice(path, expected);
361 }
362
363 @Test
364 public void testProcessWithParserThrowable() throws Exception {
365 final TreeWalker treeWalker = new TreeWalker();
366 treeWalker.configure(createModuleConfig(TypeNameCheck.class));
367 final PackageObjectFactory factory = new PackageObjectFactory(
368 new HashSet<>(), Thread.currentThread().getContextClassLoader());
369 treeWalker.setModuleFactory(factory);
370 treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
371 final File file = new File(temporaryFolder, "file.java");
372 final List<String> lines = new ArrayList<>();
373 lines.add(" classD a {} ");
374 final FileText fileText = new FileText(file, lines);
375 treeWalker.setFileContents(new FileContents(fileText));
376 try {
377 treeWalker.processFiltered(file, fileText);
378 assertWithMessage("Exception is expected").fail();
379 }
380 catch (CheckstyleException exception) {
381 assertWithMessage("Error message is unexpected")
382 .that(exception.getMessage())
383 .contains("occurred while parsing file");
384 }
385 }
386
387 @Test
388 public void testProcessWithRecognitionException() throws Exception {
389 final TreeWalker treeWalker = new TreeWalker();
390 treeWalker.configure(createModuleConfig(TypeNameCheck.class));
391 final PackageObjectFactory factory = new PackageObjectFactory(
392 new HashSet<>(), Thread.currentThread().getContextClassLoader());
393 treeWalker.setModuleFactory(factory);
394 treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
395 final File file = new File(temporaryFolder, "file.java");
396 final List<String> lines = new ArrayList<>();
397 lines.add(" class a%$# {} ");
398 final FileText fileText = new FileText(file, lines);
399 treeWalker.setFileContents(new FileContents(fileText));
400 try {
401 treeWalker.processFiltered(file, fileText);
402 assertWithMessage("Exception is expected").fail();
403 }
404 catch (CheckstyleException exception) {
405 assertWithMessage("Error message is unexpected")
406 .that(exception.getMessage())
407 .contains("IllegalStateException occurred while parsing file");
408 }
409 }
410
411 @Test
412 public void testRequiredTokenIsEmptyIntArray() throws Exception {
413 final File file = new File(temporaryFolder, "file.java");
414 try (Writer writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) {
415 final String configComment = "/*\n"
416 + "com.puppycrawl.tools.checkstyle.TreeWalkerTest"
417 + "$RequiredTokenIsEmptyIntArray\n\n"
418 + "*/";
419 writer.write(configComment);
420 }
421 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
422 verifyWithInlineConfigParserTwice(file.getPath(), expected);
423 }
424
425 @Test
426 public void testBehaviourWithZeroChecks() throws Exception {
427 final TreeWalker treeWalker = new TreeWalker();
428 final PackageObjectFactory factory = new PackageObjectFactory(
429 new HashSet<>(), Thread.currentThread().getContextClassLoader());
430 treeWalker.setModuleFactory(factory);
431
432 final File file = new File(temporaryFolder, "file.java");
433 final FileText fileText = new FileText(file, new ArrayList<>());
434
435 treeWalker.processFiltered(file, fileText);
436 final Collection<Checks> checks = TestUtil.getInternalState(treeWalker, "ordinaryChecks");
437 assertWithMessage("No checks -> No parsing")
438 .that(checks)
439 .isEmpty();
440 }
441
442 @Test
443 public void testBehaviourWithOrdinaryAndCommentChecks() throws Exception {
444 final TreeWalker treeWalker = new TreeWalker();
445 treeWalker.configure(createModuleConfig(TypeNameCheck.class));
446 treeWalker.configure(createModuleConfig(CommentsIndentationCheck.class));
447 final PackageObjectFactory factory = new PackageObjectFactory(
448 new HashSet<>(), Thread.currentThread().getContextClassLoader());
449 treeWalker.setModuleFactory(factory);
450 treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
451 treeWalker.setupChild(createModuleConfig(CommentsIndentationCheck.class));
452 final File file = new File(temporaryFolder, "file.java");
453 final List<String> lines = new ArrayList<>();
454 lines.add(" class a%$# {} ");
455 final FileText fileText = new FileText(file, lines);
456 treeWalker.setFileContents(new FileContents(fileText));
457
458 try {
459 treeWalker.processFiltered(file, fileText);
460 assertWithMessage("file is not compilable, exception is expected").fail();
461 }
462 catch (CheckstyleException exception) {
463 final String message = "IllegalStateException occurred while parsing file";
464 assertWithMessage("Error message is unexpected")
465 .that(exception.getMessage())
466 .contains(message);
467 }
468 }
469
470 @Test
471 public void testSetupChild() throws Exception {
472 final TreeWalker treeWalker = new TreeWalker();
473 final PackageObjectFactory factory = new PackageObjectFactory(
474 new HashSet<>(), Thread.currentThread().getContextClassLoader());
475 treeWalker.setModuleFactory(factory);
476 treeWalker.setTabWidth(99);
477 treeWalker.finishLocalSetup();
478
479 final Configuration config = new DefaultConfiguration(
480 XpathFileGeneratorAstFilter.class.getName());
481
482 treeWalker.setupChild(config);
483
484 final Set<TreeWalkerFilter> filters = TestUtil.getInternalState(treeWalker, "filters");
485 final int tabWidth = TestUtil.getInternalState(filters.iterator().next(), "tabWidth");
486
487 assertWithMessage("expected tab width")
488 .that(tabWidth)
489 .isEqualTo(99);
490 }
491
492 @Test
493 public void testBehaviourWithChecksAndFilters() throws Exception {
494
495 final String[] expected = {
496 "17:17: " + getCheckMessage(MemberNameCheck.class, "name.invalidPattern", "P",
497 "^[a-z][a-zA-Z0-9]*$"),
498 "12:17: " + getCheckMessage(MemberNameCheck.class, "name.invalidPattern", "I",
499 "^[a-z][a-zA-Z0-9]*$"),
500 };
501
502 verifyWithInlineConfigParserTwice(
503 getPath("InputTreeWalkerSuppressionCommentFilter.java"),
504 expected);
505 }
506
507 @Test
508 public void testMultiCheckOrder() throws Exception {
509
510 final String[] expected = {
511 "13:9: " + getCheckMessage(WhitespaceAfterCheck.class, "ws.notFollowed", "if"),
512 "13:9: " + getCheckMessage(WhitespaceAroundCheck.class, "ws.notFollowed", "if"),
513 };
514
515 verifyWithInlineConfigParserTwice(
516 getPath("InputTreeWalkerMultiCheckOrder.java"),
517 expected);
518 }
519
520 @Test
521 public void testMultiCheckOfSameTypeNoIdResultsInOrderingByHash() throws Exception {
522
523 final String[] expected = {
524 "15:28: " + getCheckMessage(ParameterNameCheck.class,
525 "name.invalidPattern", "V2", "^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"),
526 "17:25: " + getCheckMessage(ParameterNameCheck.class,
527 "name.invalidPattern", "b", "^[a-z][a-z0-9][a-zA-Z0-9]*$"),
528 };
529
530 verifyWithInlineConfigParserTwice(
531 getPath("InputTreeWalkerMultiCheckOrder2.java"),
532 expected);
533 }
534
535 @Test
536 public void testFinishLocalSetupFullyInitialized() {
537 final TreeWalker treeWalker = new TreeWalker();
538 treeWalker.setSeverity("error");
539 treeWalker.setTabWidth(100);
540 treeWalker.finishLocalSetup();
541
542 final Context context = TestUtil.getInternalState(treeWalker, "childContext");
543 assertWithMessage("Severity differs from expected")
544 .that(context.get("severity"))
545 .isEqualTo("error");
546 assertWithMessage("Tab width differs from expected")
547 .that(context.get("tabWidth"))
548 .isEqualTo(String.valueOf(100));
549 }
550
551 @Test
552 public void testCheckInitIsCalledInTreeWalker() throws Exception {
553 final DefaultConfiguration checkConfig =
554 createModuleConfig(VerifyInitCheck.class);
555 final String uniqueFileName = "file_" + UUID.randomUUID() + ".pdf";
556 final File file = new File(temporaryFolder, uniqueFileName);
557 execute(checkConfig, file.getPath());
558 assertWithMessage("Init was not called")
559 .that(VerifyInitCheck.isInitWasCalled())
560 .isTrue();
561 }
562
563 @Test
564 public void testCheckDestroyIsCalledInTreeWalker() throws Exception {
565 VerifyDestroyCheck.resetDestroyWasCalled();
566 final DefaultConfiguration checkConfig =
567 createModuleConfig(VerifyDestroyCheck.class);
568 final String uniqueFileName = "file_" + UUID.randomUUID() + ".pdf";
569 final File file = new File(temporaryFolder, uniqueFileName);
570 execute(checkConfig, file.getPath());
571 assertWithMessage("Destroy was not called")
572 .that(VerifyDestroyCheck.isDestroyWasCalled())
573 .isTrue();
574 }
575
576 @Test
577 public void testCommentCheckDestroyIsCalledInTreeWalker() throws Exception {
578 VerifyDestroyCheck.resetDestroyWasCalled();
579 final DefaultConfiguration checkConfig =
580 createModuleConfig(VerifyDestroyCommentCheck.class);
581 final String uniqueFileName = "file_" + UUID.randomUUID() + ".pdf";
582 final File file = new File(temporaryFolder, uniqueFileName);
583 execute(checkConfig, file.getPath());
584 assertWithMessage("Destroy was not called")
585 .that(VerifyDestroyCheck.isDestroyWasCalled())
586 .isTrue();
587 }
588
589 @Test
590 public void testCacheWhenFileExternalResourceContentDoesNotChange() throws Exception {
591 final DefaultConfiguration filterConfig = createModuleConfig(SuppressionXpathFilter.class);
592 filterConfig.addProperty("file", getPath("InputTreeWalkerSuppressionXpathFilter.xml"));
593 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
594 treeWalkerConfig.addChild(filterConfig);
595
596 final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
597 final String uniqueFileName1 = "junit_" + UUID.randomUUID() + ".java";
598 final File cacheFile = new File(temporaryFolder, uniqueFileName1);
599 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
600
601 final String uniqueFileName2 = "file_" + UUID.randomUUID() + ".java";
602 final File filePath = new File(temporaryFolder, uniqueFileName2);
603
604 execute(checkerConfig, filePath.toString());
605
606 execute(checkerConfig, filePath.toString());
607
608 assertWithMessage("External resource is not present in cache")
609 .that(Files.readString(cacheFile.toPath()))
610 .contains("InputTreeWalkerSuppressionXpathFilter.xml");
611 }
612
613 @Test
614 public void testTreeWalkerFilterAbsolutePath() throws Exception {
615
616 final String filePath = "src/test/resources/" + getPackageLocation()
617 + "/InputTreeWalkerSuppressionXpathFilterAbsolute.java";
618
619 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
620 verifyWithInlineConfigParserTwice(filePath, expected);
621 }
622
623 @Test
624 public void testExternalResourceFiltersWithNoExternalResource() throws Exception {
625 final DefaultConfiguration checkConfig = createModuleConfig(EmptyStatementCheck.class);
626 final DefaultConfiguration filterConfig =
627 createModuleConfig(SuppressWithNearbyCommentFilter.class);
628 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
629 treeWalkerConfig.addChild(checkConfig);
630 treeWalkerConfig.addChild(filterConfig);
631
632 final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
633 final String uniqueFileName1 = "junit_" + UUID.randomUUID() + ".java";
634 final File cacheFile = new File(temporaryFolder, uniqueFileName1);
635 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
636 final String uniqueFileName2 = "junit_" + UUID.randomUUID() + ".java";
637 final File filePath = new File(temporaryFolder, uniqueFileName2);
638
639 execute(checkerConfig, filePath.toString());
640
641 final long cacheSize = Files.size(cacheFile.toPath());
642 assertWithMessage("cacheFile should not be empty")
643 .that(cacheSize)
644 .isNotEqualTo(0);
645 }
646
647
648
649
650
651
652 @Test
653 public void testOrderOfCheckExecution() throws Exception {
654
655 final DefaultConfiguration configuration1 = createModuleConfig(AaCheck.class);
656 configuration1.addProperty("id", "2");
657 final DefaultConfiguration configuration2 = createModuleConfig(BbCheck.class);
658 configuration2.addProperty("id", "1");
659
660 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
661 treeWalkerConfig.addChild(configuration2);
662 treeWalkerConfig.addChild(configuration1);
663
664 final List<File> files =
665 Collections.singletonList(new File(getPath("InputTreeWalker2.java")));
666 final Checker checker = createChecker(treeWalkerConfig);
667
668 try {
669 checker.process(files);
670 assertWithMessage("exception is expected").fail();
671 }
672 catch (CheckstyleException exception) {
673 assertWithMessage("wrong order of Check executions")
674 .that(exception.getCause().getMessage())
675 .isEqualTo(AaCheck.class.toString());
676 }
677 }
678
679 @Test
680 public void testSkipFileOnJavaParseExceptionTrue() throws Exception {
681 final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
682 config.addProperty("skipFileOnJavaParseException", "true");
683 config.addProperty("javaParseExceptionSeverity", "ignore");
684 config.addChild(createModuleConfig(ConstantNameCheck.class));
685
686 final File[] files = {
687 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException.java")),
688 new File(getPath("InputTreeWalkerProperFileExtension.java")),
689 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException2.java")),
690 };
691
692 final Checker checker = createChecker(config);
693 final Map<String, List<String>> expectedViolation = new HashMap<>();
694 expectedViolation.put(getPath("InputTreeWalkerProperFileExtension.java"),
695 Collections.singletonList(
696 "10:27: " + getCheckMessage(ConstantNameCheck.class,
697 MSG_INVALID_PATTERN, "k", "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$")));
698 verify(checker, files, expectedViolation);
699 }
700
701
702
703
704
705
706
707
708
709
710 @Test
711 public void testSkipFileOnJavaParseExceptionFalse() throws Exception {
712 final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
713 config.addProperty("skipFileOnJavaParseException", "false");
714 config.addChild(createModuleConfig(ConstantNameCheck.class));
715
716 final String[] files = {
717 getNonCompilablePath("InputTreeWalkerSkipParsingException2.java"),
718 getPath("InputTreeWalkerProperFileExtension.java"),
719 getNonCompilablePath("InputTreeWalkerSkipParsingException.java"),
720 };
721 final Exception ex = TestUtil.getExpectedThrowable(CheckstyleException.class,
722 () -> execute(config, files),
723 "Exception is expected");
724 assertWithMessage("Error message is unexpected")
725 .that(ex.getMessage())
726 .contains("Exception was thrown while processing");
727 }
728
729 @Test
730 public void testSkipFileOnJavaParseExceptionConfigSeverityIgnore() throws Exception {
731 final String path =
732 getNonCompilablePath(
733 "InputTreeWalkerSkipParsingExceptionConfigSeverityIgnore.java");
734 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
735 verifyWithInlineXmlConfig(path, expected);
736 }
737
738 @Test
739 public void testSkipFileOnJavaParseExceptionConfigSeverityDefault() throws Exception {
740 final String path =
741 getNonCompilablePath(
742 "InputTreeWalkerSkipParsingExceptionConfigSeverityDefault.java");
743 final String[] expected = {
744 "1: " + getCheckMessage(TreeWalker.PARSE_EXCEPTION_MSG, "IllegalStateException")
745 + " occurred while parsing file " + path + ".",
746 };
747 verifyWithInlineXmlConfig(path, expected);
748 }
749
750 @Test
751 public void testSkipFileOnJavaParseExceptionSkipChecks() throws Exception {
752 final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
753 config.addProperty("skipFileOnJavaParseException", "true");
754 config.addProperty("javaParseExceptionSeverity", "ignore");
755 config.addChild(createModuleConfig(NoCodeInFileCheck.class));
756
757 final Checker checker = createChecker(config);
758
759 final File[] files = {
760 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException.java")),
761 new File(getPath("InputTreeWalkerProperFileExtension.java")),
762 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException2.java")),
763 };
764 final Map<String, List<String>> expectedViolation = new HashMap<>();
765 expectedViolation.put(getPath("InputTreeWalkerProperFileExtension.java"),
766 new ArrayList<>());
767
768 verify(checker, files, expectedViolation);
769 }
770
771 @Test
772 public void testJavaParseExceptionSeverityDefaultError() throws Exception {
773 final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
774 config.addProperty("skipFileOnJavaParseException", "true");
775 config.addChild(createModuleConfig(NoCodeInFileCheck.class));
776
777 final Checker checker = createChecker(config);
778
779 final File[] files = {
780 new File(getNonCompilablePath("InputTreeWalkerSkipParsingException.java")),
781 new File(getPath("InputTreeWalkerProperFileExtension.java")),
782 };
783
784 final Map<String, List<String>> expectedViolation = new HashMap<>();
785
786 expectedViolation.put(getPath("InputTreeWalkerProperFileExtension.java"),
787 new ArrayList<>());
788 expectedViolation.put(getNonCompilablePath("InputTreeWalkerSkipParsingException.java"),
789 List.of("1: Java specific (TreeWalker-based) modules are skipped due to an "
790 + "exception during parsing - "
791 + "IllegalStateException occurred while parsing file "
792 + getNonCompilablePath("InputTreeWalkerSkipParsingException.java") + "."));
793
794 verify(checker, files, expectedViolation);
795 }
796
797 public static class BadJavaDocCheck extends AbstractCheck {
798
799 @Override
800 public int[] getDefaultTokens() {
801 return getAcceptableTokens();
802 }
803
804 @Override
805 public int[] getAcceptableTokens() {
806 return new int[] {TokenTypes.SINGLE_LINE_COMMENT};
807 }
808
809 @Override
810 public int[] getRequiredTokens() {
811 return getAcceptableTokens();
812 }
813
814 }
815
816 public static class VerifyInitCheck extends AbstractCheck {
817
818 private static boolean initWasCalled;
819
820 @Override
821 public int[] getDefaultTokens() {
822 return CommonUtil.EMPTY_INT_ARRAY;
823 }
824
825 @Override
826 public int[] getAcceptableTokens() {
827 return getDefaultTokens();
828 }
829
830 @Override
831 public int[] getRequiredTokens() {
832 return getDefaultTokens();
833 }
834
835 @Override
836 public void init() {
837 super.init();
838 initWasCalled = true;
839 }
840
841 public static boolean isInitWasCalled() {
842 return initWasCalled;
843 }
844
845 }
846
847 public static class VerifyDestroyCheck extends AbstractCheck {
848
849 private static boolean destroyWasCalled;
850
851 @Override
852 public int[] getDefaultTokens() {
853 return CommonUtil.EMPTY_INT_ARRAY;
854 }
855
856 @Override
857 public int[] getAcceptableTokens() {
858 return getDefaultTokens();
859 }
860
861 @Override
862 public int[] getRequiredTokens() {
863 return getDefaultTokens();
864 }
865
866 @Override
867 public void destroy() {
868 super.destroy();
869 destroyWasCalled = true;
870 }
871
872 public static void resetDestroyWasCalled() {
873 destroyWasCalled = false;
874 }
875
876 public static boolean isDestroyWasCalled() {
877 return destroyWasCalled;
878 }
879
880 }
881
882 public static class VerifyDestroyCommentCheck extends VerifyDestroyCheck {
883
884 @Override
885 public boolean isCommentNodesRequired() {
886 return true;
887 }
888
889 }
890
891 public static class AaCheck extends AbstractCheck {
892
893 @Override
894 public int[] getDefaultTokens() {
895 return new int[0];
896 }
897
898 @Override
899 public int[] getAcceptableTokens() {
900 return new int[0];
901 }
902
903 @Override
904 public int[] getRequiredTokens() {
905 return new int[0];
906 }
907
908 @Override
909 public void beginTree(DetailAST rootAST) {
910 throw new IllegalStateException(AaCheck.class.toString());
911 }
912
913 }
914
915 public static class BbCheck extends AbstractCheck {
916
917 @Override
918 public int[] getDefaultTokens() {
919 return new int[0];
920 }
921
922 @Override
923 public int[] getAcceptableTokens() {
924 return new int[0];
925 }
926
927 @Override
928 public int[] getRequiredTokens() {
929 return new int[0];
930 }
931
932 @Override
933 public void beginTree(DetailAST rootAST) {
934 throw new IllegalStateException(BbCheck.class.toString());
935 }
936
937 }
938
939 public static class RequiredTokenIsEmptyIntArray extends AbstractCheck {
940
941 @Override
942 public int[] getRequiredTokens() {
943 return CommonUtil.EMPTY_INT_ARRAY;
944 }
945
946 @Override
947 public int[] getDefaultTokens() {
948 return new int[] {TokenTypes.ANNOTATION};
949 }
950
951 @Override
952 public int[] getAcceptableTokens() {
953 return CommonUtil.EMPTY_INT_ARRAY;
954 }
955
956 }
957
958 }