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