View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2018 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle;
21  
22  import static com.puppycrawl.tools.checkstyle.checks.naming.AbstractNameCheck.MSG_INVALID_PATTERN;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertTrue;
25  import static org.junit.Assert.fail;
26  
27  import java.io.BufferedWriter;
28  import java.io.File;
29  import java.io.FileOutputStream;
30  import java.io.OutputStreamWriter;
31  import java.io.Writer;
32  import java.nio.charset.StandardCharsets;
33  import java.nio.file.Files;
34  import java.util.ArrayList;
35  import java.util.Arrays;
36  import java.util.Collection;
37  import java.util.HashSet;
38  import java.util.List;
39  import java.util.regex.Matcher;
40  import java.util.regex.Pattern;
41  
42  import org.junit.Rule;
43  import org.junit.Test;
44  import org.junit.rules.TemporaryFolder;
45  import org.mockito.internal.util.Checks;
46  import org.powermock.reflect.Whitebox;
47  
48  import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
49  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
50  import com.puppycrawl.tools.checkstyle.api.Configuration;
51  import com.puppycrawl.tools.checkstyle.api.Context;
52  import com.puppycrawl.tools.checkstyle.api.FileText;
53  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
54  import com.puppycrawl.tools.checkstyle.checks.coding.HiddenFieldCheck;
55  import com.puppycrawl.tools.checkstyle.checks.indentation.CommentsIndentationCheck;
56  import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck;
57  import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocParagraphCheck;
58  import com.puppycrawl.tools.checkstyle.checks.naming.ConstantNameCheck;
59  import com.puppycrawl.tools.checkstyle.checks.naming.MemberNameCheck;
60  import com.puppycrawl.tools.checkstyle.checks.naming.TypeNameCheck;
61  import com.puppycrawl.tools.checkstyle.filters.SuppressionCommentFilter;
62  import com.puppycrawl.tools.checkstyle.filters.SuppressionXpathFilter;
63  import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
64  
65  public class TreeWalkerTest extends AbstractModuleTestSupport {
66  
67      @Rule
68      public final TemporaryFolder temporaryFolder = new TemporaryFolder();
69  
70      @Override
71      protected String getPackageLocation() {
72          return "com/puppycrawl/tools/checkstyle/treewalker";
73      }
74  
75      @Test
76      public void testProperFileExtension() throws Exception {
77          final DefaultConfiguration checkConfig =
78                  createModuleConfig(ConstantNameCheck.class);
79          final File file = temporaryFolder.newFile("file.java");
80          try (Writer writer = new BufferedWriter(
81                  new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
82              final String content = "public class Main { public static final int k = 5 + 4; }";
83              writer.write(content);
84          }
85          final String[] expected1 = {
86              "1:45: " + getCheckMessage(ConstantNameCheck.class,
87                      MSG_INVALID_PATTERN, "k", "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"),
88          };
89          verify(checkConfig, file.getPath(), expected1);
90      }
91  
92      @Test
93      public void testImproperFileExtension() throws Exception {
94          final DefaultConfiguration checkConfig =
95                  createModuleConfig(ConstantNameCheck.class);
96          final File file = temporaryFolder.newFile("file.pdf");
97          try (BufferedWriter writer = new BufferedWriter(
98                  new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
99              final String content = "public class Main { public static final int k = 5 + 4; }";
100             writer.write(content);
101         }
102         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
103         verify(checkConfig, file.getPath(), expected);
104     }
105 
106     @Test
107     public void testAcceptableTokens()
108             throws Exception {
109         final DefaultConfiguration checkConfig =
110             createModuleConfig(HiddenFieldCheck.class);
111         checkConfig.addAttribute("tokens", "VARIABLE_DEF, ENUM_DEF, CLASS_DEF, METHOD_DEF,"
112                 + "IMPORT");
113         try {
114             final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
115             verify(checkConfig, getPath("InputTreeWalker.java"), expected);
116             fail("CheckstyleException is expected");
117         }
118         catch (CheckstyleException ex) {
119             final String errorMsg = ex.getMessage();
120             final Pattern expected = Pattern.compile(Pattern.quote("cannot initialize module"
121                     + " com.puppycrawl.tools.checkstyle.TreeWalker - Token ")
122                     + "\"(ENUM_DEF|CLASS_DEF|METHOD_DEF|IMPORT)\""
123                     + Pattern.quote(" was not found in Acceptable tokens list in check"
124                     + " com.puppycrawl.tools.checkstyle.checks.coding.HiddenFieldCheck"));
125 
126             final Matcher errorMsgMatcher = expected.matcher(errorMsg);
127             assertTrue("Failure for: " + errorMsg, errorMsgMatcher.matches());
128         }
129     }
130 
131     @Test
132     public void testOnEmptyFile() throws Exception {
133         final DefaultConfiguration checkConfig = createModuleConfig(HiddenFieldCheck.class);
134         final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath();
135         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
136 
137         verify(checkConfig, pathToEmptyFile, expected);
138     }
139 
140     @Test
141     public void testWithCheckNotHavingTreeWalkerAsParent() throws Exception {
142         final DefaultConfiguration checkConfig = createModuleConfig(JavadocPackageCheck.class);
143 
144         try {
145             final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
146             verify(createChecker(checkConfig, ModuleCreationOption.IN_TREEWALKER),
147                     temporaryFolder.newFile().getPath(), expected);
148             fail("CheckstyleException is expected");
149         }
150         catch (CheckstyleException exception) {
151             assertTrue("Error message is unexpected",
152                     exception.getMessage().contains("TreeWalker is not allowed as a parent of"));
153         }
154     }
155 
156     @Test
157     public void testSetupChildExceptions() {
158         final TreeWalker treeWalker = new TreeWalker();
159         final PackageObjectFactory factory = new PackageObjectFactory(
160                 new HashSet<>(), Thread.currentThread().getContextClassLoader());
161         treeWalker.setModuleFactory(factory);
162 
163         final Configuration config = new DefaultConfiguration("java.lang.String");
164         try {
165             treeWalker.setupChild(config);
166             fail("Exception is expected");
167         }
168         catch (CheckstyleException ex) {
169             assertEquals("Error message is not expected",
170                     "TreeWalker is not allowed as a parent of java.lang.String Please review "
171                             + "'Parent Module' section for this Check in web documentation if "
172                             + "Check is standard.", ex.getMessage());
173         }
174     }
175 
176     @Test
177     public void testSettersForParameters() throws Exception {
178         final TreeWalker treeWalker = new TreeWalker();
179         final DefaultConfiguration config = new DefaultConfiguration("default config");
180         treeWalker.setTabWidth(1);
181         treeWalker.configure(config);
182         treeWalker.setCacheFile(temporaryFolder.newFile().getPath());
183 
184         assertEquals("Invalid setter result", 1,
185                 (int) Whitebox.getInternalState(treeWalker, "tabWidth"));
186         assertEquals("Invalid configuration", config,
187             Whitebox.getInternalState(treeWalker, "configuration"));
188     }
189 
190     @Test
191     public void testForInvalidCheckImplementation() throws Exception {
192         final DefaultConfiguration checkConfig = createModuleConfig(BadJavaDocCheck.class);
193         final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath();
194 
195         try {
196             final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
197             verify(checkConfig, pathToEmptyFile, expected);
198             fail("Exception is expected");
199         }
200         catch (CheckstyleException ex) {
201             assertTrue("Error message is unexpected",
202                     ex.getMessage().contains("isCommentNodesRequired"));
203         }
204     }
205 
206     @Test
207     public void testProcessNonJavaFiles() throws Exception {
208         final TreeWalker treeWalker = new TreeWalker();
209         final PackageObjectFactory factory = new PackageObjectFactory(
210             new HashSet<>(), Thread.currentThread().getContextClassLoader());
211         treeWalker.setModuleFactory(factory);
212         treeWalker.configure(new DefaultConfiguration("default config"));
213         final DefaultConfiguration childConfig = createModuleConfig(JavadocParagraphCheck.class);
214         treeWalker.setupChild(childConfig);
215         final File file = new File("input.java");
216         final List<String> lines =
217             new ArrayList<>(Arrays.asList("package com.puppycrawl.tools.checkstyle;", "",
218                 "error public class InputTreeWalkerFileWithViolation {}"));
219         final FileText fileText = new FileText(file, lines);
220         try {
221             treeWalker.processFiltered(file, fileText);
222             fail("Exception expected");
223         }
224         catch (CheckstyleException ex) {
225             assertEquals("Invalid exception message",
226                 "MismatchedTokenException occurred while parsing file input.java.",
227                 ex.getMessage());
228         }
229     }
230 
231     @Test
232     public void testProcessNonJavaFilesWithoutException() throws Exception {
233         final TreeWalker treeWalker = new TreeWalker();
234         treeWalker.setTabWidth(1);
235         treeWalker.configure(new DefaultConfiguration("default config"));
236         final File file = new File(getPath("InputTreeWalkerNotJava.xml"));
237         final FileText fileText = new FileText(file, StandardCharsets.ISO_8859_1.name());
238         treeWalker.processFiltered(file, fileText);
239         final Collection<Checks> checks = Whitebox.getInternalState(treeWalker, "ordinaryChecks");
240         assertTrue("No checks -> No parsing", checks.isEmpty());
241     }
242 
243     @Test
244     public void testWithCacheWithNoViolation() throws Exception {
245         final DefaultConfiguration checkConfig = createModuleConfig(HiddenFieldCheck.class);
246         final Checker checker = createChecker(checkConfig);
247         final PackageObjectFactory factory = new PackageObjectFactory(
248             new HashSet<>(), Thread.currentThread().getContextClassLoader());
249         checker.setModuleFactory(factory);
250         final File file = temporaryFolder.newFile("file.java");
251         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
252 
253         verify(checker, file.getPath(), expected);
254     }
255 
256     @Test
257     public void testProcessWithParserThrowable() throws Exception {
258         final TreeWalker treeWalker = new TreeWalker();
259         treeWalker.configure(createModuleConfig(TypeNameCheck.class));
260         final PackageObjectFactory factory = new PackageObjectFactory(
261             new HashSet<>(), Thread.currentThread().getContextClassLoader());
262         treeWalker.setModuleFactory(factory);
263         treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
264         final File file = temporaryFolder.newFile("file.java");
265         final List<String> lines = new ArrayList<>();
266         lines.add(" classD a {} ");
267         final FileText fileText = new FileText(file, lines);
268         try {
269             treeWalker.processFiltered(file, fileText);
270             fail("Exception is expected");
271         }
272         catch (CheckstyleException exception) {
273             assertTrue("Error message is unexpected",
274                     exception.getMessage().contains(
275                     "occurred while parsing file"));
276         }
277     }
278 
279     @Test
280     public void testProcessWithRecognitionException() throws Exception {
281         final TreeWalker treeWalker = new TreeWalker();
282         treeWalker.configure(createModuleConfig(TypeNameCheck.class));
283         final PackageObjectFactory factory = new PackageObjectFactory(
284             new HashSet<>(), Thread.currentThread().getContextClassLoader());
285         treeWalker.setModuleFactory(factory);
286         treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
287         final File file = temporaryFolder.newFile("file.java");
288         final List<String> lines = new ArrayList<>();
289         lines.add(" class a%$# {} ");
290         final FileText fileText = new FileText(file, lines);
291         try {
292             treeWalker.processFiltered(file, fileText);
293             fail("Exception is expected");
294         }
295         catch (CheckstyleException exception) {
296             assertTrue("Error message is unexpected",
297                     exception.getMessage().contains(
298                     "TokenStreamRecognitionException occurred while parsing file"));
299         }
300     }
301 
302     @Test
303     public void testRequiredTokenIsNotInDefaultTokens() throws Exception {
304         final DefaultConfiguration checkConfig =
305             createModuleConfig(RequiredTokenIsNotInDefaultsCheck.class);
306         final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath();
307 
308         try {
309             final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
310             verify(checkConfig, pathToEmptyFile, expected);
311             fail("CheckstyleException is expected");
312         }
313         catch (CheckstyleException ex) {
314             assertTrue("Error message is unexpected",
315                     ex.getMessage().startsWith("cannot initialize module"
316                 + " com.puppycrawl.tools.checkstyle.TreeWalker - Token \""
317                 + TokenTypes.ASSIGN + "\" from required"
318                 + " tokens was not found in default tokens list in check"));
319         }
320     }
321 
322     @Test
323     public void testRequiredTokenIsEmptyIntArray() throws Exception {
324         final DefaultConfiguration checkConfig =
325             createModuleConfig(RequiredTokenIsEmptyIntArray.class);
326         final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath();
327 
328         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
329         verify(checkConfig, pathToEmptyFile, expected);
330     }
331 
332     @Test
333     public void testBehaviourWithZeroChecks() throws Exception {
334         final TreeWalker treeWalker = new TreeWalker();
335         final PackageObjectFactory factory = new PackageObjectFactory(
336                 new HashSet<>(), Thread.currentThread().getContextClassLoader());
337         treeWalker.setModuleFactory(factory);
338         // create file that should throw exception
339         final File file = temporaryFolder.newFile("file.java");
340         final FileText fileText = new FileText(file, new ArrayList<>());
341 
342         treeWalker.processFiltered(file, fileText);
343         final Collection<Checks> checks = Whitebox.getInternalState(treeWalker, "ordinaryChecks");
344         assertTrue("No checks -> No parsing", checks.isEmpty());
345     }
346 
347     @Test
348     public void testBehaviourWithOnlyOrdinaryChecks() throws Exception {
349         final TreeWalker treeWalker = new TreeWalker();
350         treeWalker.configure(createModuleConfig(TypeNameCheck.class));
351         final PackageObjectFactory factory = new PackageObjectFactory(
352                 new HashSet<>(), Thread.currentThread().getContextClassLoader());
353         treeWalker.setModuleFactory(factory);
354         treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
355         final File file = temporaryFolder.newFile("file.java");
356         final List<String> lines = new ArrayList<>();
357         lines.add(" class a%$# {} ");
358         final FileText fileText = new FileText(file, lines);
359 
360         try {
361             treeWalker.processFiltered(file, fileText);
362             fail("file is not compilable, exception is expected");
363         }
364         catch (CheckstyleException exception) {
365             final String message =
366                     "TokenStreamRecognitionException occurred while parsing file";
367             assertTrue("Error message is unexpected",
368                     exception.getMessage().contains(message));
369         }
370     }
371 
372     @Test
373     public void testBehaviourWithOnlyCommentChecks() throws Exception {
374         final TreeWalker treeWalker = new TreeWalker();
375         treeWalker.configure(createModuleConfig(CommentsIndentationCheck.class));
376         final PackageObjectFactory factory = new PackageObjectFactory(
377                 new HashSet<>(), Thread.currentThread().getContextClassLoader());
378         treeWalker.setModuleFactory(factory);
379         treeWalker.setupChild(createModuleConfig(CommentsIndentationCheck.class));
380         final File file = temporaryFolder.newFile("file.java");
381         final List<String> lines = new ArrayList<>();
382         lines.add(" class a%$# {} ");
383         final FileText fileText = new FileText(file, lines);
384 
385         try {
386             treeWalker.processFiltered(file, fileText);
387             fail("file is not compilable, exception is expected");
388         }
389         catch (CheckstyleException exception) {
390             final String message =
391                     "TokenStreamRecognitionException occurred while parsing file";
392             assertTrue("Error message is unexpected",
393                     exception.getMessage().contains(message));
394         }
395     }
396 
397     @Test
398     public void testBehaviourWithOrdinaryAndCommentChecks() throws Exception {
399         final TreeWalker treeWalker = new TreeWalker();
400         treeWalker.configure(createModuleConfig(TypeNameCheck.class));
401         treeWalker.configure(createModuleConfig(CommentsIndentationCheck.class));
402         final PackageObjectFactory factory = new PackageObjectFactory(
403                 new HashSet<>(), Thread.currentThread().getContextClassLoader());
404         treeWalker.setModuleFactory(factory);
405         treeWalker.setupChild(createModuleConfig(TypeNameCheck.class));
406         treeWalker.setupChild(createModuleConfig(CommentsIndentationCheck.class));
407         final File file = temporaryFolder.newFile("file.java");
408         final List<String> lines = new ArrayList<>();
409         lines.add(" class a%$# {} ");
410         final FileText fileText = new FileText(file, lines);
411 
412         try {
413             treeWalker.processFiltered(file, fileText);
414             fail("file is not compilable, exception is expected");
415         }
416         catch (CheckstyleException exception) {
417             final String message =
418                     "TokenStreamRecognitionException occurred while parsing file";
419             assertTrue("Error message is unexpected",
420                     exception.getMessage().contains(message));
421         }
422     }
423 
424     @Test
425     public void testBehaviourWithChecksAndFilters() throws Exception {
426         final DefaultConfiguration filterConfig =
427                 createModuleConfig(SuppressionCommentFilter.class);
428         filterConfig.addAttribute("checkCPP", "false");
429 
430         final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
431         treeWalkerConfig.addChild(createModuleConfig(MemberNameCheck.class));
432         treeWalkerConfig.addChild(filterConfig);
433 
434         final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
435 
436         final File file = new File(getPath("InputTreeWalkerSuppressionCommentFilter.java"));
437 
438         final String[] expected = {
439             "9:17: " + getCheckMessage(MemberNameCheck.class, "name.invalidPattern", "P",
440                     "^[a-z][a-zA-Z0-9]*$"),
441             "4:17: " + getCheckMessage(MemberNameCheck.class, "name.invalidPattern", "I",
442                     "^[a-z][a-zA-Z0-9]*$"),
443         };
444 
445         verify(checkerConfig,
446                 file.getPath(),
447                 expected);
448     }
449 
450     @Test
451     public void testFinishLocalSetupFullyInitialized() {
452         final TreeWalker treeWalker = new TreeWalker();
453         final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
454         treeWalker.setClassLoader(contextClassLoader);
455         treeWalker.setSeverity("error");
456         treeWalker.setTabWidth(100);
457         treeWalker.finishLocalSetup();
458 
459         final Context context = Whitebox.getInternalState(treeWalker, "childContext");
460         assertEquals("Classloader object differs from expected",
461                 contextClassLoader, context.get("classLoader"));
462         assertEquals("Severity differs from expected",
463                 "error", context.get("severity"));
464         assertEquals("Tab width differs from expected",
465                 String.valueOf(100), context.get("tabWidth"));
466     }
467 
468     @Test
469     public void testCheckInitIsCalledInTreeWalker() throws Exception {
470         final DefaultConfiguration checkConfig =
471                 createModuleConfig(VerifyInitCheck.class);
472         final File file = temporaryFolder.newFile("file.pdf");
473         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
474         verify(checkConfig, file.getPath(), expected);
475         assertTrue("Init was not called", VerifyInitCheck.isInitWasCalled());
476     }
477 
478     @Test
479     public void testCheckDestroyIsCalledInTreeWalker() throws Exception {
480         VerifyDestroyCheck.resetDestroyWasCalled();
481         final DefaultConfiguration checkConfig =
482                 createModuleConfig(VerifyDestroyCheck.class);
483         final File file = temporaryFolder.newFile("file.pdf");
484         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
485         verify(checkConfig, file.getPath(), expected);
486         assertTrue("Destroy was not called", VerifyDestroyCheck.isDestroyWasCalled());
487     }
488 
489     @Test
490     public void testCommentCheckDestroyIsCalledInTreeWalker() throws Exception {
491         VerifyDestroyCheck.resetDestroyWasCalled();
492         final DefaultConfiguration checkConfig =
493                 createModuleConfig(VerifyDestroyCommentCheck.class);
494         final File file = temporaryFolder.newFile("file.pdf");
495         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
496         verify(checkConfig, file.getPath(), expected);
497         assertTrue("Destroy was not called", VerifyDestroyCheck.isDestroyWasCalled());
498     }
499 
500     @Test
501     public void testCacheWhenFileExternalResourceContentDoesNotChange() throws Exception {
502         final DefaultConfiguration filterConfig = createModuleConfig(SuppressionXpathFilter.class);
503         filterConfig.addAttribute("file", getPath("InputTreeWalkerSuppressionXpathFilter.xml"));
504         final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
505         treeWalkerConfig.addChild(filterConfig);
506 
507         final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
508         final File cacheFile = temporaryFolder.newFile();
509         checkerConfig.addAttribute("cacheFile", cacheFile.getPath());
510 
511         final String filePath = temporaryFolder.newFile("file.java").getPath();
512         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
513 
514         verify(checkerConfig, filePath, expected);
515         // One more time to use cache.
516         verify(checkerConfig, filePath, expected);
517 
518         assertTrue("External resource is not present in cache",
519                 new String(Files.readAllBytes(cacheFile.toPath()),
520                         StandardCharsets.UTF_8).contains(
521                                 "InputTreeWalkerSuppressionXpathFilter.xml"));
522     }
523 
524     private static class BadJavaDocCheck extends AbstractCheck {
525 
526         @Override
527         public int[] getDefaultTokens() {
528             return getAcceptableTokens();
529         }
530 
531         @Override
532         public int[] getAcceptableTokens() {
533             return new int[] {TokenTypes.SINGLE_LINE_COMMENT};
534         }
535 
536         @Override
537         public int[] getRequiredTokens() {
538             return getAcceptableTokens();
539         }
540 
541     }
542 
543     private static class VerifyInitCheck extends AbstractCheck {
544 
545         private static boolean initWasCalled;
546 
547         @Override
548         public int[] getDefaultTokens() {
549             return CommonUtils.EMPTY_INT_ARRAY;
550         }
551 
552         @Override
553         public int[] getAcceptableTokens() {
554             return getDefaultTokens();
555         }
556 
557         @Override
558         public int[] getRequiredTokens() {
559             return getDefaultTokens();
560         }
561 
562         @Override
563         public void init() {
564             super.init();
565             initWasCalled = true;
566         }
567 
568         public static boolean isInitWasCalled() {
569             return initWasCalled;
570         }
571 
572     }
573 
574     private static class VerifyDestroyCheck extends AbstractCheck {
575 
576         private static boolean destroyWasCalled;
577 
578         @Override
579         public int[] getDefaultTokens() {
580             return CommonUtils.EMPTY_INT_ARRAY;
581         }
582 
583         @Override
584         public int[] getAcceptableTokens() {
585             return getDefaultTokens();
586         }
587 
588         @Override
589         public int[] getRequiredTokens() {
590             return getDefaultTokens();
591         }
592 
593         @Override
594         public void destroy() {
595             super.destroy();
596             destroyWasCalled = true;
597         }
598 
599         public static void resetDestroyWasCalled() {
600             destroyWasCalled = false;
601         }
602 
603         public static boolean isDestroyWasCalled() {
604             return destroyWasCalled;
605         }
606 
607     }
608 
609     private static class VerifyDestroyCommentCheck extends VerifyDestroyCheck {
610 
611         @Override
612         public boolean isCommentNodesRequired() {
613             return true;
614         }
615 
616     }
617 
618     private static class RequiredTokenIsNotInDefaultsCheck extends AbstractCheck {
619 
620         @Override
621         public int[] getRequiredTokens() {
622             return new int[] {TokenTypes.ASSIGN};
623         }
624 
625         @Override
626         public int[] getDefaultTokens() {
627             return new int[] {TokenTypes.ANNOTATION};
628         }
629 
630         @Override
631         public int[] getAcceptableTokens() {
632             return CommonUtils.EMPTY_INT_ARRAY;
633         }
634 
635     }
636 
637     private static class RequiredTokenIsEmptyIntArray extends AbstractCheck {
638 
639         @Override
640         public int[] getRequiredTokens() {
641             return CommonUtils.EMPTY_INT_ARRAY;
642         }
643 
644         @Override
645         public int[] getDefaultTokens() {
646             return new int[] {TokenTypes.ANNOTATION};
647         }
648 
649         @Override
650         public int[] getAcceptableTokens() {
651             return CommonUtils.EMPTY_INT_ARRAY;
652         }
653 
654     }
655 
656 }