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.nio.file.Files;
27 import java.text.MessageFormat;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.BitSet;
31 import java.util.List;
32 import java.util.Locale;
33 import java.util.Set;
34 import java.util.function.Consumer;
35
36 import org.antlr.v4.runtime.CommonToken;
37 import org.junit.jupiter.api.Test;
38 import org.junit.jupiter.api.io.TempDir;
39
40 import com.puppycrawl.tools.checkstyle.api.DetailAST;
41 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
42 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
43 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
44
45
46
47
48 public class DetailAstImplTest extends AbstractModuleTestSupport {
49
50
51 public static final Set<String> NO_ROOT_FILES = Set.of(
52
53 "InputGrammar.java",
54
55 "InputPackageDeclarationWithCommentOnly.java",
56 "InputSingleSpaceSeparatorEmpty.java",
57 "InputNoCodeInFile1.java",
58 "InputNoCodeInFile2.java",
59 "InputNoCodeInFile3.java",
60 "InputNoCodeInFile5.java",
61 "InputOuterTypeFilenameEmpty.java",
62 "InputOneTopLevelClassEmpty.java",
63 "InputMethodCountEmpty.java",
64 "InputDeclarationOrderEmpty.java",
65 "InputJavadocLinkFirstOccurrenceEmptyFile.java"
66 );
67
68 @TempDir
69 public File temporaryFolder;
70
71 @Override
72 public String getPackageLocation() {
73 return "com/puppycrawl/tools/checkstyle/api/detailast";
74 }
75
76 private static void invokeSetParentMethod(DetailAST instance, DetailAstImpl parent)
77 throws Exception {
78 TestUtil.invokeVoidMethod(instance, "setParent", parent);
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 invokeSetParentMethod(firstLevelA, root);
143 firstLevelA.setFirstChild(secondLevelA);
144 firstLevelA.setNextSibling(firstLevelB);
145
146 invokeSetParentMethod(firstLevelB, root);
147
148 invokeSetParentMethod(secondLevelA, root);
149
150 assertWithMessage("Invalid child count")
151 .that(secondLevelA.getChildCount())
152 .isEqualTo(0);
153 assertWithMessage("Invalid child count")
154 .that(firstLevelB.getChildCount())
155 .isEqualTo(0);
156 assertWithMessage("Invalid child count")
157 .that(firstLevelA.getChildCount())
158 .isEqualTo(1);
159 assertWithMessage("Invalid child count")
160 .that(root.getChildCount())
161 .isEqualTo(2);
162 assertWithMessage("Invalid child count")
163 .that(root.getNumberOfChildren())
164 .isEqualTo(2);
165
166 assertWithMessage("Previous sibling should be null")
167 .that(root.getPreviousSibling())
168 .isNull();
169 assertWithMessage("Previous sibling should be null")
170 .that(firstLevelA.getPreviousSibling())
171 .isNull();
172 assertWithMessage("Previous sibling should be null")
173 .that(secondLevelA.getPreviousSibling())
174 .isNull();
175 assertWithMessage("Invalid previous sibling")
176 .that(firstLevelB.getPreviousSibling())
177 .isEqualTo(firstLevelA);
178 }
179
180 @Test
181 public void testHasChildren() {
182 final DetailAstImpl root = new DetailAstImpl();
183 final DetailAstImpl child = new DetailAstImpl();
184 root.setFirstChild(child);
185
186 assertWithMessage("Root node should have children")
187 .that(root.hasChildren())
188 .isTrue();
189 assertWithMessage("Child node should have no children")
190 .that(child.hasChildren())
191 .isFalse();
192 }
193
194 @Test
195 public void testGetChildCountType() throws Exception {
196 final DetailAstImpl root = new DetailAstImpl();
197 final DetailAstImpl firstLevelA = new DetailAstImpl();
198 final DetailAstImpl firstLevelB = new DetailAstImpl();
199
200 root.setFirstChild(firstLevelA);
201
202 invokeSetParentMethod(firstLevelA, root);
203 firstLevelA.setNextSibling(firstLevelB);
204
205 firstLevelA.setType(TokenTypes.IDENT);
206 firstLevelB.setType(TokenTypes.EXPR);
207
208 invokeSetParentMethod(firstLevelB, root);
209
210 final int childCountLevelB = firstLevelB.getChildCount(0);
211 assertWithMessage("Invalid child count")
212 .that(childCountLevelB)
213 .isEqualTo(0);
214 final int childCountLevelA = firstLevelA.getChildCount(TokenTypes.EXPR);
215 assertWithMessage("Invalid child count")
216 .that(childCountLevelA)
217 .isEqualTo(0);
218 final int identTypeCount = root.getChildCount(TokenTypes.IDENT);
219 assertWithMessage("Invalid child count")
220 .that(identTypeCount)
221 .isEqualTo(1);
222 final int exprTypeCount = root.getChildCount(TokenTypes.EXPR);
223 assertWithMessage("Invalid child count")
224 .that(exprTypeCount)
225 .isEqualTo(1);
226 final int invalidTypeCount = root.getChildCount(0);
227 assertWithMessage("Invalid child count")
228 .that(invalidTypeCount)
229 .isEqualTo(0);
230 }
231
232 @Test
233 public void testSetSiblingNull() throws Exception {
234 final DetailAstImpl root = new DetailAstImpl();
235 final DetailAstImpl firstLevelA = new DetailAstImpl();
236
237 root.setFirstChild(firstLevelA);
238
239 assertWithMessage("Invalid child count")
240 .that(root.getChildCount())
241 .isEqualTo(1);
242
243 invokeSetParentMethod(firstLevelA, root);
244 firstLevelA.addPreviousSibling(null);
245 firstLevelA.addNextSibling(null);
246
247 assertWithMessage("Invalid child count")
248 .that(root.getChildCount())
249 .isEqualTo(1);
250 }
251
252 @Test
253 public void testAddPreviousSibling() {
254 final DetailAST previousSibling = new DetailAstImpl();
255 final DetailAstImpl instance = new DetailAstImpl();
256 final DetailAstImpl parent = new DetailAstImpl();
257
258 parent.setFirstChild(instance);
259
260 instance.addPreviousSibling(previousSibling);
261
262 assertWithMessage("unexpected result")
263 .that(instance.getPreviousSibling())
264 .isEqualTo(previousSibling);
265 assertWithMessage("unexpected result")
266 .that(parent.getFirstChild())
267 .isEqualTo(previousSibling);
268
269 final DetailAST newPreviousSibling = new DetailAstImpl();
270
271 instance.addPreviousSibling(newPreviousSibling);
272
273 assertWithMessage("unexpected result")
274 .that(instance.getPreviousSibling())
275 .isEqualTo(newPreviousSibling);
276 assertWithMessage("unexpected result")
277 .that(newPreviousSibling.getPreviousSibling())
278 .isEqualTo(previousSibling);
279 assertWithMessage("unexpected result")
280 .that(previousSibling.getNextSibling())
281 .isEqualTo(newPreviousSibling);
282 assertWithMessage("unexpected result")
283 .that(parent.getFirstChild())
284 .isEqualTo(previousSibling);
285
286 final DetailAstImpl secondNewPreviousSibling = new DetailAstImpl();
287 instance.addPreviousSibling(secondNewPreviousSibling);
288 assertWithMessage("unexpected result")
289 .that(secondNewPreviousSibling.getPreviousSibling())
290 .isEqualTo(newPreviousSibling);
291 assertWithMessage("unexpected result")
292 .that(secondNewPreviousSibling.getNextSibling())
293 .isEqualTo(instance);
294 assertWithMessage("unexpected result")
295 .that(newPreviousSibling.getNextSibling())
296 .isEqualTo(secondNewPreviousSibling);
297 assertWithMessage("unexpected result")
298 .that(secondNewPreviousSibling.getPreviousSibling().getPreviousSibling())
299 .isEqualTo(previousSibling);
300 assertWithMessage("unexpected result")
301 .that(instance.getPreviousSibling().getPreviousSibling().getPreviousSibling())
302 .isEqualTo(previousSibling);
303 }
304
305 @Test
306 public void testAddPreviousSiblingNullParent() {
307 final DetailAstImpl child = new DetailAstImpl();
308 final DetailAST newSibling = new DetailAstImpl();
309
310 child.addPreviousSibling(newSibling);
311
312 assertWithMessage("Invalid child token")
313 .that(newSibling.getNextSibling())
314 .isEqualTo(child);
315 assertWithMessage("Invalid child token")
316 .that(child.getPreviousSibling())
317 .isEqualTo(newSibling);
318 }
319
320 @Test
321 public void testInsertSiblingBetween() throws Exception {
322 final DetailAstImpl root = new DetailAstImpl();
323 final DetailAstImpl firstLevelA = new DetailAstImpl();
324 final DetailAST firstLevelB = new DetailAstImpl();
325 final DetailAST firstLevelC = new DetailAstImpl();
326
327 assertWithMessage("Invalid child count")
328 .that(root.getChildCount())
329 .isEqualTo(0);
330
331 root.setFirstChild(firstLevelA);
332 invokeSetParentMethod(firstLevelA, root);
333
334 assertWithMessage("Invalid child count")
335 .that(root.getChildCount())
336 .isEqualTo(1);
337
338 firstLevelA.addNextSibling(firstLevelB);
339 invokeSetParentMethod(firstLevelB, root);
340
341 assertWithMessage("Invalid next sibling")
342 .that(firstLevelA.getNextSibling())
343 .isEqualTo(firstLevelB);
344
345 firstLevelA.addNextSibling(firstLevelC);
346 invokeSetParentMethod(firstLevelC, root);
347
348 assertWithMessage("Invalid next sibling")
349 .that(firstLevelA.getNextSibling())
350 .isEqualTo(firstLevelC);
351 }
352
353 @Test
354 public void testBranchContains() {
355 final DetailAstImpl root = createToken(null, TokenTypes.CLASS_DEF);
356 final DetailAstImpl modifiers = createToken(root, TokenTypes.MODIFIERS);
357 createToken(modifiers, TokenTypes.LITERAL_PUBLIC);
358
359 assertWithMessage("invalid result")
360 .that(root.branchContains(TokenTypes.LITERAL_PUBLIC))
361 .isTrue();
362 assertWithMessage("invalid result")
363 .that(root.branchContains(TokenTypes.OBJBLOCK))
364 .isFalse();
365 }
366
367 private static DetailAstImpl createToken(DetailAstImpl root, int type) {
368 final DetailAstImpl result = new DetailAstImpl();
369 result.setType(type);
370 if (root != null) {
371 root.addChild(result);
372 }
373 return result;
374 }
375
376 @Test
377 public void testClearBranchTokenTypes() throws Exception {
378 final DetailAstImpl parent = new DetailAstImpl();
379 final DetailAstImpl child = new DetailAstImpl();
380 parent.setFirstChild(child);
381
382 final List<Consumer<DetailAstImpl>> clearBranchTokenTypesMethods = Arrays.asList(
383 child::setFirstChild,
384 child::setNextSibling,
385 child::addPreviousSibling,
386 child::addNextSibling,
387 child::addChild,
388 ast -> {
389 try {
390 TestUtil.invokeVoidMethod(child, "setParent", ast);
391 }
392
393 catch (Exception exception) {
394 throw new IllegalStateException(exception);
395 }
396 }
397 );
398
399 for (Consumer<DetailAstImpl> method : clearBranchTokenTypesMethods) {
400 final BitSet branchTokenTypes = TestUtil.invokeMethod(parent,
401 "getBranchTokenTypes", BitSet.class);
402 method.accept(null);
403 final BitSet branchTokenTypes2 = TestUtil.invokeMethod(parent,
404 "getBranchTokenTypes", BitSet.class);
405 assertWithMessage("Branch token types are not equal")
406 .that(branchTokenTypes)
407 .isEqualTo(branchTokenTypes2);
408 assertWithMessage("Branch token types should not be the same")
409 .that(branchTokenTypes)
410 .isNotSameInstanceAs(branchTokenTypes2);
411 }
412 }
413
414 @Test
415 public void testCacheBranchTokenTypes() {
416 final DetailAST root = new DetailAstImpl();
417 final BitSet bitSet = new BitSet();
418 bitSet.set(999);
419
420 TestUtil.setInternalState(root, "branchTokenTypes", bitSet);
421 assertWithMessage("Branch tokens has changed")
422 .that(root.branchContains(999))
423 .isTrue();
424 }
425
426 @Test
427 public void testClearChildCountCache() {
428 final DetailAstImpl parent = new DetailAstImpl();
429 final DetailAstImpl child = new DetailAstImpl();
430 parent.setFirstChild(child);
431
432 final List<Consumer<DetailAstImpl>> clearChildCountCacheMethods = Arrays.asList(
433 child::setNextSibling,
434 child::addPreviousSibling,
435 child::addNextSibling
436 );
437
438 for (Consumer<DetailAstImpl> method : clearChildCountCacheMethods) {
439 final int startCount = parent.getChildCount();
440 method.accept(null);
441 final int intermediateCount = TestUtil.getInternalState(parent, "childCount",
442 Integer.class);
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", Integer.class);
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())) {
688 bw.write(
689 """
690
691
692
693
694
695 """);
696 bw.write("class C {\n");
697 for (int i = 0; i <= 30000; i++) {
698 bw.write("// " + i + "\n");
699 }
700 bw.write("}\n");
701 }
702
703 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
704 verifyWithInlineConfigParser(file.getAbsolutePath(), expected);
705 }
706
707 @Test
708 public void testTreeStructure() throws Exception {
709 final List<File> files = getAllFiles(
710 new File("src/test/resources/com/puppycrawl/tools/checkstyle"));
711
712 for (File file : files) {
713 final String fileName = file.getCanonicalPath();
714 final DetailAST rootAST = JavaParser.parseFile(new File(fileName),
715 JavaParser.Options.WITHOUT_COMMENTS);
716
717 assertWithMessage("file must return a root node: %s", fileName)
718 .that(rootAST)
719 .isNotNull();
720
721 assertWithMessage("tree is valid")
722 .that(checkTree(fileName, rootAST))
723 .isTrue();
724 }
725 }
726
727 @Test
728 public void testToString() {
729 final DetailAstImpl ast = new DetailAstImpl();
730 ast.setText("text");
731 ast.setColumnNo(1);
732 ast.setLineNo(1);
733 assertWithMessage("Invalid text")
734 .that(ast.toString())
735 .isEqualTo("text[1x1]");
736 }
737
738 @Test
739 public void testRemoveChildren() {
740 final DetailAstImpl parent = new DetailAstImpl();
741 final DetailAstImpl child1 = new DetailAstImpl();
742 parent.setFirstChild(child1);
743 final DetailAstImpl child2 = new DetailAstImpl();
744 child1.setNextSibling(child2);
745
746 parent.removeChildren();
747
748 assertWithMessage("")
749 .that(parent.getChildCount())
750 .isEqualTo(0);
751 }
752
753 @Test
754 public void testAddChild() {
755 final DetailAstImpl grandParent = new DetailAstImpl();
756 grandParent.setText("grandparent");
757 final DetailAstImpl parent = new DetailAstImpl();
758 parent.setText("parent");
759 grandParent.setFirstChild(parent);
760
761 final DetailAstImpl child = new DetailAstImpl();
762 child.setText("child");
763 parent.setFirstChild(child);
764
765 final DetailAstImpl secondChild = new DetailAstImpl();
766 secondChild.setText("SecondChild");
767 parent.addChild(secondChild);
768
769 assertWithMessage("Invalid previous sibling")
770 .that(secondChild.getPreviousSibling())
771 .isEqualTo(child);
772 }
773
774 private static List<File> getAllFiles(File dir) {
775 final List<File> result = new ArrayList<>();
776
777 dir.listFiles(file -> {
778 if (file.isDirectory()) {
779 result.addAll(getAllFiles(file));
780 }
781 else if (file.getName().endsWith(".java")
782 && !NO_ROOT_FILES.contains(file.getName())) {
783 result.add(file);
784 }
785 return false;
786 });
787
788 return result;
789 }
790
791 private static boolean checkTree(final String filename, final DetailAST root) {
792 DetailAST curNode = root;
793 DetailAST parent = null;
794 DetailAST prev = null;
795 while (curNode != null) {
796 checkNode(curNode, parent, prev, filename, root);
797 DetailAST toVisit = curNode.getFirstChild();
798 if (toVisit == null) {
799 while (curNode != null && toVisit == null) {
800 toVisit = curNode.getNextSibling();
801 if (toVisit == null) {
802 curNode = curNode.getParent();
803 if (curNode != null) {
804 parent = curNode.getParent();
805 }
806 }
807 else {
808 prev = curNode;
809 curNode = toVisit;
810 }
811 }
812 }
813 else {
814 parent = curNode;
815 curNode = toVisit;
816 prev = null;
817 }
818 }
819
820 return true;
821 }
822
823 private static void checkNode(final DetailAST node,
824 final DetailAST parent,
825 final DetailAST prev,
826 final String filename,
827 final DetailAST root) {
828 final Object[] params = {
829 node, parent, prev, filename, root,
830 };
831 final MessageFormat badParentFormatter = new MessageFormat(
832 "Bad parent node={0} parent={1} filename={3} root={4}", Locale.ROOT);
833 final String badParentMsg = badParentFormatter.format(params);
834 assertWithMessage(badParentMsg)
835 .that(node.getParent())
836 .isEqualTo(parent);
837 final MessageFormat badPrevFormatter = new MessageFormat(
838 "Bad prev node={0} prev={2} parent={1} filename={3} root={4}", Locale.ROOT);
839 final String badPrevMsg = badPrevFormatter.format(params);
840 assertWithMessage(badPrevMsg)
841 .that(node.getPreviousSibling())
842 .isEqualTo(prev);
843 }
844
845 }