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
24 import java.io.File;
25 import java.io.Writer;
26 import java.lang.reflect.Method;
27 import java.nio.charset.StandardCharsets;
28 import java.nio.file.Files;
29 import java.text.MessageFormat;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.BitSet;
33 import java.util.List;
34 import java.util.Locale;
35 import java.util.Set;
36 import java.util.function.Consumer;
37
38 import org.antlr.v4.runtime.CommonToken;
39 import org.junit.jupiter.api.Test;
40 import org.junit.jupiter.api.io.TempDir;
41
42 import com.puppycrawl.tools.checkstyle.api.DetailAST;
43 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
44 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
45 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
46
47
48
49
50 public class DetailAstImplTest extends AbstractModuleTestSupport {
51
52
53 public static final Set<String> NO_ROOT_FILES = Set.of(
54
55 "InputGrammar.java",
56
57 "InputPackageDeclarationWithCommentOnly.java",
58 "InputSingleSpaceSeparatorEmpty.java",
59 "InputNoCodeInFile1.java",
60 "InputNoCodeInFile2.java",
61 "InputNoCodeInFile3.java",
62 "InputNoCodeInFile5.java"
63 );
64
65 @TempDir
66 public File temporaryFolder;
67
68 @Override
69 protected String getPackageLocation() {
70 return "com/puppycrawl/tools/checkstyle/api/detailast";
71 }
72
73 private static Method getSetParentMethod() throws Exception {
74 final Class<DetailAstImpl> detailAstClass = DetailAstImpl.class;
75 final Method setParentMethod =
76 detailAstClass.getDeclaredMethod("setParent", DetailAstImpl.class);
77 setParentMethod.setAccessible(true);
78 return setParentMethod;
79 }
80
81 @Test
82 public void testInitialize() {
83 final DetailAstImpl ast = new DetailAstImpl();
84 ast.setText("test");
85 ast.setType(1);
86 ast.setLineNo(2);
87 ast.setColumnNo(3);
88
89 final DetailAstImpl copy = new DetailAstImpl();
90 copy.setText(ast.getText());
91 copy.setType(ast.getType());
92 copy.setLineNo(ast.getLineNo());
93 copy.setColumnNo(ast.getColumnNo());
94
95 assertWithMessage("Invalid text")
96 .that(copy.getText())
97 .isEqualTo("test");
98 assertWithMessage("Invalid type")
99 .that(copy.getType())
100 .isEqualTo(1);
101 assertWithMessage("Invalid line number")
102 .that(copy.getLineNo())
103 .isEqualTo(2);
104 assertWithMessage("Invalid column number")
105 .that(copy.getColumnNo())
106 .isEqualTo(3);
107 }
108
109 @Test
110 public void testInitializeToken() {
111 final CommonToken token = new CommonToken(1);
112 token.setText("test");
113 token.setLine(2);
114 token.setCharPositionInLine(3);
115
116 final DetailAstImpl ast = new DetailAstImpl();
117 ast.initialize(token);
118
119 assertWithMessage("Invalid text")
120 .that(ast.getText())
121 .isEqualTo("test");
122 assertWithMessage("Invalid type")
123 .that(ast.getType())
124 .isEqualTo(1);
125 assertWithMessage("Invalid line number")
126 .that(ast.getLineNo())
127 .isEqualTo(2);
128 assertWithMessage("Invalid column number")
129 .that(ast.getColumnNo())
130 .isEqualTo(3);
131 }
132
133 @Test
134 public void testGetChildCount() throws Exception {
135 final DetailAstImpl root = new DetailAstImpl();
136 final DetailAstImpl firstLevelA = new DetailAstImpl();
137 final DetailAstImpl firstLevelB = new DetailAstImpl();
138 final DetailAstImpl secondLevelA = new DetailAstImpl();
139
140 root.setFirstChild(firstLevelA);
141
142 final Method setParentMethod = getSetParentMethod();
143 setParentMethod.invoke(firstLevelA, root);
144 firstLevelA.setFirstChild(secondLevelA);
145 firstLevelA.setNextSibling(firstLevelB);
146
147 setParentMethod.invoke(firstLevelB, root);
148
149 setParentMethod.invoke(secondLevelA, root);
150
151 assertWithMessage("Invalid child count")
152 .that(secondLevelA.getChildCount())
153 .isEqualTo(0);
154 assertWithMessage("Invalid child count")
155 .that(firstLevelB.getChildCount())
156 .isEqualTo(0);
157 assertWithMessage("Invalid child count")
158 .that(firstLevelA.getChildCount())
159 .isEqualTo(1);
160 assertWithMessage("Invalid child count")
161 .that(root.getChildCount())
162 .isEqualTo(2);
163 assertWithMessage("Invalid child count")
164 .that(root.getNumberOfChildren())
165 .isEqualTo(2);
166
167 assertWithMessage("Previous sibling should be null")
168 .that(root.getPreviousSibling())
169 .isNull();
170 assertWithMessage("Previous sibling should be null")
171 .that(firstLevelA.getPreviousSibling())
172 .isNull();
173 assertWithMessage("Previous sibling should be null")
174 .that(secondLevelA.getPreviousSibling())
175 .isNull();
176 assertWithMessage("Invalid previous sibling")
177 .that(firstLevelB.getPreviousSibling())
178 .isEqualTo(firstLevelA);
179 }
180
181 @Test
182 public void testHasChildren() {
183 final DetailAstImpl root = new DetailAstImpl();
184 final DetailAstImpl child = new DetailAstImpl();
185 root.setFirstChild(child);
186
187 assertWithMessage("Root node should have children")
188 .that(root.hasChildren())
189 .isTrue();
190 assertWithMessage("Child node should have no children")
191 .that(child.hasChildren())
192 .isFalse();
193 }
194
195 @Test
196 public void testGetChildCountType() throws Exception {
197 final DetailAstImpl root = new DetailAstImpl();
198 final DetailAstImpl firstLevelA = new DetailAstImpl();
199 final DetailAstImpl firstLevelB = new DetailAstImpl();
200
201 root.setFirstChild(firstLevelA);
202
203 final Method setParentMethod = getSetParentMethod();
204 setParentMethod.invoke(firstLevelA, root);
205 firstLevelA.setNextSibling(firstLevelB);
206
207 firstLevelA.setType(TokenTypes.IDENT);
208 firstLevelB.setType(TokenTypes.EXPR);
209
210 setParentMethod.invoke(firstLevelB, root);
211
212 final int childCountLevelB = firstLevelB.getChildCount(0);
213 assertWithMessage("Invalid child count")
214 .that(childCountLevelB)
215 .isEqualTo(0);
216 final int childCountLevelA = firstLevelA.getChildCount(TokenTypes.EXPR);
217 assertWithMessage("Invalid child count")
218 .that(childCountLevelA)
219 .isEqualTo(0);
220 final int identTypeCount = root.getChildCount(TokenTypes.IDENT);
221 assertWithMessage("Invalid child count")
222 .that(identTypeCount)
223 .isEqualTo(1);
224 final int exprTypeCount = root.getChildCount(TokenTypes.EXPR);
225 assertWithMessage("Invalid child count")
226 .that(exprTypeCount)
227 .isEqualTo(1);
228 final int invalidTypeCount = root.getChildCount(0);
229 assertWithMessage("Invalid child count")
230 .that(invalidTypeCount)
231 .isEqualTo(0);
232 }
233
234 @Test
235 public void testSetSiblingNull() throws Exception {
236 final DetailAstImpl root = new DetailAstImpl();
237 final DetailAstImpl firstLevelA = new DetailAstImpl();
238
239 root.setFirstChild(firstLevelA);
240
241 assertWithMessage("Invalid child count")
242 .that(root.getChildCount())
243 .isEqualTo(1);
244
245 getSetParentMethod().invoke(firstLevelA, root);
246 firstLevelA.addPreviousSibling(null);
247 firstLevelA.addNextSibling(null);
248
249 assertWithMessage("Invalid child count")
250 .that(root.getChildCount())
251 .isEqualTo(1);
252 }
253
254 @Test
255 public void testAddPreviousSibling() {
256 final DetailAST previousSibling = new DetailAstImpl();
257 final DetailAstImpl instance = new DetailAstImpl();
258 final DetailAstImpl parent = new DetailAstImpl();
259
260 parent.setFirstChild(instance);
261
262 instance.addPreviousSibling(previousSibling);
263
264 assertWithMessage("unexpected result")
265 .that(instance.getPreviousSibling())
266 .isEqualTo(previousSibling);
267 assertWithMessage("unexpected result")
268 .that(parent.getFirstChild())
269 .isEqualTo(previousSibling);
270
271 final DetailAST newPreviousSibling = new DetailAstImpl();
272
273 instance.addPreviousSibling(newPreviousSibling);
274
275 assertWithMessage("unexpected result")
276 .that(instance.getPreviousSibling())
277 .isEqualTo(newPreviousSibling);
278 assertWithMessage("unexpected result")
279 .that(newPreviousSibling.getPreviousSibling())
280 .isEqualTo(previousSibling);
281 assertWithMessage("unexpected result")
282 .that(previousSibling.getNextSibling())
283 .isEqualTo(newPreviousSibling);
284 assertWithMessage("unexpected result")
285 .that(parent.getFirstChild())
286 .isEqualTo(previousSibling);
287
288 final DetailAstImpl secondNewPreviousSibling = new DetailAstImpl();
289 instance.addPreviousSibling(secondNewPreviousSibling);
290 assertWithMessage("unexpected result")
291 .that(secondNewPreviousSibling.getPreviousSibling())
292 .isEqualTo(newPreviousSibling);
293 assertWithMessage("unexpected result")
294 .that(secondNewPreviousSibling.getNextSibling())
295 .isEqualTo(instance);
296 assertWithMessage("unexpected result")
297 .that(newPreviousSibling.getNextSibling())
298 .isEqualTo(secondNewPreviousSibling);
299 assertWithMessage("unexpected result")
300 .that(secondNewPreviousSibling.getPreviousSibling().getPreviousSibling())
301 .isEqualTo(previousSibling);
302 assertWithMessage("unexpected result")
303 .that(instance.getPreviousSibling().getPreviousSibling().getPreviousSibling())
304 .isEqualTo(previousSibling);
305 }
306
307 @Test
308 public void testAddPreviousSiblingNullParent() {
309 final DetailAstImpl child = new DetailAstImpl();
310 final DetailAST newSibling = new DetailAstImpl();
311
312 child.addPreviousSibling(newSibling);
313
314 assertWithMessage("Invalid child token")
315 .that(newSibling.getNextSibling())
316 .isEqualTo(child);
317 assertWithMessage("Invalid child token")
318 .that(child.getPreviousSibling())
319 .isEqualTo(newSibling);
320 }
321
322 @Test
323 public void testInsertSiblingBetween() throws Exception {
324 final DetailAstImpl root = new DetailAstImpl();
325 final DetailAstImpl firstLevelA = new DetailAstImpl();
326 final DetailAST firstLevelB = new DetailAstImpl();
327 final DetailAST firstLevelC = new DetailAstImpl();
328
329 assertWithMessage("Invalid child count")
330 .that(root.getChildCount())
331 .isEqualTo(0);
332
333 root.setFirstChild(firstLevelA);
334 final Method setParentMethod = getSetParentMethod();
335 setParentMethod.invoke(firstLevelA, root);
336
337 assertWithMessage("Invalid child count")
338 .that(root.getChildCount())
339 .isEqualTo(1);
340
341 firstLevelA.addNextSibling(firstLevelB);
342 setParentMethod.invoke(firstLevelB, root);
343
344 assertWithMessage("Invalid next sibling")
345 .that(firstLevelA.getNextSibling())
346 .isEqualTo(firstLevelB);
347
348 firstLevelA.addNextSibling(firstLevelC);
349 setParentMethod.invoke(firstLevelC, root);
350
351 assertWithMessage("Invalid next sibling")
352 .that(firstLevelA.getNextSibling())
353 .isEqualTo(firstLevelC);
354 }
355
356 @Test
357 public void testBranchContains() {
358 final DetailAstImpl root = createToken(null, TokenTypes.CLASS_DEF);
359 final DetailAstImpl modifiers = createToken(root, TokenTypes.MODIFIERS);
360 createToken(modifiers, TokenTypes.LITERAL_PUBLIC);
361
362 assertWithMessage("invalid result")
363 .that(root.branchContains(TokenTypes.LITERAL_PUBLIC))
364 .isTrue();
365 assertWithMessage("invalid result")
366 .that(root.branchContains(TokenTypes.OBJBLOCK))
367 .isFalse();
368 }
369
370 private static DetailAstImpl createToken(DetailAstImpl root, int type) {
371 final DetailAstImpl result = new DetailAstImpl();
372 result.setType(type);
373 if (root != null) {
374 root.addChild(result);
375 }
376 return result;
377 }
378
379 @Test
380 public void testClearBranchTokenTypes() throws Exception {
381 final DetailAstImpl parent = new DetailAstImpl();
382 final DetailAstImpl child = new DetailAstImpl();
383 parent.setFirstChild(child);
384
385 final List<Consumer<DetailAstImpl>> clearBranchTokenTypesMethods = Arrays.asList(
386 child::setFirstChild,
387 child::setNextSibling,
388 child::addPreviousSibling,
389 child::addNextSibling,
390 child::addChild,
391 ast -> {
392 try {
393 TestUtil.invokeMethod(child, "setParent", ast);
394 }
395
396 catch (Exception exception) {
397 throw new IllegalStateException(exception);
398 }
399 }
400 );
401
402 for (Consumer<DetailAstImpl> method : clearBranchTokenTypesMethods) {
403 final BitSet branchTokenTypes = TestUtil.invokeMethod(parent, "getBranchTokenTypes");
404 method.accept(null);
405 final BitSet branchTokenTypes2 = TestUtil.invokeMethod(parent, "getBranchTokenTypes");
406 assertWithMessage("Branch token types are not equal")
407 .that(branchTokenTypes)
408 .isEqualTo(branchTokenTypes2);
409 assertWithMessage("Branch token types should not be the same")
410 .that(branchTokenTypes)
411 .isNotSameInstanceAs(branchTokenTypes2);
412 }
413 }
414
415 @Test
416 public void testCacheBranchTokenTypes() {
417 final DetailAST root = new DetailAstImpl();
418 final BitSet bitSet = new BitSet();
419 bitSet.set(999);
420
421 TestUtil.setInternalState(root, "branchTokenTypes", bitSet);
422 assertWithMessage("Branch tokens has changed")
423 .that(root.branchContains(999))
424 .isTrue();
425 }
426
427 @Test
428 public void testClearChildCountCache() {
429 final DetailAstImpl parent = new DetailAstImpl();
430 final DetailAstImpl child = new DetailAstImpl();
431 parent.setFirstChild(child);
432
433 final List<Consumer<DetailAstImpl>> clearChildCountCacheMethods = Arrays.asList(
434 child::setNextSibling,
435 child::addPreviousSibling,
436 child::addNextSibling
437 );
438
439 for (Consumer<DetailAstImpl> method : clearChildCountCacheMethods) {
440 final int startCount = parent.getChildCount();
441 method.accept(null);
442 final int intermediateCount = TestUtil.getInternalState(parent, "childCount");
443 final int finishCount = parent.getChildCount();
444 assertWithMessage("Child count has changed")
445 .that(finishCount)
446 .isEqualTo(startCount);
447 assertWithMessage("Invalid child count")
448 .that(intermediateCount)
449 .isEqualTo(Integer.MIN_VALUE);
450 }
451
452 final int startCount = child.getChildCount();
453 child.addChild(null);
454 final int intermediateCount = TestUtil.getInternalState(child, "childCount");
455 final int finishCount = child.getChildCount();
456 assertWithMessage("Child count has changed")
457 .that(finishCount)
458 .isEqualTo(startCount);
459 assertWithMessage("Invalid child count")
460 .that(intermediateCount)
461 .isEqualTo(Integer.MIN_VALUE);
462 }
463
464 @Test
465 public void testCacheGetChildCount() {
466 final DetailAST root = new DetailAstImpl();
467
468 TestUtil.setInternalState(root, "childCount", 999);
469 assertWithMessage("Child count has changed")
470 .that(root.getChildCount())
471 .isEqualTo(999);
472 }
473
474 @Test
475 public void testAddNextSibling() {
476 final DetailAstImpl parent = new DetailAstImpl();
477 final DetailAstImpl child = new DetailAstImpl();
478 final DetailAstImpl sibling = new DetailAstImpl();
479 final DetailAstImpl newSibling = new DetailAstImpl();
480 final DetailAST newNextSibling = new DetailAstImpl();
481
482 parent.setFirstChild(child);
483 child.setNextSibling(sibling);
484 child.addNextSibling(newSibling);
485 newSibling.addNextSibling(newNextSibling);
486
487 assertWithMessage("Invalid previous sibling")
488 .that(newNextSibling.getPreviousSibling())
489 .isEqualTo(newSibling);
490 assertWithMessage("Invalid next sibling")
491 .that(newNextSibling.getNextSibling())
492 .isEqualTo(sibling);
493 assertWithMessage("Invalid next sibling")
494 .that(sibling.getNextSibling())
495 .isNull();
496 assertWithMessage("Invalid node")
497 .that(sibling.getPreviousSibling().getPreviousSibling())
498 .isEqualTo(newSibling);
499 assertWithMessage("Invalid node")
500 .that(newNextSibling.getPreviousSibling().getPreviousSibling())
501 .isEqualTo(child);
502 assertWithMessage("Invalid parent")
503 .that(newSibling.getParent())
504 .isEqualTo(parent);
505 assertWithMessage("Invalid next sibling")
506 .that(newSibling.getNextSibling())
507 .isEqualTo(newNextSibling);
508 assertWithMessage("Invalid child")
509 .that(child.getNextSibling())
510 .isEqualTo(newSibling);
511 }
512
513 @Test
514 public void testAddNextSibling2() {
515 final DetailAstImpl parent = new DetailAstImpl();
516 final DetailAstImpl child = new DetailAstImpl();
517 parent.setFirstChild(child);
518 final DetailAstImpl siblingOfChild = new DetailAstImpl();
519 child.addNextSibling(siblingOfChild);
520
521 assertWithMessage("Previous Sibling should be child")
522 .that(siblingOfChild.getPreviousSibling())
523 .isEqualTo(child);
524
525 final DetailAST nullChild = null;
526 siblingOfChild.addNextSibling(nullChild);
527 assertWithMessage("Expected to be null")
528 .that(siblingOfChild.getNextSibling())
529 .isNull();
530 assertWithMessage("Child count should be 2")
531 .that(parent.getChildCount())
532 .isEqualTo(2);
533 }
534
535 @Test
536 public void testAddNextSibling3() {
537 final DetailAstImpl parent = new DetailAstImpl();
538 final DetailAstImpl child = new DetailAstImpl();
539 final DetailAstImpl sibling = new DetailAstImpl();
540
541 parent.setFirstChild(child);
542 child.setNextSibling(sibling);
543 child.addNextSibling(null);
544
545 assertWithMessage("Invalid next sibling")
546 .that(child.getNextSibling())
547 .isEqualTo(sibling);
548 }
549
550 @Test
551 public void testAddNextSibling4() {
552 final DetailAstImpl parent = new DetailAstImpl();
553 parent.setText("Parent");
554 final DetailAstImpl child = new DetailAstImpl();
555 child.setText("Child");
556 final DetailAstImpl sibling = new DetailAstImpl();
557 sibling.setText("Sibling");
558 parent.setFirstChild(child);
559 child.addNextSibling(sibling);
560
561 assertWithMessage("Invalid next sibling")
562 .that(child.getNextSibling())
563 .isEqualTo(sibling);
564 }
565
566 @Test
567 public void testAddNextSiblingNullParent() {
568 final DetailAstImpl child = new DetailAstImpl();
569 final DetailAstImpl newSibling = new DetailAstImpl();
570 final DetailAstImpl oldParent = new DetailAstImpl();
571 oldParent.addChild(newSibling);
572 child.addNextSibling(newSibling);
573
574 assertWithMessage("Invalid parent")
575 .that(newSibling.getParent())
576 .isEqualTo(oldParent);
577 assertWithMessage("Invalid next sibling")
578 .that(newSibling.getNextSibling())
579 .isNull();
580 assertWithMessage("Invalid parent")
581 .that(child.getNextSibling())
582 .isSameInstanceAs(newSibling);
583 }
584
585 @Test
586 public void testGetLineNo() {
587 final DetailAstImpl root1 = new DetailAstImpl();
588 root1.setLineNo(1);
589 assertWithMessage("Invalid line number")
590 .that(root1.getLineNo())
591 .isEqualTo(1);
592
593 final DetailAstImpl root2 = new DetailAstImpl();
594 final DetailAstImpl firstChild = new DetailAstImpl();
595 firstChild.setLineNo(2);
596 root2.setFirstChild(firstChild);
597 assertWithMessage("Invalid line number")
598 .that(root2.getLineNo())
599 .isEqualTo(2);
600
601 final DetailAstImpl root3 = new DetailAstImpl();
602 final DetailAstImpl nextSibling = new DetailAstImpl();
603 nextSibling.setLineNo(3);
604 root3.setNextSibling(nextSibling);
605 assertWithMessage("Invalid line number")
606 .that(root3.getLineNo())
607 .isEqualTo(3);
608
609 final DetailAstImpl root4 = new DetailAstImpl();
610 final DetailAstImpl comment = new DetailAstImpl();
611 comment.setType(TokenTypes.SINGLE_LINE_COMMENT);
612 comment.setLineNo(3);
613 root4.setFirstChild(comment);
614 assertWithMessage("Invalid line number")
615 .that(root4.getLineNo())
616 .isEqualTo(Integer.MIN_VALUE);
617 }
618
619 @Test
620 public void testGetColumnNo() {
621 final DetailAstImpl root1 = new DetailAstImpl();
622 root1.setColumnNo(1);
623 assertWithMessage("Invalid column number")
624 .that(root1.getColumnNo())
625 .isEqualTo(1);
626
627 final DetailAstImpl root2 = new DetailAstImpl();
628 final DetailAstImpl firstChild = new DetailAstImpl();
629 firstChild.setColumnNo(2);
630 root2.setFirstChild(firstChild);
631 assertWithMessage("Invalid column number")
632 .that(root2.getColumnNo())
633 .isEqualTo(2);
634
635 final DetailAstImpl root3 = new DetailAstImpl();
636 final DetailAstImpl nextSibling = new DetailAstImpl();
637 nextSibling.setColumnNo(3);
638 root3.setNextSibling(nextSibling);
639 assertWithMessage("Invalid column number")
640 .that(root3.getColumnNo())
641 .isEqualTo(3);
642
643 final DetailAstImpl root4 = new DetailAstImpl();
644 final DetailAstImpl comment = new DetailAstImpl();
645 comment.setType(TokenTypes.SINGLE_LINE_COMMENT);
646 comment.setColumnNo(3);
647 root4.setFirstChild(comment);
648 assertWithMessage("Invalid column number")
649 .that(root4.getColumnNo())
650 .isEqualTo(Integer.MIN_VALUE);
651 }
652
653 @Test
654 public void testFindFirstToken() {
655 final DetailAstImpl root = new DetailAstImpl();
656 final DetailAstImpl firstChild = new DetailAstImpl();
657 firstChild.setType(TokenTypes.IDENT);
658 final DetailAstImpl secondChild = new DetailAstImpl();
659 secondChild.setType(TokenTypes.EXPR);
660 final DetailAstImpl thirdChild = new DetailAstImpl();
661 thirdChild.setType(TokenTypes.IDENT);
662
663 root.addChild(firstChild);
664 root.addChild(secondChild);
665 root.addChild(thirdChild);
666
667 assertWithMessage("Invalid result")
668 .that(firstChild.findFirstToken(TokenTypes.IDENT))
669 .isNull();
670 final DetailAST ident = root.findFirstToken(TokenTypes.IDENT);
671 assertWithMessage("Invalid result")
672 .that(ident)
673 .isEqualTo(firstChild);
674 final DetailAST expr = root.findFirstToken(TokenTypes.EXPR);
675 assertWithMessage("Invalid result")
676 .that(expr)
677 .isEqualTo(secondChild);
678 assertWithMessage("Invalid result")
679 .that(root.findFirstToken(0))
680 .isNull();
681 }
682
683 @Test
684 public void testManyComments() throws Exception {
685 final File file = new File(temporaryFolder, "InputDetailASTManyComments.java");
686
687 try (Writer bw = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) {
688 bw.write("/*\ncom.puppycrawl.tools.checkstyle.checks.TodoCommentCheck\n\n\n\n*/\n");
689 bw.write("class C {\n");
690 for (int i = 0; i <= 30000; i++) {
691 bw.write("// " + i + "\n");
692 }
693 bw.write("}\n");
694 }
695
696 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
697 verifyWithInlineConfigParser(file.getAbsolutePath(), expected);
698 }
699
700 @Test
701 public void testTreeStructure() throws Exception {
702 final List<File> files = getAllFiles(
703 new File("src/test/resources/com/puppycrawl/tools/checkstyle"));
704
705 for (File file : files) {
706 final String fileName = file.getCanonicalPath();
707 final DetailAST rootAST = JavaParser.parseFile(new File(fileName),
708 JavaParser.Options.WITHOUT_COMMENTS);
709
710 assertWithMessage("file must return a root node: " + fileName)
711 .that(rootAST)
712 .isNotNull();
713
714 assertWithMessage("tree is valid")
715 .that(checkTree(fileName, rootAST))
716 .isTrue();
717 }
718 }
719
720 @Test
721 public void testToString() {
722 final DetailAstImpl ast = new DetailAstImpl();
723 ast.setText("text");
724 ast.setColumnNo(1);
725 ast.setLineNo(1);
726 assertWithMessage("Invalid text")
727 .that(ast.toString())
728 .isEqualTo("text[1x1]");
729 }
730
731 @Test
732 public void testRemoveChildren() {
733 final DetailAstImpl parent = new DetailAstImpl();
734 final DetailAstImpl child1 = new DetailAstImpl();
735 parent.setFirstChild(child1);
736 final DetailAstImpl child2 = new DetailAstImpl();
737 child1.setNextSibling(child2);
738
739 parent.removeChildren();
740
741 assertWithMessage("")
742 .that(parent.getChildCount())
743 .isEqualTo(0);
744 }
745
746 @Test
747 public void testAddChild() {
748 final DetailAstImpl grandParent = new DetailAstImpl();
749 grandParent.setText("grandparent");
750 final DetailAstImpl parent = new DetailAstImpl();
751 parent.setText("parent");
752 grandParent.setFirstChild(parent);
753
754 final DetailAstImpl child = new DetailAstImpl();
755 child.setText("child");
756 parent.setFirstChild(child);
757
758 final DetailAstImpl secondChild = new DetailAstImpl();
759 secondChild.setText("SecondChild");
760 parent.addChild(secondChild);
761
762 assertWithMessage("Invalid previous sibling")
763 .that(secondChild.getPreviousSibling())
764 .isEqualTo(child);
765 }
766
767 private static List<File> getAllFiles(File dir) {
768 final List<File> result = new ArrayList<>();
769
770 dir.listFiles(file -> {
771 if (file.isDirectory()) {
772 result.addAll(getAllFiles(file));
773 }
774 else if (file.getName().endsWith(".java")
775 && !NO_ROOT_FILES.contains(file.getName())) {
776 result.add(file);
777 }
778 return false;
779 });
780
781 return result;
782 }
783
784 private static boolean checkTree(final String filename, final DetailAST root) {
785 DetailAST curNode = root;
786 DetailAST parent = null;
787 DetailAST prev = null;
788 while (curNode != null) {
789 checkNode(curNode, parent, prev, filename, root);
790 DetailAST toVisit = curNode.getFirstChild();
791 if (toVisit == null) {
792 while (curNode != null && toVisit == null) {
793 toVisit = curNode.getNextSibling();
794 if (toVisit == null) {
795 curNode = curNode.getParent();
796 if (curNode != null) {
797 parent = curNode.getParent();
798 }
799 }
800 else {
801 prev = curNode;
802 curNode = toVisit;
803 }
804 }
805 }
806 else {
807 parent = curNode;
808 curNode = toVisit;
809 prev = null;
810 }
811 }
812
813 return true;
814 }
815
816 private static void checkNode(final DetailAST node,
817 final DetailAST parent,
818 final DetailAST prev,
819 final String filename,
820 final DetailAST root) {
821 final Object[] params = {
822 node, parent, prev, filename, root,
823 };
824 final MessageFormat badParentFormatter = new MessageFormat(
825 "Bad parent node={0} parent={1} filename={3} root={4}", Locale.ROOT);
826 final String badParentMsg = badParentFormatter.format(params);
827 assertWithMessage(badParentMsg)
828 .that(node.getParent())
829 .isEqualTo(parent);
830 final MessageFormat badPrevFormatter = new MessageFormat(
831 "Bad prev node={0} prev={2} parent={1} filename={3} root={4}", Locale.ROOT);
832 final String badPrevMsg = badPrevFormatter.format(params);
833 assertWithMessage(badPrevMsg)
834 .that(node.getPreviousSibling())
835 .isEqualTo(prev);
836 }
837
838 }