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