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 java.util.ArrayDeque;
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Optional;
27 import java.util.Queue;
28 import java.util.stream.Collectors;
29
30 import org.antlr.v4.runtime.BufferedTokenStream;
31 import org.antlr.v4.runtime.CommonTokenStream;
32 import org.antlr.v4.runtime.ParserRuleContext;
33 import org.antlr.v4.runtime.Token;
34 import org.antlr.v4.runtime.tree.ParseTree;
35 import org.antlr.v4.runtime.tree.TerminalNode;
36
37 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
38 import com.puppycrawl.tools.checkstyle.grammar.java.JavaLanguageLexer;
39 import com.puppycrawl.tools.checkstyle.grammar.java.JavaLanguageParser;
40 import com.puppycrawl.tools.checkstyle.grammar.java.JavaLanguageParserBaseVisitor;
41 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 public final class JavaAstVisitor extends JavaLanguageParserBaseVisitor<DetailAstImpl> {
100
101
102 private static final String LEFT_SHIFT = "<<";
103
104
105 private static final String UNSIGNED_RIGHT_SHIFT = ">>>";
106
107
108 private static final String RIGHT_SHIFT = ">>";
109
110
111
112
113
114 private static final int[] EXPRESSIONS_WITH_NO_EXPR_ROOT = {
115 TokenTypes.CTOR_CALL,
116 TokenTypes.SUPER_CTOR_CALL,
117 TokenTypes.LAMBDA,
118 };
119
120
121 private final BufferedTokenStream tokens;
122
123
124
125
126
127
128 public JavaAstVisitor(CommonTokenStream tokenStream) {
129 tokens = tokenStream;
130 }
131
132 @Override
133 public DetailAstImpl visitCompilationUnit(JavaLanguageParser.CompilationUnitContext ctx) {
134 final DetailAstImpl root;
135
136 final boolean isEmptyFile = ctx.children.size() == 1;
137 if (isEmptyFile) {
138 root = null;
139 }
140 else {
141
142 final List<ParseTree> children = ctx.children.subList(0, ctx.children.size() - 1);
143
144 final boolean isCompactSourceFile = children.stream()
145 .anyMatch(JavaAstVisitor::isCompactMemberDeclaration);
146
147 if (isCompactSourceFile) {
148 root = createImaginary(TokenTypes.COMPACT_COMPILATION_UNIT);
149 }
150 else {
151 root = createImaginary(TokenTypes.COMPILATION_UNIT);
152 }
153 processChildren(root, children);
154 }
155 return root;
156 }
157
158
159
160
161
162
163
164 private static boolean isCompactMemberDeclaration(ParseTree child) {
165 return child instanceof JavaLanguageParser.CompactMemberDeclarationContext;
166 }
167
168 @Override
169 public DetailAstImpl visitPackageDeclaration(
170 JavaLanguageParser.PackageDeclarationContext ctx) {
171 final DetailAstImpl packageDeclaration =
172 create(TokenTypes.PACKAGE_DEF, (Token) ctx.LITERAL_PACKAGE().getPayload());
173 packageDeclaration.addChild(visit(ctx.annotations()));
174 packageDeclaration.addChild(visit(ctx.qualifiedName()));
175 packageDeclaration.addChild(create(ctx.SEMI()));
176 return packageDeclaration;
177 }
178
179 @Override
180 public DetailAstImpl visitImportDec(JavaLanguageParser.ImportDecContext ctx) {
181 final DetailAstImpl importRoot = create(ctx.start);
182
183
184 final TerminalNode literalStaticNode = ctx.LITERAL_STATIC();
185 if (literalStaticNode != null) {
186 importRoot.setType(TokenTypes.STATIC_IMPORT);
187 importRoot.addChild(create(literalStaticNode));
188 }
189
190
191 final TerminalNode literalModuleNode = ctx.LITERAL_MODULE();
192 if (literalModuleNode != null) {
193 importRoot.setType(TokenTypes.MODULE_IMPORT);
194 importRoot.addChild(create(literalModuleNode));
195 }
196
197
198 final boolean isStarImport = ctx.STAR() != null;
199 if (isStarImport) {
200 final DetailAstImpl dot = create(ctx.DOT());
201 dot.addChild(visit(ctx.qualifiedName()));
202 dot.addChild(create(ctx.STAR()));
203 importRoot.addChild(dot);
204 }
205 else {
206 importRoot.addChild(visit(ctx.qualifiedName()));
207 }
208
209 importRoot.addChild(create(ctx.SEMI()));
210 return importRoot;
211 }
212
213 @Override
214 public DetailAstImpl visitSingleSemiImport(JavaLanguageParser.SingleSemiImportContext ctx) {
215 return create(ctx.SEMI());
216 }
217
218 @Override
219 public DetailAstImpl visitModuleDeclaration(
220 JavaLanguageParser.ModuleDeclarationContext ctx) {
221 final DetailAstImpl moduleDeclaration = createImaginary(TokenTypes.MODULE_DEF);
222 processChildren(moduleDeclaration, ctx.children);
223 return moduleDeclaration;
224 }
225
226 @Override
227 public DetailAstImpl visitDirectiveBlock(JavaLanguageParser.DirectiveBlockContext ctx) {
228 final DetailAstImpl directiveBlock = createImaginary(TokenTypes.DIRECTIVE_BLOCK);
229 processChildren(directiveBlock, ctx.children);
230 return directiveBlock;
231 }
232
233 @Override
234 public DetailAstImpl visitRequiresDirective(
235 JavaLanguageParser.RequiresDirectiveContext ctx) {
236 return createNodeFromFirstToken(TokenTypes.REQUIRES, ctx);
237 }
238
239 @Override
240 public DetailAstImpl visitExportsDirective(
241 JavaLanguageParser.ExportsDirectiveContext ctx) {
242 return createNodeFromFirstToken(TokenTypes.EXPORTS, ctx);
243 }
244
245 @Override
246 public DetailAstImpl visitOpensDirective(JavaLanguageParser.OpensDirectiveContext ctx) {
247 return createNodeFromFirstToken(TokenTypes.OPENS, ctx);
248 }
249
250 @Override
251 public DetailAstImpl visitUsesDirective(JavaLanguageParser.UsesDirectiveContext ctx) {
252 return createNodeFromFirstToken(TokenTypes.USES, ctx);
253 }
254
255 @Override
256 public DetailAstImpl visitProvidesDirective(
257 JavaLanguageParser.ProvidesDirectiveContext ctx) {
258 return createNodeFromFirstToken(TokenTypes.PROVIDES, ctx);
259 }
260
261 @Override
262 public DetailAstImpl visitRequiresModifier(
263 JavaLanguageParser.RequiresModifierContext ctx) {
264 return flattenedTree(ctx);
265 }
266
267 @Override
268 public DetailAstImpl visitToClause(JavaLanguageParser.ToClauseContext ctx) {
269 return createNodeFromFirstToken(TokenTypes.TO, ctx);
270 }
271
272 @Override
273 public DetailAstImpl visitWithClause(JavaLanguageParser.WithClauseContext ctx) {
274 return createNodeFromFirstToken(TokenTypes.WITH, ctx);
275 }
276
277 @Override
278 public DetailAstImpl visitTypeDeclaration(JavaLanguageParser.TypeDeclarationContext ctx) {
279 final DetailAstImpl typeDeclaration;
280 if (ctx.type == null) {
281 typeDeclaration = create(ctx.semi.getFirst());
282 ctx.semi.subList(1, ctx.semi.size())
283 .forEach(semi -> addLastSibling(typeDeclaration, create(semi)));
284 }
285 else {
286 typeDeclaration = visit(ctx.type);
287 }
288 return typeDeclaration;
289 }
290
291 @Override
292 public DetailAstImpl visitModifier(JavaLanguageParser.ModifierContext ctx) {
293 return flattenedTree(ctx);
294 }
295
296 @Override
297 public DetailAstImpl visitVariableModifier(JavaLanguageParser.VariableModifierContext ctx) {
298 return flattenedTree(ctx);
299 }
300
301 @Override
302 public DetailAstImpl visitClassDeclaration(JavaLanguageParser.ClassDeclarationContext ctx) {
303 return createTypeDeclaration(ctx, TokenTypes.CLASS_DEF, ctx.mods);
304 }
305
306 @Override
307 public DetailAstImpl visitRecordDeclaration(JavaLanguageParser.RecordDeclarationContext ctx) {
308 return createTypeDeclaration(ctx, TokenTypes.RECORD_DEF, ctx.mods);
309 }
310
311 @Override
312 public DetailAstImpl visitRecordComponentsList(
313 JavaLanguageParser.RecordComponentsListContext ctx) {
314 final DetailAstImpl lparen = create(ctx.LPAREN());
315
316
317 if (ctx.recordComponents() == null) {
318 addLastSibling(lparen, createImaginary(TokenTypes.RECORD_COMPONENTS));
319 }
320 else {
321 addLastSibling(lparen, visit(ctx.recordComponents()));
322 }
323 addLastSibling(lparen, create(ctx.RPAREN()));
324 return lparen;
325 }
326
327 @Override
328 public DetailAstImpl visitRecordComponents(JavaLanguageParser.RecordComponentsContext ctx) {
329 final DetailAstImpl recordComponents = createImaginary(TokenTypes.RECORD_COMPONENTS);
330 processChildren(recordComponents, ctx.children);
331 return recordComponents;
332 }
333
334 @Override
335 public DetailAstImpl visitRecordComponent(JavaLanguageParser.RecordComponentContext ctx) {
336 final DetailAstImpl recordComponent = createImaginary(TokenTypes.RECORD_COMPONENT_DEF);
337 processChildren(recordComponent, ctx.children);
338 return recordComponent;
339 }
340
341 @Override
342 public DetailAstImpl visitLastRecordComponent(
343 JavaLanguageParser.LastRecordComponentContext ctx) {
344 final DetailAstImpl recordComponent = createImaginary(TokenTypes.RECORD_COMPONENT_DEF);
345 processChildren(recordComponent, ctx.children);
346 return recordComponent;
347 }
348
349 @Override
350 public DetailAstImpl visitRecordBody(JavaLanguageParser.RecordBodyContext ctx) {
351 final DetailAstImpl objBlock = createImaginary(TokenTypes.OBJBLOCK);
352 processChildren(objBlock, ctx.children);
353 return objBlock;
354 }
355
356 @Override
357 public DetailAstImpl visitCompactConstructorDeclaration(
358 JavaLanguageParser.CompactConstructorDeclarationContext ctx) {
359 final DetailAstImpl compactConstructor = createImaginary(TokenTypes.COMPACT_CTOR_DEF);
360 compactConstructor.addChild(createModifiers(ctx.mods));
361 compactConstructor.addChild(visit(ctx.id()));
362 compactConstructor.addChild(visit(ctx.constructorBlock()));
363 return compactConstructor;
364 }
365
366 @Override
367 public DetailAstImpl visitClassExtends(JavaLanguageParser.ClassExtendsContext ctx) {
368 final DetailAstImpl classExtends = create(ctx.EXTENDS_CLAUSE());
369 classExtends.addChild(visit(ctx.type));
370 return classExtends;
371 }
372
373 @Override
374 public DetailAstImpl visitImplementsClause(JavaLanguageParser.ImplementsClauseContext ctx) {
375 final DetailAstImpl classImplements = create(TokenTypes.IMPLEMENTS_CLAUSE,
376 (Token) ctx.LITERAL_IMPLEMENTS().getPayload());
377 classImplements.addChild(visit(ctx.typeList()));
378 return classImplements;
379 }
380
381 @Override
382 public DetailAstImpl visitTypeParameters(JavaLanguageParser.TypeParametersContext ctx) {
383 final DetailAstImpl typeParameters = createImaginary(TokenTypes.TYPE_PARAMETERS);
384 typeParameters.addChild(create(TokenTypes.GENERIC_START, (Token) ctx.LT().getPayload()));
385
386 processChildren(typeParameters, ctx.children.subList(1, ctx.children.size() - 1));
387 typeParameters.addChild(create(TokenTypes.GENERIC_END, (Token) ctx.GT().getPayload()));
388 return typeParameters;
389 }
390
391 @Override
392 public DetailAstImpl visitTypeParameter(JavaLanguageParser.TypeParameterContext ctx) {
393 final DetailAstImpl typeParameter = createImaginary(TokenTypes.TYPE_PARAMETER);
394 processChildren(typeParameter, ctx.children);
395 return typeParameter;
396 }
397
398 @Override
399 public DetailAstImpl visitTypeUpperBounds(JavaLanguageParser.TypeUpperBoundsContext ctx) {
400
401 final DetailAstImpl typeUpperBounds = create(TokenTypes.TYPE_UPPER_BOUNDS,
402 (Token) ctx.EXTENDS_CLAUSE().getPayload());
403
404 processChildren(typeUpperBounds, ctx.children.subList(1, ctx.children.size()));
405 return typeUpperBounds;
406 }
407
408 @Override
409 public DetailAstImpl visitTypeBound(JavaLanguageParser.TypeBoundContext ctx) {
410 final DetailAstImpl typeBoundType = visit(ctx.typeBoundType(0));
411 final Iterator<JavaLanguageParser.TypeBoundTypeContext> typeBoundTypeIterator =
412 ctx.typeBoundType().listIterator(1);
413 ctx.BAND().forEach(band -> {
414 addLastSibling(typeBoundType, create(TokenTypes.TYPE_EXTENSION_AND,
415 (Token) band.getPayload()));
416 addLastSibling(typeBoundType, visit(typeBoundTypeIterator.next()));
417 });
418 return typeBoundType;
419 }
420
421 @Override
422 public DetailAstImpl visitTypeBoundType(JavaLanguageParser.TypeBoundTypeContext ctx) {
423 return flattenedTree(ctx);
424 }
425
426 @Override
427 public DetailAstImpl visitEnumDeclaration(JavaLanguageParser.EnumDeclarationContext ctx) {
428 return createTypeDeclaration(ctx, TokenTypes.ENUM_DEF, ctx.mods);
429 }
430
431 @Override
432 public DetailAstImpl visitEnumBody(JavaLanguageParser.EnumBodyContext ctx) {
433 final DetailAstImpl objBlock = createImaginary(TokenTypes.OBJBLOCK);
434 processChildren(objBlock, ctx.children);
435 return objBlock;
436 }
437
438 @Override
439 public DetailAstImpl visitEnumConstants(JavaLanguageParser.EnumConstantsContext ctx) {
440 return flattenedTree(ctx);
441 }
442
443 @Override
444 public DetailAstImpl visitEnumConstant(JavaLanguageParser.EnumConstantContext ctx) {
445 final DetailAstImpl enumConstant =
446 createImaginary(TokenTypes.ENUM_CONSTANT_DEF);
447 processChildren(enumConstant, ctx.children);
448 return enumConstant;
449 }
450
451 @Override
452 public DetailAstImpl visitEnumBodyDeclarations(
453 JavaLanguageParser.EnumBodyDeclarationsContext ctx) {
454 return flattenedTree(ctx);
455 }
456
457 @Override
458 public DetailAstImpl visitInterfaceDeclaration(
459 JavaLanguageParser.InterfaceDeclarationContext ctx) {
460 return createTypeDeclaration(ctx, TokenTypes.INTERFACE_DEF, ctx.mods);
461 }
462
463 @Override
464 public DetailAstImpl visitInterfaceExtends(JavaLanguageParser.InterfaceExtendsContext ctx) {
465 final DetailAstImpl interfaceExtends = create(ctx.EXTENDS_CLAUSE());
466 interfaceExtends.addChild(visit(ctx.typeList()));
467 return interfaceExtends;
468 }
469
470 @Override
471 public DetailAstImpl visitClassBody(JavaLanguageParser.ClassBodyContext ctx) {
472 final DetailAstImpl objBlock = createImaginary(TokenTypes.OBJBLOCK);
473 processChildren(objBlock, ctx.children);
474 return objBlock;
475 }
476
477 @Override
478 public DetailAstImpl visitInterfaceBody(JavaLanguageParser.InterfaceBodyContext ctx) {
479 final DetailAstImpl objBlock = createImaginary(TokenTypes.OBJBLOCK);
480 processChildren(objBlock, ctx.children);
481 return objBlock;
482 }
483
484 @Override
485 public DetailAstImpl visitEmptyClass(JavaLanguageParser.EmptyClassContext ctx) {
486 return flattenedTree(ctx);
487 }
488
489 @Override
490 public DetailAstImpl visitClassBlock(JavaLanguageParser.ClassBlockContext ctx) {
491 final DetailAstImpl classBlock;
492 if (ctx.LITERAL_STATIC() == null) {
493
494 classBlock = createImaginary(TokenTypes.INSTANCE_INIT);
495 }
496 else {
497 classBlock = create(TokenTypes.STATIC_INIT, (Token) ctx.LITERAL_STATIC().getPayload());
498 classBlock.setText(TokenUtil.getTokenName(TokenTypes.STATIC_INIT));
499 }
500 classBlock.addChild(visit(ctx.block()));
501 return classBlock;
502 }
503
504 @Override
505 public DetailAstImpl visitMethodDeclaration(JavaLanguageParser.MethodDeclarationContext ctx) {
506 final DetailAstImpl methodDef = createImaginary(TokenTypes.METHOD_DEF);
507 methodDef.addChild(createModifiers(ctx.mods));
508
509
510 processChildren(methodDef, ctx.children.stream()
511 .filter(child -> !(child instanceof JavaLanguageParser.ArrayDeclaratorContext))
512 .toList());
513
514
515 final DetailAstImpl typeAst = (DetailAstImpl) methodDef.findFirstToken(TokenTypes.TYPE);
516 ctx.cStyleArrDec.forEach(child -> typeAst.addChild(visit(child)));
517
518 return methodDef;
519 }
520
521 @Override
522 public DetailAstImpl visitMethodBody(JavaLanguageParser.MethodBodyContext ctx) {
523 return flattenedTree(ctx);
524 }
525
526 @Override
527 public DetailAstImpl visitThrowsList(JavaLanguageParser.ThrowsListContext ctx) {
528 final DetailAstImpl throwsRoot = create(ctx.LITERAL_THROWS());
529 throwsRoot.addChild(visit(ctx.qualifiedNameList()));
530 return throwsRoot;
531 }
532
533 @Override
534 public DetailAstImpl visitConstructorDeclaration(
535 JavaLanguageParser.ConstructorDeclarationContext ctx) {
536 final DetailAstImpl constructorDeclaration = createImaginary(TokenTypes.CTOR_DEF);
537 constructorDeclaration.addChild(createModifiers(ctx.mods));
538 processChildren(constructorDeclaration, ctx.children);
539 return constructorDeclaration;
540 }
541
542 @Override
543 public DetailAstImpl visitFieldDeclaration(JavaLanguageParser.FieldDeclarationContext ctx) {
544 final DetailAstImpl dummyNode = new DetailAstImpl();
545
546
547
548 processChildren(dummyNode, ctx.children.subList(1, ctx.children.size() - 1));
549 dummyNode.getFirstChild().addChild(create(ctx.SEMI()));
550 return dummyNode.getFirstChild();
551 }
552
553 @Override
554 public DetailAstImpl visitInterfaceBodyDeclaration(
555 JavaLanguageParser.InterfaceBodyDeclarationContext ctx) {
556 final DetailAstImpl returnTree;
557 if (ctx.SEMI() == null) {
558 returnTree = visit(ctx.interfaceMemberDeclaration());
559 }
560 else {
561 returnTree = create(ctx.SEMI());
562 }
563 return returnTree;
564 }
565
566 @Override
567 public DetailAstImpl visitInterfaceMethodDeclaration(
568 JavaLanguageParser.InterfaceMethodDeclarationContext ctx) {
569 final DetailAstImpl methodDef = createImaginary(TokenTypes.METHOD_DEF);
570 methodDef.addChild(createModifiers(ctx.mods));
571
572
573 final List<ParseTree> children = ctx.children
574 .stream()
575 .filter(child -> !(child instanceof JavaLanguageParser.ArrayDeclaratorContext))
576 .toList();
577 processChildren(methodDef, children);
578
579
580 final DetailAstImpl typeAst = (DetailAstImpl) methodDef.findFirstToken(TokenTypes.TYPE);
581 ctx.cStyleArrDec.forEach(child -> typeAst.addChild(visit(child)));
582
583 return methodDef;
584 }
585
586 @Override
587 public DetailAstImpl visitVariableDeclarators(
588 JavaLanguageParser.VariableDeclaratorsContext ctx) {
589 return flattenedTree(ctx);
590 }
591
592 @Override
593 public DetailAstImpl visitVariableDeclarator(
594 JavaLanguageParser.VariableDeclaratorContext ctx) {
595 final DetailAstImpl variableDef = createImaginary(TokenTypes.VARIABLE_DEF);
596 variableDef.addChild(createModifiers(ctx.mods));
597
598 final DetailAstImpl type = visit(ctx.type);
599 variableDef.addChild(type);
600 variableDef.addChild(visit(ctx.id()));
601
602
603 ctx.arrayDeclarator().forEach(child -> type.addChild(visit(child)));
604
605
606 final TerminalNode assignNode = ctx.ASSIGN();
607 if (assignNode != null) {
608 final DetailAstImpl assign = create(assignNode);
609 variableDef.addChild(assign);
610 assign.addChild(visit(ctx.variableInitializer()));
611 }
612 return variableDef;
613 }
614
615 @Override
616 public DetailAstImpl visitVariableDeclaratorId(
617 JavaLanguageParser.VariableDeclaratorIdContext ctx) {
618 final DetailAstImpl root = new DetailAstImpl();
619 root.addChild(createModifiers(ctx.mods));
620 final DetailAstImpl type = visit(ctx.type);
621 root.addChild(type);
622
623 final DetailAstImpl declaratorId;
624 if (ctx.LITERAL_THIS() == null) {
625 declaratorId = visit(ctx.qualifiedName());
626 }
627 else if (ctx.DOT() == null) {
628 declaratorId = create(ctx.LITERAL_THIS());
629 }
630 else {
631 declaratorId = create(ctx.DOT());
632 declaratorId.addChild(visit(ctx.qualifiedName()));
633 declaratorId.addChild(create(ctx.LITERAL_THIS()));
634 }
635
636 root.addChild(declaratorId);
637 ctx.arrayDeclarator().forEach(child -> type.addChild(visit(child)));
638
639 return root.getFirstChild();
640 }
641
642 @Override
643 public DetailAstImpl visitArrayInitializer(JavaLanguageParser.ArrayInitializerContext ctx) {
644 final DetailAstImpl arrayInitializer = create(TokenTypes.ARRAY_INIT, ctx.start);
645
646 processChildren(arrayInitializer, ctx.children.subList(1, ctx.children.size()));
647 return arrayInitializer;
648 }
649
650 @Override
651 public DetailAstImpl visitClassOrInterfaceType(
652 JavaLanguageParser.ClassOrInterfaceTypeContext ctx) {
653 final DetailAstPair currentAST = new DetailAstPair();
654 DetailAstPair.addAstChild(currentAST, visit(ctx.id()));
655 DetailAstPair.addAstChild(currentAST, visit(ctx.typeArguments()));
656
657
658 for (ParserRuleContext extendedContext : ctx.extended) {
659 final DetailAstImpl dot = create(extendedContext.start);
660 DetailAstPair.makeAstRoot(currentAST, dot);
661 extendedContext.children
662 .forEach(child -> DetailAstPair.addAstChild(currentAST, visit(child)));
663 }
664
665
666 final DetailAstImpl returnTree;
667 if (ctx.createImaginaryNode) {
668 returnTree = createImaginary(TokenTypes.TYPE);
669 returnTree.addChild(currentAST.root);
670 }
671 else {
672 returnTree = currentAST.root;
673 }
674 return returnTree;
675 }
676
677 @Override
678 public DetailAstImpl visitSimpleTypeArgument(
679 JavaLanguageParser.SimpleTypeArgumentContext ctx) {
680 final DetailAstImpl typeArgument =
681 createImaginary(TokenTypes.TYPE_ARGUMENT);
682 typeArgument.addChild(visit(ctx.typeType()));
683 return typeArgument;
684 }
685
686 @Override
687 public DetailAstImpl visitWildCardTypeArgument(
688 JavaLanguageParser.WildCardTypeArgumentContext ctx) {
689 final DetailAstImpl typeArgument = createImaginary(TokenTypes.TYPE_ARGUMENT);
690 typeArgument.addChild(visit(ctx.annotations()));
691 typeArgument.addChild(create(TokenTypes.WILDCARD_TYPE,
692 (Token) ctx.QUESTION().getPayload()));
693
694 if (ctx.upperBound != null) {
695 final DetailAstImpl upperBound = create(TokenTypes.TYPE_UPPER_BOUNDS, ctx.upperBound);
696 upperBound.addChild(visit(ctx.typeType()));
697 typeArgument.addChild(upperBound);
698 }
699 else if (ctx.lowerBound != null) {
700 final DetailAstImpl lowerBound = create(TokenTypes.TYPE_LOWER_BOUNDS, ctx.lowerBound);
701 lowerBound.addChild(visit(ctx.typeType()));
702 typeArgument.addChild(lowerBound);
703 }
704
705 return typeArgument;
706 }
707
708 @Override
709 public DetailAstImpl visitQualifiedNameList(JavaLanguageParser.QualifiedNameListContext ctx) {
710 return flattenedTree(ctx);
711 }
712
713 @Override
714 public DetailAstImpl visitFormalParameters(JavaLanguageParser.FormalParametersContext ctx) {
715 final DetailAstImpl lparen = create(ctx.LPAREN());
716
717
718 if (ctx.formalParameterList() == null) {
719 addLastSibling(lparen, createImaginary(TokenTypes.PARAMETERS));
720 }
721 else {
722 addLastSibling(lparen, visit(ctx.formalParameterList()));
723 }
724 addLastSibling(lparen, create(ctx.RPAREN()));
725 return lparen;
726 }
727
728 @Override
729 public DetailAstImpl visitFormalParameterList(
730 JavaLanguageParser.FormalParameterListContext ctx) {
731 final DetailAstImpl parameters = createImaginary(TokenTypes.PARAMETERS);
732 processChildren(parameters, ctx.children);
733 return parameters;
734 }
735
736 @Override
737 public DetailAstImpl visitFormalParameter(JavaLanguageParser.FormalParameterContext ctx) {
738 final DetailAstImpl variableDeclaratorId =
739 visitVariableDeclaratorId(ctx.variableDeclaratorId());
740 final DetailAstImpl parameterDef = createImaginary(TokenTypes.PARAMETER_DEF);
741 parameterDef.addChild(variableDeclaratorId);
742 return parameterDef;
743 }
744
745 @Override
746 public DetailAstImpl visitLastFormalParameter(
747 JavaLanguageParser.LastFormalParameterContext ctx) {
748 final DetailAstImpl parameterDef =
749 createImaginary(TokenTypes.PARAMETER_DEF);
750 parameterDef.addChild(visit(ctx.variableDeclaratorId()));
751 final DetailAstImpl ident = (DetailAstImpl) parameterDef.findFirstToken(TokenTypes.IDENT);
752 ident.addPreviousSibling(create(ctx.ELLIPSIS()));
753
754 final DetailAstImpl type = (DetailAstImpl) parameterDef.findFirstToken(TokenTypes.TYPE);
755 type.addChild(visit(ctx.annotations()));
756 return parameterDef;
757 }
758
759 @Override
760 public DetailAstImpl visitQualifiedName(JavaLanguageParser.QualifiedNameContext ctx) {
761 final DetailAstImpl ast = visit(ctx.id());
762 final DetailAstPair currentAst = new DetailAstPair();
763 DetailAstPair.addAstChild(currentAst, ast);
764
765 for (ParserRuleContext extendedContext : ctx.extended) {
766 final DetailAstImpl dot = create(extendedContext.start);
767 DetailAstPair.makeAstRoot(currentAst, dot);
768 final List<ParseTree> childList = extendedContext
769 .children.subList(1, extendedContext.children.size());
770 processChildren(dot, childList);
771 }
772 return currentAst.getRoot();
773 }
774
775 @Override
776 public DetailAstImpl visitLiteral(JavaLanguageParser.LiteralContext ctx) {
777 return flattenedTree(ctx);
778 }
779
780 @Override
781 public DetailAstImpl visitIntegerLiteral(JavaLanguageParser.IntegerLiteralContext ctx) {
782 final int[] longTypes = {
783 JavaLanguageLexer.DECIMAL_LITERAL_LONG,
784 JavaLanguageLexer.HEX_LITERAL_LONG,
785 JavaLanguageLexer.OCT_LITERAL_LONG,
786 JavaLanguageLexer.BINARY_LITERAL_LONG,
787 };
788
789 final int tokenType;
790 if (TokenUtil.isOfType(ctx.start.getType(), longTypes)) {
791 tokenType = TokenTypes.NUM_LONG;
792 }
793 else {
794 tokenType = TokenTypes.NUM_INT;
795 }
796
797 return create(tokenType, ctx.start);
798 }
799
800 @Override
801 public DetailAstImpl visitFloatLiteral(JavaLanguageParser.FloatLiteralContext ctx) {
802 final DetailAstImpl floatLiteral;
803 if (TokenUtil.isOfType(ctx.start.getType(),
804 JavaLanguageLexer.DOUBLE_LITERAL, JavaLanguageLexer.HEX_DOUBLE_LITERAL)) {
805 floatLiteral = create(TokenTypes.NUM_DOUBLE, ctx.start);
806 }
807 else {
808 floatLiteral = create(TokenTypes.NUM_FLOAT, ctx.start);
809 }
810 return floatLiteral;
811 }
812
813 @Override
814 public DetailAstImpl visitTextBlockLiteral(JavaLanguageParser.TextBlockLiteralContext ctx) {
815 final DetailAstImpl textBlockLiteralBegin = create(ctx.TEXT_BLOCK_LITERAL_BEGIN());
816 textBlockLiteralBegin.addChild(create(ctx.TEXT_BLOCK_CONTENT()));
817 textBlockLiteralBegin.addChild(create(ctx.TEXT_BLOCK_LITERAL_END()));
818 return textBlockLiteralBegin;
819 }
820
821 @Override
822 public DetailAstImpl visitAnnotations(JavaLanguageParser.AnnotationsContext ctx) {
823 final DetailAstImpl annotations;
824
825 if (!ctx.createImaginaryNode && ctx.anno.isEmpty()) {
826
827 annotations = null;
828 }
829 else {
830
831 annotations = createImaginary(TokenTypes.ANNOTATIONS);
832 processChildren(annotations, ctx.anno);
833 }
834
835 return annotations;
836 }
837
838 @Override
839 public DetailAstImpl visitAnnotation(JavaLanguageParser.AnnotationContext ctx) {
840 final DetailAstImpl annotation = createImaginary(TokenTypes.ANNOTATION);
841 processChildren(annotation, ctx.children);
842 return annotation;
843 }
844
845 @Override
846 public DetailAstImpl visitElementValuePairs(JavaLanguageParser.ElementValuePairsContext ctx) {
847 return flattenedTree(ctx);
848 }
849
850 @Override
851 public DetailAstImpl visitElementValuePair(JavaLanguageParser.ElementValuePairContext ctx) {
852 final DetailAstImpl elementValuePair =
853 createImaginary(TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR);
854 processChildren(elementValuePair, ctx.children);
855 return elementValuePair;
856 }
857
858 @Override
859 public DetailAstImpl visitElementValue(JavaLanguageParser.ElementValueContext ctx) {
860 return flattenedTree(ctx);
861 }
862
863 @Override
864 public DetailAstImpl visitElementValueArrayInitializer(
865 JavaLanguageParser.ElementValueArrayInitializerContext ctx) {
866 final DetailAstImpl arrayInit =
867 create(TokenTypes.ANNOTATION_ARRAY_INIT, (Token) ctx.LCURLY().getPayload());
868 processChildren(arrayInit, ctx.children.subList(1, ctx.children.size()));
869 return arrayInit;
870 }
871
872 @Override
873 public DetailAstImpl visitAnnotationTypeDeclaration(
874 JavaLanguageParser.AnnotationTypeDeclarationContext ctx) {
875 return createTypeDeclaration(ctx, TokenTypes.ANNOTATION_DEF, ctx.mods);
876 }
877
878 @Override
879 public DetailAstImpl visitAnnotationTypeBody(
880 JavaLanguageParser.AnnotationTypeBodyContext ctx) {
881 final DetailAstImpl objBlock = createImaginary(TokenTypes.OBJBLOCK);
882 processChildren(objBlock, ctx.children);
883 return objBlock;
884 }
885
886 @Override
887 public DetailAstImpl visitAnnotationTypeElementDeclaration(
888 JavaLanguageParser.AnnotationTypeElementDeclarationContext ctx) {
889 final DetailAstImpl returnTree;
890 if (ctx.SEMI() == null) {
891 returnTree = visit(ctx.annotationTypeElementRest());
892 }
893 else {
894 returnTree = create(ctx.SEMI());
895 }
896 return returnTree;
897 }
898
899 @Override
900 public DetailAstImpl visitAnnotationField(JavaLanguageParser.AnnotationFieldContext ctx) {
901 final DetailAstImpl dummyNode = new DetailAstImpl();
902
903
904 processChildren(dummyNode, List.of(ctx.children.get(1)));
905
906
907 dummyNode.getFirstChild().addChild(create(ctx.SEMI()));
908 return dummyNode.getFirstChild();
909 }
910
911 @Override
912 public DetailAstImpl visitAnnotationType(JavaLanguageParser.AnnotationTypeContext ctx) {
913 return flattenedTree(ctx);
914 }
915
916 @Override
917 public DetailAstImpl visitAnnotationMethodRest(
918 JavaLanguageParser.AnnotationMethodRestContext ctx) {
919 final DetailAstImpl annotationFieldDef =
920 createImaginary(TokenTypes.ANNOTATION_FIELD_DEF);
921 annotationFieldDef.addChild(createModifiers(ctx.mods));
922 annotationFieldDef.addChild(visit(ctx.type));
923
924
925 processChildren(annotationFieldDef, ctx.children.stream()
926 .filter(child -> !(child instanceof JavaLanguageParser.ArrayDeclaratorContext))
927 .toList());
928
929
930 final DetailAstImpl typeAst =
931 (DetailAstImpl) annotationFieldDef.findFirstToken(TokenTypes.TYPE);
932 ctx.cStyleArrDec.forEach(child -> typeAst.addChild(visit(child)));
933
934 return annotationFieldDef;
935 }
936
937 @Override
938 public DetailAstImpl visitDefaultValue(JavaLanguageParser.DefaultValueContext ctx) {
939 final DetailAstImpl defaultValue = create(ctx.LITERAL_DEFAULT());
940 defaultValue.addChild(visit(ctx.elementValue()));
941 return defaultValue;
942 }
943
944 @Override
945 public DetailAstImpl visitConstructorBlock(JavaLanguageParser.ConstructorBlockContext ctx) {
946 final DetailAstImpl slist = create(TokenTypes.SLIST, ctx.start);
947
948 processChildren(slist, ctx.children.subList(1, ctx.children.size()));
949 return slist;
950 }
951
952 @Override
953 public DetailAstImpl visitExplicitCtorCall(JavaLanguageParser.ExplicitCtorCallContext ctx) {
954 final DetailAstImpl root;
955 if (ctx.LITERAL_THIS() == null) {
956 root = create(TokenTypes.SUPER_CTOR_CALL, (Token) ctx.LITERAL_SUPER().getPayload());
957 }
958 else {
959 root = create(TokenTypes.CTOR_CALL, (Token) ctx.LITERAL_THIS().getPayload());
960 }
961 root.addChild(visit(ctx.typeArguments()));
962 root.addChild(visit(ctx.arguments()));
963 root.addChild(create(ctx.SEMI()));
964 return root;
965 }
966
967 @Override
968 public DetailAstImpl visitPrimaryCtorCall(JavaLanguageParser.PrimaryCtorCallContext ctx) {
969 final DetailAstImpl primaryCtorCall = create(TokenTypes.SUPER_CTOR_CALL,
970 (Token) ctx.LITERAL_SUPER().getPayload());
971
972 processChildren(primaryCtorCall, ctx.children.stream()
973 .filter(child -> !child.equals(ctx.LITERAL_SUPER()))
974 .toList());
975 return primaryCtorCall;
976 }
977
978 @Override
979 public DetailAstImpl visitBlock(JavaLanguageParser.BlockContext ctx) {
980 final DetailAstImpl slist = create(TokenTypes.SLIST, ctx.start);
981
982 processChildren(slist, ctx.children.subList(1, ctx.children.size()));
983 return slist;
984 }
985
986 @Override
987 public DetailAstImpl visitLocalVar(JavaLanguageParser.LocalVarContext ctx) {
988 return flattenedTree(ctx);
989 }
990
991 @Override
992 public DetailAstImpl visitBlockStat(JavaLanguageParser.BlockStatContext ctx) {
993 return flattenedTree(ctx);
994 }
995
996 @Override
997 public DetailAstImpl visitAssertExp(JavaLanguageParser.AssertExpContext ctx) {
998 final DetailAstImpl assertExp = create(ctx.ASSERT());
999
1000 processChildren(assertExp, ctx.children.subList(1, ctx.children.size()));
1001 return assertExp;
1002 }
1003
1004 @Override
1005 public DetailAstImpl visitIfStat(JavaLanguageParser.IfStatContext ctx) {
1006 final DetailAstImpl ifStat = create(ctx.LITERAL_IF());
1007
1008 processChildren(ifStat, ctx.children.subList(1, ctx.children.size()));
1009 return ifStat;
1010 }
1011
1012 @Override
1013 public DetailAstImpl visitForStat(JavaLanguageParser.ForStatContext ctx) {
1014 final DetailAstImpl forInit = create(ctx.start);
1015
1016 processChildren(forInit, ctx.children.subList(1, ctx.children.size()));
1017 return forInit;
1018 }
1019
1020 @Override
1021 public DetailAstImpl visitWhileStat(JavaLanguageParser.WhileStatContext ctx) {
1022 final DetailAstImpl whileStatement = create(ctx.start);
1023
1024 processChildren(whileStatement, ctx.children.subList(1, ctx.children.size()));
1025 return whileStatement;
1026 }
1027
1028 @Override
1029 public DetailAstImpl visitDoStat(JavaLanguageParser.DoStatContext ctx) {
1030 final DetailAstImpl doStatement = create(ctx.start);
1031
1032 doStatement.addChild(visit(ctx.statement()));
1033
1034 doStatement.addChild(create(TokenTypes.DO_WHILE, (Token) ctx.LITERAL_WHILE().getPayload()));
1035 doStatement.addChild(visit(ctx.parExpression()));
1036 doStatement.addChild(create(ctx.SEMI()));
1037 return doStatement;
1038 }
1039
1040 @Override
1041 public DetailAstImpl visitTryStat(JavaLanguageParser.TryStatContext ctx) {
1042 final DetailAstImpl tryStat = create(ctx.start);
1043
1044 processChildren(tryStat, ctx.children.subList(1, ctx.children.size()));
1045 return tryStat;
1046 }
1047
1048 @Override
1049 public DetailAstImpl visitTryWithResourceStat(
1050 JavaLanguageParser.TryWithResourceStatContext ctx) {
1051 final DetailAstImpl tryWithResources = create(ctx.LITERAL_TRY());
1052
1053 processChildren(tryWithResources, ctx.children.subList(1, ctx.children.size()));
1054 return tryWithResources;
1055 }
1056
1057 @Override
1058 public DetailAstImpl visitYieldStat(JavaLanguageParser.YieldStatContext ctx) {
1059 final DetailAstImpl yieldParent = create(ctx.LITERAL_YIELD());
1060
1061 processChildren(yieldParent, ctx.children.subList(1, ctx.children.size()));
1062 return yieldParent;
1063 }
1064
1065 @Override
1066 public DetailAstImpl visitSyncStat(JavaLanguageParser.SyncStatContext ctx) {
1067 final DetailAstImpl syncStatement = create(ctx.start);
1068
1069 processChildren(syncStatement, ctx.children.subList(1, ctx.children.size()));
1070 return syncStatement;
1071 }
1072
1073 @Override
1074 public DetailAstImpl visitReturnStat(JavaLanguageParser.ReturnStatContext ctx) {
1075 final DetailAstImpl returnStat = create(ctx.LITERAL_RETURN());
1076
1077 processChildren(returnStat, ctx.children.subList(1, ctx.children.size()));
1078 return returnStat;
1079 }
1080
1081 @Override
1082 public DetailAstImpl visitThrowStat(JavaLanguageParser.ThrowStatContext ctx) {
1083 final DetailAstImpl throwStat = create(ctx.LITERAL_THROW());
1084
1085 processChildren(throwStat, ctx.children.subList(1, ctx.children.size()));
1086 return throwStat;
1087 }
1088
1089 @Override
1090 public DetailAstImpl visitBreakStat(JavaLanguageParser.BreakStatContext ctx) {
1091 final DetailAstImpl literalBreak = create(ctx.LITERAL_BREAK());
1092
1093 processChildren(literalBreak, ctx.children.subList(1, ctx.children.size()));
1094 return literalBreak;
1095 }
1096
1097 @Override
1098 public DetailAstImpl visitContinueStat(JavaLanguageParser.ContinueStatContext ctx) {
1099 final DetailAstImpl continueStat = create(ctx.LITERAL_CONTINUE());
1100
1101 processChildren(continueStat, ctx.children.subList(1, ctx.children.size()));
1102 return continueStat;
1103 }
1104
1105 @Override
1106 public DetailAstImpl visitEmptyStat(JavaLanguageParser.EmptyStatContext ctx) {
1107 return create(TokenTypes.EMPTY_STAT, ctx.start);
1108 }
1109
1110 @Override
1111 public DetailAstImpl visitExpStat(JavaLanguageParser.ExpStatContext ctx) {
1112 final DetailAstImpl expStatRoot = visit(ctx.statementExpression);
1113 addLastSibling(expStatRoot, create(ctx.SEMI()));
1114 return expStatRoot;
1115 }
1116
1117 @Override
1118 public DetailAstImpl visitLabelStat(JavaLanguageParser.LabelStatContext ctx) {
1119 final DetailAstImpl labelStat = create(TokenTypes.LABELED_STAT,
1120 (Token) ctx.COLON().getPayload());
1121 labelStat.addChild(visit(ctx.id()));
1122 labelStat.addChild(visit(ctx.statement()));
1123 return labelStat;
1124 }
1125
1126 @Override
1127 public DetailAstImpl visitSwitchExpressionOrStatement(
1128 JavaLanguageParser.SwitchExpressionOrStatementContext ctx) {
1129 final DetailAstImpl switchStat = create(ctx.LITERAL_SWITCH());
1130 switchStat.addChild(visit(ctx.parExpression()));
1131 switchStat.addChild(create(ctx.LCURLY()));
1132 switchStat.addChild(visit(ctx.switchBlock()));
1133 switchStat.addChild(create(ctx.RCURLY()));
1134 return switchStat;
1135 }
1136
1137 @Override
1138 public DetailAstImpl visitSwitchRules(JavaLanguageParser.SwitchRulesContext ctx) {
1139 final DetailAstImpl dummyRoot = new DetailAstImpl();
1140 ctx.switchLabeledRule().forEach(switchLabeledRuleContext -> {
1141 final DetailAstImpl switchRule = visit(switchLabeledRuleContext);
1142 final DetailAstImpl switchRuleParent = createImaginary(TokenTypes.SWITCH_RULE);
1143 switchRuleParent.addChild(switchRule);
1144 dummyRoot.addChild(switchRuleParent);
1145 });
1146 return dummyRoot.getFirstChild();
1147 }
1148
1149 @Override
1150 public DetailAstImpl visitSwitchBlocks(JavaLanguageParser.SwitchBlocksContext ctx) {
1151 final DetailAstImpl dummyRoot = new DetailAstImpl();
1152 ctx.groups.forEach(group -> dummyRoot.addChild(visit(group)));
1153
1154
1155 if (!ctx.emptyLabels.isEmpty()) {
1156 final DetailAstImpl emptyLabelParent =
1157 createImaginary(TokenTypes.CASE_GROUP);
1158 ctx.emptyLabels.forEach(label -> emptyLabelParent.addChild(visit(label)));
1159 dummyRoot.addChild(emptyLabelParent);
1160 }
1161 return dummyRoot.getFirstChild();
1162 }
1163
1164 @Override
1165 public DetailAstImpl visitSwitchLabeledExpression(
1166 JavaLanguageParser.SwitchLabeledExpressionContext ctx) {
1167 return flattenedTree(ctx);
1168 }
1169
1170 @Override
1171 public DetailAstImpl visitSwitchLabeledBlock(
1172 JavaLanguageParser.SwitchLabeledBlockContext ctx) {
1173 return flattenedTree(ctx);
1174 }
1175
1176 @Override
1177 public DetailAstImpl visitSwitchLabeledThrow(
1178 JavaLanguageParser.SwitchLabeledThrowContext ctx) {
1179 final DetailAstImpl switchLabel = visit(ctx.switchLabel());
1180 addLastSibling(switchLabel, create(ctx.LAMBDA()));
1181 final DetailAstImpl literalThrow = create(ctx.LITERAL_THROW());
1182 literalThrow.addChild(visit(ctx.expression()));
1183 literalThrow.addChild(create(ctx.SEMI()));
1184 addLastSibling(switchLabel, literalThrow);
1185 return switchLabel;
1186 }
1187
1188 @Override
1189 public DetailAstImpl visitElseStat(JavaLanguageParser.ElseStatContext ctx) {
1190 final DetailAstImpl elseStat = create(ctx.LITERAL_ELSE());
1191
1192 processChildren(elseStat, ctx.children.subList(1, ctx.children.size()));
1193 return elseStat;
1194 }
1195
1196 @Override
1197 public DetailAstImpl visitCatchClause(JavaLanguageParser.CatchClauseContext ctx) {
1198 final DetailAstImpl catchClause = create(TokenTypes.LITERAL_CATCH,
1199 (Token) ctx.LITERAL_CATCH().getPayload());
1200
1201 processChildren(catchClause, ctx.children.subList(1, ctx.children.size()));
1202 return catchClause;
1203 }
1204
1205 @Override
1206 public DetailAstImpl visitCatchParameter(JavaLanguageParser.CatchParameterContext ctx) {
1207 final DetailAstImpl catchParameterDef = createImaginary(TokenTypes.PARAMETER_DEF);
1208 catchParameterDef.addChild(createModifiers(ctx.mods));
1209
1210 processChildren(catchParameterDef, ctx.children.stream()
1211 .filter(child -> !(child instanceof JavaLanguageParser.VariableModifierContext))
1212 .toList());
1213 return catchParameterDef;
1214 }
1215
1216 @Override
1217 public DetailAstImpl visitCatchType(JavaLanguageParser.CatchTypeContext ctx) {
1218 final DetailAstImpl type = createImaginary(TokenTypes.TYPE);
1219 processChildren(type, ctx.children);
1220 return type;
1221 }
1222
1223 @Override
1224 public DetailAstImpl visitFinallyBlock(JavaLanguageParser.FinallyBlockContext ctx) {
1225 final DetailAstImpl finallyBlock = create(ctx.LITERAL_FINALLY());
1226
1227 processChildren(finallyBlock, ctx.children.subList(1, ctx.children.size()));
1228 return finallyBlock;
1229 }
1230
1231 @Override
1232 public DetailAstImpl visitResourceSpecification(
1233 JavaLanguageParser.ResourceSpecificationContext ctx) {
1234 final DetailAstImpl resourceSpecification =
1235 createImaginary(TokenTypes.RESOURCE_SPECIFICATION);
1236 processChildren(resourceSpecification, ctx.children);
1237 return resourceSpecification;
1238 }
1239
1240 @Override
1241 public DetailAstImpl visitResources(JavaLanguageParser.ResourcesContext ctx) {
1242 final DetailAstImpl firstResource = visit(ctx.resource(0));
1243 final DetailAstImpl resources = createImaginary(TokenTypes.RESOURCES);
1244 resources.addChild(firstResource);
1245 processChildren(resources, ctx.children.subList(1, ctx.children.size()));
1246 return resources;
1247 }
1248
1249 @Override
1250 public DetailAstImpl visitResourceDeclaration(
1251 JavaLanguageParser.ResourceDeclarationContext ctx) {
1252 final DetailAstImpl resource = createImaginary(TokenTypes.RESOURCE);
1253 resource.addChild(visit(ctx.variableDeclaratorId()));
1254
1255 final DetailAstImpl assign = create(ctx.ASSIGN());
1256 resource.addChild(assign);
1257 assign.addChild(visit(ctx.expression()));
1258 return resource;
1259 }
1260
1261 @Override
1262 public DetailAstImpl visitVariableAccess(JavaLanguageParser.VariableAccessContext ctx) {
1263 final DetailAstImpl resource = createImaginary(TokenTypes.RESOURCE);
1264
1265 final DetailAstImpl childNode;
1266 if (ctx.LITERAL_THIS() == null) {
1267 childNode = visit(ctx.id());
1268 }
1269 else {
1270 childNode = create(ctx.LITERAL_THIS());
1271 }
1272
1273 if (ctx.accessList.isEmpty()) {
1274 resource.addChild(childNode);
1275 }
1276 else {
1277 final DetailAstPair currentAst = new DetailAstPair();
1278 ctx.accessList.forEach(fieldAccess -> {
1279 DetailAstPair.addAstChild(currentAst, visit(fieldAccess.expr()));
1280 DetailAstPair.makeAstRoot(currentAst, create(fieldAccess.DOT()));
1281 });
1282 resource.addChild(currentAst.getRoot());
1283 resource.getFirstChild().addChild(childNode);
1284 }
1285 return resource;
1286 }
1287
1288 @Override
1289 public DetailAstImpl visitSwitchBlockStatementGroup(
1290 JavaLanguageParser.SwitchBlockStatementGroupContext ctx) {
1291 final DetailAstImpl caseGroup = createImaginary(TokenTypes.CASE_GROUP);
1292 processChildren(caseGroup, ctx.switchLabel());
1293 final DetailAstImpl sList = createImaginary(TokenTypes.SLIST);
1294 processChildren(sList, ctx.slists);
1295 caseGroup.addChild(sList);
1296 return caseGroup;
1297 }
1298
1299 @Override
1300 public DetailAstImpl visitCaseLabel(JavaLanguageParser.CaseLabelContext ctx) {
1301 final DetailAstImpl caseLabel = create(ctx.LITERAL_CASE());
1302
1303 processChildren(caseLabel, ctx.children.subList(1, ctx.children.size()));
1304 return caseLabel;
1305 }
1306
1307 @Override
1308 public DetailAstImpl visitDefaultLabel(JavaLanguageParser.DefaultLabelContext ctx) {
1309 final DetailAstImpl defaultLabel = create(ctx.LITERAL_DEFAULT());
1310 if (ctx.COLON() != null) {
1311 defaultLabel.addChild(create(ctx.COLON()));
1312 }
1313 return defaultLabel;
1314 }
1315
1316 @Override
1317 public DetailAstImpl visitCaseConstants(JavaLanguageParser.CaseConstantsContext ctx) {
1318 return flattenedTree(ctx);
1319 }
1320
1321 @Override
1322 public DetailAstImpl visitCaseConstant(JavaLanguageParser.CaseConstantContext ctx) {
1323 return flattenedTree(ctx);
1324 }
1325
1326 @Override
1327 public DetailAstImpl visitEnhancedFor(JavaLanguageParser.EnhancedForContext ctx) {
1328 final DetailAstImpl leftParen = create(ctx.LPAREN());
1329 final DetailAstImpl enhancedForControl =
1330 visit(ctx.getChild(1));
1331 final DetailAstImpl forEachClause = createImaginary(TokenTypes.FOR_EACH_CLAUSE);
1332 forEachClause.addChild(enhancedForControl);
1333 addLastSibling(leftParen, forEachClause);
1334 addLastSibling(leftParen, create(ctx.RPAREN()));
1335 return leftParen;
1336 }
1337
1338 @Override
1339 public DetailAstImpl visitForFor(JavaLanguageParser.ForForContext ctx) {
1340 final DetailAstImpl dummyRoot = new DetailAstImpl();
1341 dummyRoot.addChild(create(ctx.LPAREN()));
1342
1343 if (ctx.forInit() == null) {
1344 final DetailAstImpl imaginaryForInitParent =
1345 createImaginary(TokenTypes.FOR_INIT);
1346 dummyRoot.addChild(imaginaryForInitParent);
1347 }
1348 else {
1349 dummyRoot.addChild(visit(ctx.forInit()));
1350 }
1351
1352 dummyRoot.addChild(create(ctx.SEMI(0)));
1353
1354 final DetailAstImpl forCondParent = createImaginary(TokenTypes.FOR_CONDITION);
1355 forCondParent.addChild(visit(ctx.forCond));
1356 dummyRoot.addChild(forCondParent);
1357 dummyRoot.addChild(create(ctx.SEMI(1)));
1358
1359 final DetailAstImpl forItParent = createImaginary(TokenTypes.FOR_ITERATOR);
1360 forItParent.addChild(visit(ctx.forUpdate));
1361 dummyRoot.addChild(forItParent);
1362
1363 dummyRoot.addChild(create(ctx.RPAREN()));
1364
1365 return dummyRoot.getFirstChild();
1366 }
1367
1368 @Override
1369 public DetailAstImpl visitForInit(JavaLanguageParser.ForInitContext ctx) {
1370 final DetailAstImpl forInit = createImaginary(TokenTypes.FOR_INIT);
1371 processChildren(forInit, ctx.children);
1372 return forInit;
1373 }
1374
1375 @Override
1376 public DetailAstImpl visitEnhancedForControl(
1377 JavaLanguageParser.EnhancedForControlContext ctx) {
1378 final DetailAstImpl variableDeclaratorId =
1379 visit(ctx.variableDeclaratorId());
1380 final DetailAstImpl variableDef = createImaginary(TokenTypes.VARIABLE_DEF);
1381 variableDef.addChild(variableDeclaratorId);
1382
1383 addLastSibling(variableDef, create(ctx.COLON()));
1384 addLastSibling(variableDef, visit(ctx.expression()));
1385 return variableDef;
1386 }
1387
1388 @Override
1389 public DetailAstImpl visitEnhancedForControlWithRecordPattern(
1390 JavaLanguageParser.EnhancedForControlWithRecordPatternContext ctx) {
1391 final DetailAstImpl recordPattern =
1392 visit(ctx.pattern());
1393 addLastSibling(recordPattern, create(ctx.COLON()));
1394 addLastSibling(recordPattern, visit(ctx.expression()));
1395 return recordPattern;
1396 }
1397
1398 @Override
1399 public DetailAstImpl visitParExpression(JavaLanguageParser.ParExpressionContext ctx) {
1400 return flattenedTree(ctx);
1401 }
1402
1403 @Override
1404 public DetailAstImpl visitExpressionList(JavaLanguageParser.ExpressionListContext ctx) {
1405 final DetailAstImpl elist = createImaginary(TokenTypes.ELIST);
1406 processChildren(elist, ctx.children);
1407 return elist;
1408 }
1409
1410 @Override
1411 public DetailAstImpl visitExpression(JavaLanguageParser.ExpressionContext ctx) {
1412 return buildExpressionNode(ctx.expr());
1413 }
1414
1415 @Override
1416 public DetailAstImpl visitRefOp(JavaLanguageParser.RefOpContext ctx) {
1417 final DetailAstImpl bop = create(ctx.bop);
1418 final DetailAstImpl leftChild = visit(ctx.expr());
1419 final DetailAstImpl rightChild = create(TokenTypes.IDENT, ctx.stop);
1420 bop.addChild(leftChild);
1421 bop.addChild(rightChild);
1422 return bop;
1423 }
1424
1425 @Override
1426 public DetailAstImpl visitSuperExp(JavaLanguageParser.SuperExpContext ctx) {
1427 final DetailAstImpl bop = create(ctx.bop);
1428 bop.addChild(visit(ctx.expr()));
1429 bop.addChild(create(ctx.LITERAL_SUPER()));
1430 DetailAstImpl superSuffixParent = visit(ctx.superSuffix());
1431
1432 if (superSuffixParent == null) {
1433 superSuffixParent = bop;
1434 }
1435 else {
1436 DetailAstImpl firstChild = superSuffixParent;
1437 while (firstChild.getFirstChild() != null) {
1438 firstChild = firstChild.getFirstChild();
1439 }
1440 firstChild.addPreviousSibling(bop);
1441 }
1442
1443 return superSuffixParent;
1444 }
1445
1446 @Override
1447 public DetailAstImpl visitInstanceOfExp(JavaLanguageParser.InstanceOfExpContext ctx) {
1448 final DetailAstImpl literalInstanceOf = create(ctx.LITERAL_INSTANCEOF());
1449 literalInstanceOf.addChild(visit(ctx.expr()));
1450 final ParseTree patternOrType = ctx.getChild(2);
1451 final DetailAstImpl patternDef = visit(patternOrType);
1452 literalInstanceOf.addChild(patternDef);
1453 return literalInstanceOf;
1454 }
1455
1456 @Override
1457 public DetailAstImpl visitBitShift(JavaLanguageParser.BitShiftContext ctx) {
1458 final DetailAstImpl shiftOperation;
1459
1460
1461
1462
1463 if (ctx.LT().size() == LEFT_SHIFT.length()) {
1464 shiftOperation = create(TokenTypes.SL, (Token) ctx.LT(0).getPayload());
1465 shiftOperation.setText(LEFT_SHIFT);
1466 }
1467 else if (ctx.GT().size() == UNSIGNED_RIGHT_SHIFT.length()) {
1468 shiftOperation = create(TokenTypes.BSR, (Token) ctx.GT(0).getPayload());
1469 shiftOperation.setText(UNSIGNED_RIGHT_SHIFT);
1470 }
1471 else {
1472 shiftOperation = create(TokenTypes.SR, (Token) ctx.GT(0).getPayload());
1473 shiftOperation.setText(RIGHT_SHIFT);
1474 }
1475
1476 shiftOperation.addChild(visit(ctx.expr(0)));
1477 shiftOperation.addChild(visit(ctx.expr(1)));
1478 return shiftOperation;
1479 }
1480
1481 @Override
1482 public DetailAstImpl visitNewExp(JavaLanguageParser.NewExpContext ctx) {
1483 final DetailAstImpl newExp = create(ctx.LITERAL_NEW());
1484
1485 processChildren(newExp, ctx.children.subList(1, ctx.children.size()));
1486 return newExp;
1487 }
1488
1489 @Override
1490 public DetailAstImpl visitPrefix(JavaLanguageParser.PrefixContext ctx) {
1491 final int tokenType = switch (ctx.prefix.getType()) {
1492 case JavaLanguageLexer.PLUS -> TokenTypes.UNARY_PLUS;
1493 case JavaLanguageLexer.MINUS -> TokenTypes.UNARY_MINUS;
1494 default -> ctx.prefix.getType();
1495 };
1496 final DetailAstImpl prefix = create(tokenType, ctx.prefix);
1497 prefix.addChild(visit(ctx.expr()));
1498 return prefix;
1499 }
1500
1501 @Override
1502 public DetailAstImpl visitCastExp(JavaLanguageParser.CastExpContext ctx) {
1503 final DetailAstImpl cast = create(TokenTypes.TYPECAST, (Token) ctx.LPAREN().getPayload());
1504
1505 processChildren(cast, ctx.children.subList(1, ctx.children.size()));
1506 return cast;
1507 }
1508
1509 @Override
1510 public DetailAstImpl visitIndexOp(JavaLanguageParser.IndexOpContext ctx) {
1511
1512 final DetailAstImpl indexOp = create(TokenTypes.INDEX_OP,
1513 (Token) ctx.LBRACK().getPayload());
1514
1515
1516 indexOp.addChild(visit(ctx.expr(0)));
1517
1518
1519 final DetailAstImpl expr = visit(ctx.expr(1));
1520 final DetailAstImpl imaginaryExpr = createImaginary(TokenTypes.EXPR);
1521 imaginaryExpr.addChild(expr);
1522 indexOp.addChild(imaginaryExpr);
1523
1524
1525 indexOp.addChild(create(ctx.RBRACK()));
1526 return indexOp;
1527 }
1528
1529 @Override
1530 public DetailAstImpl visitInvOp(JavaLanguageParser.InvOpContext ctx) {
1531 final DetailAstPair currentAst = new DetailAstPair();
1532
1533 final DetailAstImpl returnAst = visit(ctx.expr());
1534 DetailAstPair.addAstChild(currentAst, returnAst);
1535 DetailAstPair.makeAstRoot(currentAst, create(ctx.bop));
1536
1537 DetailAstPair.addAstChild(currentAst,
1538 visit(ctx.nonWildcardTypeArguments()));
1539 DetailAstPair.addAstChild(currentAst, visit(ctx.id()));
1540 final DetailAstImpl lparen = create(TokenTypes.METHOD_CALL,
1541 (Token) ctx.LPAREN().getPayload());
1542 DetailAstPair.makeAstRoot(currentAst, lparen);
1543
1544
1545 final DetailAstImpl expressionList = Optional.ofNullable(visit(ctx.expressionList()))
1546 .orElseGet(() -> createImaginary(TokenTypes.ELIST));
1547
1548 DetailAstPair.addAstChild(currentAst, expressionList);
1549 DetailAstPair.addAstChild(currentAst, create(ctx.RPAREN()));
1550
1551 return currentAst.root;
1552 }
1553
1554 @Override
1555 public DetailAstImpl visitInitExp(JavaLanguageParser.InitExpContext ctx) {
1556 final DetailAstImpl dot = create(ctx.bop);
1557 dot.addChild(visit(ctx.expr()));
1558 final DetailAstImpl literalNew = create(ctx.LITERAL_NEW());
1559 literalNew.addChild(visit(ctx.nonWildcardTypeArguments()));
1560 literalNew.addChild(visit(ctx.innerCreator()));
1561 dot.addChild(literalNew);
1562 return dot;
1563 }
1564
1565 @Override
1566 public DetailAstImpl visitSimpleMethodCall(JavaLanguageParser.SimpleMethodCallContext ctx) {
1567 final DetailAstImpl methodCall = create(TokenTypes.METHOD_CALL,
1568 (Token) ctx.LPAREN().getPayload());
1569 methodCall.addChild(visit(ctx.id()));
1570
1571 final DetailAstImpl expressionList = Optional.ofNullable(visit(ctx.expressionList()))
1572 .orElseGet(() -> createImaginary(TokenTypes.ELIST));
1573
1574 methodCall.addChild(expressionList);
1575 methodCall.addChild(create((Token) ctx.RPAREN().getPayload()));
1576 return methodCall;
1577 }
1578
1579 @Override
1580 public DetailAstImpl visitLambdaExp(JavaLanguageParser.LambdaExpContext ctx) {
1581 final DetailAstImpl lambda = create(ctx.LAMBDA());
1582 lambda.addChild(visit(ctx.lambdaParameters()));
1583
1584 final JavaLanguageParser.BlockContext blockContext = ctx.block();
1585 final DetailAstImpl rightHandLambdaChild;
1586 if (blockContext != null) {
1587 rightHandLambdaChild = visit(blockContext);
1588 }
1589 else {
1590
1591
1592
1593
1594 rightHandLambdaChild = buildExpressionNode(ctx.expr());
1595 }
1596 lambda.addChild(rightHandLambdaChild);
1597 return lambda;
1598 }
1599
1600 @Override
1601 public DetailAstImpl visitThisExp(JavaLanguageParser.ThisExpContext ctx) {
1602 final DetailAstImpl bop = create(ctx.bop);
1603 bop.addChild(visit(ctx.expr()));
1604 bop.addChild(create(ctx.LITERAL_THIS()));
1605 return bop;
1606 }
1607
1608 @Override
1609 public DetailAstImpl visitPrimaryExp(JavaLanguageParser.PrimaryExpContext ctx) {
1610 return flattenedTree(ctx);
1611 }
1612
1613 @Override
1614 public DetailAstImpl visitPostfix(JavaLanguageParser.PostfixContext ctx) {
1615 final DetailAstImpl postfix;
1616 if (ctx.postfix.getType() == JavaLanguageLexer.INC) {
1617 postfix = create(TokenTypes.POST_INC, ctx.postfix);
1618 }
1619 else {
1620 postfix = create(TokenTypes.POST_DEC, ctx.postfix);
1621 }
1622 postfix.addChild(visit(ctx.expr()));
1623 return postfix;
1624 }
1625
1626 @Override
1627 public DetailAstImpl visitMethodRef(JavaLanguageParser.MethodRefContext ctx) {
1628 final DetailAstImpl doubleColon = create(TokenTypes.METHOD_REF,
1629 (Token) ctx.DOUBLE_COLON().getPayload());
1630 final List<ParseTree> children = ctx.children.stream()
1631 .filter(child -> !child.equals(ctx.DOUBLE_COLON()))
1632 .toList();
1633 processChildren(doubleColon, children);
1634 return doubleColon;
1635 }
1636
1637 @Override
1638 public DetailAstImpl visitTernaryOp(JavaLanguageParser.TernaryOpContext ctx) {
1639 final DetailAstImpl root = create(ctx.QUESTION());
1640 processChildren(root, ctx.children.stream()
1641 .filter(child -> !child.equals(ctx.QUESTION()))
1642 .toList());
1643 return root;
1644 }
1645
1646 @Override
1647 public DetailAstImpl visitBinOp(JavaLanguageParser.BinOpContext ctx) {
1648 final DetailAstImpl bop = create(ctx.bop);
1649
1650
1651
1652 final List<JavaLanguageParser.BinOpContext> binOpList = new ArrayList<>();
1653 ParseTree firstExpression = ctx.expr(0);
1654 while (firstExpression instanceof JavaLanguageParser.BinOpContext) {
1655
1656 binOpList.add((JavaLanguageParser.BinOpContext) firstExpression);
1657 firstExpression = ((JavaLanguageParser.BinOpContext) firstExpression).expr(0);
1658 }
1659
1660 if (binOpList.isEmpty()) {
1661 final DetailAstImpl leftChild = visit(ctx.children.getFirst());
1662 bop.addChild(leftChild);
1663 }
1664 else {
1665
1666
1667 final Queue<DetailAstImpl> descendantList = binOpList.parallelStream()
1668 .map(this::getInnerBopAst)
1669 .collect(Collectors.toCollection(ArrayDeque::new));
1670
1671 bop.addChild(descendantList.poll());
1672 DetailAstImpl pointer = bop.getFirstChild();
1673
1674 for (DetailAstImpl descendant : descendantList) {
1675 pointer.getFirstChild().addPreviousSibling(descendant);
1676 pointer = descendant;
1677 }
1678 }
1679
1680 bop.addChild(visit(ctx.children.get(2)));
1681 return bop;
1682 }
1683
1684
1685
1686
1687
1688
1689
1690 private DetailAstImpl getInnerBopAst(JavaLanguageParser.BinOpContext descendant) {
1691 final DetailAstImpl innerBop = create(descendant.bop);
1692 final JavaLanguageParser.ExprContext expr = descendant.expr(0);
1693 if (!(expr instanceof JavaLanguageParser.BinOpContext)) {
1694 innerBop.addChild(visit(expr));
1695 }
1696 innerBop.addChild(visit(descendant.expr(1)));
1697 return innerBop;
1698 }
1699
1700 @Override
1701 public DetailAstImpl visitMethodCall(JavaLanguageParser.MethodCallContext ctx) {
1702 final DetailAstImpl methodCall = create(TokenTypes.METHOD_CALL,
1703 (Token) ctx.LPAREN().getPayload());
1704
1705 final DetailAstImpl expressionList = Optional.ofNullable(visit(ctx.expressionList()))
1706 .orElseGet(() -> createImaginary(TokenTypes.ELIST));
1707
1708 final DetailAstImpl dot = create(ctx.DOT());
1709 dot.addChild(visit(ctx.expr()));
1710 dot.addChild(visit(ctx.id()));
1711 methodCall.addChild(dot);
1712 methodCall.addChild(expressionList);
1713 methodCall.addChild(create((Token) ctx.RPAREN().getPayload()));
1714 return methodCall;
1715 }
1716
1717 @Override
1718 public DetailAstImpl visitTypeCastParameters(
1719 JavaLanguageParser.TypeCastParametersContext ctx) {
1720 final DetailAstImpl typeType = visit(ctx.typeType(0));
1721 for (int i = 0; i < ctx.BAND().size(); i++) {
1722 addLastSibling(typeType, create(TokenTypes.TYPE_EXTENSION_AND,
1723 (Token) ctx.BAND(i).getPayload()));
1724 addLastSibling(typeType, visit(ctx.typeType(i + 1)));
1725 }
1726 return typeType;
1727 }
1728
1729 @Override
1730 public DetailAstImpl visitSingleLambdaParam(JavaLanguageParser.SingleLambdaParamContext ctx) {
1731 return flattenedTree(ctx);
1732 }
1733
1734 @Override
1735 public DetailAstImpl visitFormalLambdaParam(JavaLanguageParser.FormalLambdaParamContext ctx) {
1736 final DetailAstImpl lparen = create(ctx.LPAREN());
1737
1738
1739 final DetailAstImpl parameters = Optional.ofNullable(visit(ctx.formalParameterList()))
1740 .orElseGet(() -> createImaginary(TokenTypes.PARAMETERS));
1741 addLastSibling(lparen, parameters);
1742 addLastSibling(lparen, create(ctx.RPAREN()));
1743 return lparen;
1744 }
1745
1746 @Override
1747 public DetailAstImpl visitMultiLambdaParam(JavaLanguageParser.MultiLambdaParamContext ctx) {
1748 final DetailAstImpl lparen = create(ctx.LPAREN());
1749 addLastSibling(lparen, visit(ctx.multiLambdaParams()));
1750 addLastSibling(lparen, create(ctx.RPAREN()));
1751 return lparen;
1752 }
1753
1754 @Override
1755 public DetailAstImpl visitMultiLambdaParams(JavaLanguageParser.MultiLambdaParamsContext ctx) {
1756 final DetailAstImpl parameters = createImaginary(TokenTypes.PARAMETERS);
1757 parameters.addChild(createLambdaParameter(ctx.id(0)));
1758
1759 for (int i = 0; i < ctx.COMMA().size(); i++) {
1760 parameters.addChild(create(ctx.COMMA(i)));
1761 parameters.addChild(createLambdaParameter(ctx.id(i + 1)));
1762 }
1763 return parameters;
1764 }
1765
1766
1767
1768
1769
1770
1771
1772
1773 private DetailAstImpl createLambdaParameter(JavaLanguageParser.IdContext ctx) {
1774 final DetailAstImpl ident = visitId(ctx);
1775 final DetailAstImpl parameter = createImaginary(TokenTypes.PARAMETER_DEF);
1776 final DetailAstImpl modifiers = createImaginary(TokenTypes.MODIFIERS);
1777 final DetailAstImpl type = createImaginary(TokenTypes.TYPE);
1778 parameter.addChild(modifiers);
1779 parameter.addChild(type);
1780 parameter.addChild(ident);
1781 return parameter;
1782 }
1783
1784 @Override
1785 public DetailAstImpl visitParenPrimary(JavaLanguageParser.ParenPrimaryContext ctx) {
1786 return flattenedTree(ctx);
1787 }
1788
1789 @Override
1790 public DetailAstImpl visitTokenPrimary(JavaLanguageParser.TokenPrimaryContext ctx) {
1791 return flattenedTree(ctx);
1792 }
1793
1794 @Override
1795 public DetailAstImpl visitClassRefPrimary(JavaLanguageParser.ClassRefPrimaryContext ctx) {
1796 final DetailAstImpl dot = create(ctx.DOT());
1797 final DetailAstImpl primaryTypeNoArray = visit(ctx.type);
1798 dot.addChild(primaryTypeNoArray);
1799 if (TokenUtil.isOfType(primaryTypeNoArray, TokenTypes.DOT)) {
1800
1801 ctx.arrayDeclarator()
1802 .forEach(child -> primaryTypeNoArray.addChild(visit(child)));
1803 }
1804 else {
1805 ctx.arrayDeclarator()
1806 .forEach(child -> addLastSibling(primaryTypeNoArray, visit(child)));
1807 }
1808 dot.addChild(create(ctx.LITERAL_CLASS()));
1809 return dot;
1810 }
1811
1812 @Override
1813 public DetailAstImpl visitPrimitivePrimary(JavaLanguageParser.PrimitivePrimaryContext ctx) {
1814 final DetailAstImpl dot = create(ctx.DOT());
1815 final DetailAstImpl primaryTypeNoArray = visit(ctx.type);
1816 dot.addChild(primaryTypeNoArray);
1817 ctx.arrayDeclarator().forEach(child -> dot.addChild(visit(child)));
1818 dot.addChild(create(ctx.LITERAL_CLASS()));
1819 return dot;
1820 }
1821
1822 @Override
1823 public DetailAstImpl visitCreator(JavaLanguageParser.CreatorContext ctx) {
1824 return flattenedTree(ctx);
1825 }
1826
1827 @Override
1828 public DetailAstImpl visitCreatedNameObject(JavaLanguageParser.CreatedNameObjectContext ctx) {
1829 final DetailAstPair currentAST = new DetailAstPair();
1830 DetailAstPair.addAstChild(currentAST, visit(ctx.annotations()));
1831 DetailAstPair.addAstChild(currentAST, visit(ctx.id()));
1832 DetailAstPair.addAstChild(currentAST, visit(ctx.typeArgumentsOrDiamond()));
1833
1834
1835 for (ParserRuleContext extendedContext : ctx.extended) {
1836 final DetailAstImpl dot = create(extendedContext.start);
1837 DetailAstPair.makeAstRoot(currentAST, dot);
1838 final List<ParseTree> childList = extendedContext
1839 .children.subList(1, extendedContext.children.size());
1840 processChildren(dot, childList);
1841 }
1842
1843 return currentAST.root;
1844 }
1845
1846 @Override
1847 public DetailAstImpl visitCreatedNamePrimitive(
1848 JavaLanguageParser.CreatedNamePrimitiveContext ctx) {
1849 return flattenedTree(ctx);
1850 }
1851
1852 @Override
1853 public DetailAstImpl visitInnerCreator(JavaLanguageParser.InnerCreatorContext ctx) {
1854 return flattenedTree(ctx);
1855 }
1856
1857 @Override
1858 public DetailAstImpl visitArrayCreatorRest(JavaLanguageParser.ArrayCreatorRestContext ctx) {
1859 final DetailAstImpl arrayDeclarator = create(TokenTypes.ARRAY_DECLARATOR,
1860 (Token) ctx.LBRACK().getPayload());
1861 final JavaLanguageParser.ExpressionContext expression = ctx.expression();
1862 final TerminalNode rbrack = ctx.RBRACK();
1863
1864 for (int i = 1; i < ctx.children.size(); i++) {
1865 if (ctx.children.get(i) == rbrack) {
1866 arrayDeclarator.addChild(create(rbrack));
1867 }
1868 else if (ctx.children.get(i) == expression) {
1869
1870 arrayDeclarator.addChild(visit(expression));
1871 }
1872 else {
1873 addLastSibling(arrayDeclarator, visit(ctx.children.get(i)));
1874 }
1875 }
1876 return arrayDeclarator;
1877 }
1878
1879 @Override
1880 public DetailAstImpl visitBracketsWithExp(JavaLanguageParser.BracketsWithExpContext ctx) {
1881 final DetailAstImpl dummyRoot = new DetailAstImpl();
1882 dummyRoot.addChild(visit(ctx.annotations()));
1883 final DetailAstImpl arrayDeclarator =
1884 create(TokenTypes.ARRAY_DECLARATOR, (Token) ctx.LBRACK().getPayload());
1885 arrayDeclarator.addChild(visit(ctx.expression()));
1886 arrayDeclarator.addChild(create(ctx.stop));
1887 dummyRoot.addChild(arrayDeclarator);
1888 return dummyRoot.getFirstChild();
1889 }
1890
1891 @Override
1892 public DetailAstImpl visitClassCreatorRest(JavaLanguageParser.ClassCreatorRestContext ctx) {
1893 return flattenedTree(ctx);
1894 }
1895
1896 @Override
1897 public DetailAstImpl visitDiamond(JavaLanguageParser.DiamondContext ctx) {
1898 final DetailAstImpl typeArguments =
1899 createImaginary(TokenTypes.TYPE_ARGUMENTS);
1900 typeArguments.addChild(create(TokenTypes.GENERIC_START,
1901 (Token) ctx.LT().getPayload()));
1902 typeArguments.addChild(create(TokenTypes.GENERIC_END,
1903 (Token) ctx.GT().getPayload()));
1904 return typeArguments;
1905 }
1906
1907 @Override
1908 public DetailAstImpl visitTypeArgs(JavaLanguageParser.TypeArgsContext ctx) {
1909 return flattenedTree(ctx);
1910 }
1911
1912 @Override
1913 public DetailAstImpl visitNonWildcardDiamond(
1914 JavaLanguageParser.NonWildcardDiamondContext ctx) {
1915 final DetailAstImpl typeArguments =
1916 createImaginary(TokenTypes.TYPE_ARGUMENTS);
1917 typeArguments.addChild(create(TokenTypes.GENERIC_START,
1918 (Token) ctx.LT().getPayload()));
1919 typeArguments.addChild(create(TokenTypes.GENERIC_END,
1920 (Token) ctx.GT().getPayload()));
1921 return typeArguments;
1922 }
1923
1924 @Override
1925 public DetailAstImpl visitNonWildcardTypeArguments(
1926 JavaLanguageParser.NonWildcardTypeArgumentsContext ctx) {
1927 final DetailAstImpl typeArguments = createImaginary(TokenTypes.TYPE_ARGUMENTS);
1928 typeArguments.addChild(create(TokenTypes.GENERIC_START, (Token) ctx.LT().getPayload()));
1929 typeArguments.addChild(visit(ctx.typeArgumentsTypeList()));
1930 typeArguments.addChild(create(TokenTypes.GENERIC_END, (Token) ctx.GT().getPayload()));
1931 return typeArguments;
1932 }
1933
1934 @Override
1935 public DetailAstImpl visitTypeArgumentsTypeList(
1936 JavaLanguageParser.TypeArgumentsTypeListContext ctx) {
1937 final DetailAstImpl firstIdent = visit(ctx.typeType(0));
1938 final DetailAstImpl firstTypeArgument = createImaginary(TokenTypes.TYPE_ARGUMENT);
1939 firstTypeArgument.addChild(firstIdent);
1940
1941 for (int i = 0; i < ctx.COMMA().size(); i++) {
1942 addLastSibling(firstTypeArgument, create(ctx.COMMA(i)));
1943 final DetailAstImpl ident = visit(ctx.typeType(i + 1));
1944 final DetailAstImpl typeArgument = createImaginary(TokenTypes.TYPE_ARGUMENT);
1945 typeArgument.addChild(ident);
1946 addLastSibling(firstTypeArgument, typeArgument);
1947 }
1948 return firstTypeArgument;
1949 }
1950
1951 @Override
1952 public DetailAstImpl visitTypeList(JavaLanguageParser.TypeListContext ctx) {
1953 return flattenedTree(ctx);
1954 }
1955
1956 @Override
1957 public DetailAstImpl visitTypeType(JavaLanguageParser.TypeTypeContext ctx) {
1958 final DetailAstImpl type = createImaginary(TokenTypes.TYPE);
1959 processChildren(type, ctx.children);
1960
1961 final DetailAstImpl returnTree;
1962 if (ctx.createImaginaryNode) {
1963 returnTree = type;
1964 }
1965 else {
1966 returnTree = type.getFirstChild();
1967 }
1968 return returnTree;
1969 }
1970
1971 @Override
1972 public DetailAstImpl visitArrayDeclarator(JavaLanguageParser.ArrayDeclaratorContext ctx) {
1973 final DetailAstImpl arrayDeclarator = create(TokenTypes.ARRAY_DECLARATOR,
1974 (Token) ctx.LBRACK().getPayload());
1975 arrayDeclarator.addChild(create(ctx.RBRACK()));
1976
1977 final DetailAstImpl returnTree;
1978 final DetailAstImpl annotations = visit(ctx.anno);
1979 if (annotations == null) {
1980 returnTree = arrayDeclarator;
1981 }
1982 else {
1983 returnTree = annotations;
1984 addLastSibling(returnTree, arrayDeclarator);
1985 }
1986 return returnTree;
1987 }
1988
1989 @Override
1990 public DetailAstImpl visitPrimitiveType(JavaLanguageParser.PrimitiveTypeContext ctx) {
1991 return create(ctx.start);
1992 }
1993
1994 @Override
1995 public DetailAstImpl visitTypeArguments(JavaLanguageParser.TypeArgumentsContext ctx) {
1996 final DetailAstImpl typeArguments = createImaginary(TokenTypes.TYPE_ARGUMENTS);
1997 typeArguments.addChild(create(TokenTypes.GENERIC_START, (Token) ctx.LT().getPayload()));
1998
1999 processChildren(typeArguments, ctx.children.subList(1, ctx.children.size() - 1));
2000 typeArguments.addChild(create(TokenTypes.GENERIC_END, (Token) ctx.GT().getPayload()));
2001 return typeArguments;
2002 }
2003
2004 @Override
2005 public DetailAstImpl visitSuperSuffixDot(JavaLanguageParser.SuperSuffixDotContext ctx) {
2006 final DetailAstImpl root;
2007 if (ctx.LPAREN() == null) {
2008 root = create(ctx.DOT());
2009 root.addChild(visit(ctx.id()));
2010 }
2011 else {
2012 root = create(TokenTypes.METHOD_CALL, (Token) ctx.LPAREN().getPayload());
2013
2014 final DetailAstImpl dot = create(ctx.DOT());
2015 dot.addChild(visit(ctx.id()));
2016 root.addChild(dot);
2017
2018 final DetailAstImpl expressionList = Optional.ofNullable(visit(ctx.expressionList()))
2019 .orElseGet(() -> createImaginary(TokenTypes.ELIST));
2020 root.addChild(expressionList);
2021
2022 root.addChild(create(ctx.RPAREN()));
2023 }
2024
2025 return root;
2026 }
2027
2028 @Override
2029 public DetailAstImpl visitArguments(JavaLanguageParser.ArgumentsContext ctx) {
2030 final DetailAstImpl lparen = create(ctx.LPAREN());
2031
2032
2033 final DetailAstImpl expressionList = Optional.ofNullable(visit(ctx.expressionList()))
2034 .orElseGet(() -> createImaginary(TokenTypes.ELIST));
2035 addLastSibling(lparen, expressionList);
2036 addLastSibling(lparen, create(ctx.RPAREN()));
2037 return lparen;
2038 }
2039
2040 @Override
2041 public DetailAstImpl visitPattern(JavaLanguageParser.PatternContext ctx) {
2042 final JavaLanguageParser.InnerPatternContext innerPattern = ctx.innerPattern();
2043 final ParserRuleContext primaryPattern = innerPattern.primaryPattern();
2044 final ParserRuleContext recordPattern = innerPattern.recordPattern();
2045
2046 final DetailAstImpl pattern;
2047
2048 if (recordPattern != null) {
2049 pattern = visit(recordPattern);
2050 }
2051 else if (primaryPattern != null) {
2052
2053 pattern = visit(primaryPattern);
2054 }
2055 else {
2056 pattern = createImaginary(TokenTypes.PATTERN_DEF);
2057 pattern.addChild(visit(ctx.getChild(0)));
2058 }
2059 return pattern;
2060 }
2061
2062 @Override
2063 public DetailAstImpl visitInnerPattern(JavaLanguageParser.InnerPatternContext ctx) {
2064 return flattenedTree(ctx);
2065 }
2066
2067 @Override
2068 public DetailAstImpl visitGuardedPattern(JavaLanguageParser.GuardedPatternContext ctx) {
2069 final DetailAstImpl guardAstNode = flattenedTree(ctx.guard());
2070 guardAstNode.addChild(visit(ctx.primaryPattern()));
2071 guardAstNode.addChild(visit(ctx.expression()));
2072 return guardAstNode;
2073 }
2074
2075 @Override
2076 public DetailAstImpl visitRecordPatternDef(JavaLanguageParser.RecordPatternDefContext ctx) {
2077 return flattenedTree(ctx);
2078 }
2079
2080 @Override
2081 public DetailAstImpl visitTypePatternDef(
2082 JavaLanguageParser.TypePatternDefContext ctx) {
2083 final DetailAstImpl type = visit(ctx.type);
2084 final DetailAstImpl patternVariableDef = createImaginary(TokenTypes.PATTERN_VARIABLE_DEF);
2085 patternVariableDef.addChild(createModifiers(ctx.mods));
2086 patternVariableDef.addChild(type);
2087 patternVariableDef.addChild(visit(ctx.id()));
2088 return patternVariableDef;
2089 }
2090
2091 @Override
2092 public DetailAstImpl visitUnnamedPatternDef(JavaLanguageParser.UnnamedPatternDefContext ctx) {
2093 return create(TokenTypes.UNNAMED_PATTERN_DEF, ctx.start);
2094 }
2095
2096 @Override
2097 public DetailAstImpl visitRecordPattern(JavaLanguageParser.RecordPatternContext ctx) {
2098 final DetailAstImpl recordPattern = createImaginary(TokenTypes.RECORD_PATTERN_DEF);
2099 recordPattern.addChild(createModifiers(ctx.mods));
2100 processChildren(recordPattern,
2101 ctx.children.subList(ctx.mods.size(), ctx.children.size()));
2102 return recordPattern;
2103 }
2104
2105 @Override
2106 public DetailAstImpl visitRecordComponentPatternList(
2107 JavaLanguageParser.RecordComponentPatternListContext ctx) {
2108 final DetailAstImpl recordComponents =
2109 createImaginary(TokenTypes.RECORD_PATTERN_COMPONENTS);
2110 processChildren(recordComponents, ctx.children);
2111 return recordComponents;
2112 }
2113
2114 @Override
2115 public DetailAstImpl visitPermittedSubclassesAndInterfaces(
2116 JavaLanguageParser.PermittedSubclassesAndInterfacesContext ctx) {
2117 final DetailAstImpl literalPermits =
2118 create(TokenTypes.PERMITS_CLAUSE, (Token) ctx.LITERAL_PERMITS().getPayload());
2119
2120 processChildren(literalPermits, ctx.children.subList(1, ctx.children.size()));
2121 return literalPermits;
2122 }
2123
2124 @Override
2125 public DetailAstImpl visitId(JavaLanguageParser.IdContext ctx) {
2126 return create(TokenTypes.IDENT, ctx.start);
2127 }
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137 private DetailAstImpl flattenedTree(ParserRuleContext ctx) {
2138 final DetailAstImpl dummyNode = new DetailAstImpl();
2139 processChildren(dummyNode, ctx.children);
2140 return dummyNode.getFirstChild();
2141 }
2142
2143
2144
2145
2146
2147
2148
2149
2150 private void processChildren(DetailAstImpl parent, List<? extends ParseTree> children) {
2151 children.forEach(child -> {
2152 if (child instanceof TerminalNode node) {
2153
2154 parent.addChild(create(node));
2155 }
2156 else {
2157
2158 parent.addChild(visit(child));
2159 }
2160 });
2161 }
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171 private static DetailAstImpl createImaginary(int tokenType) {
2172 final DetailAstImpl detailAst = new DetailAstImpl();
2173 detailAst.setType(tokenType);
2174 detailAst.setText(TokenUtil.getTokenName(tokenType));
2175 return detailAst;
2176 }
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186 private DetailAstImpl create(Token token) {
2187 final int tokenIndex = token.getTokenIndex();
2188 final List<Token> tokensToLeft =
2189 tokens.getHiddenTokensToLeft(tokenIndex, JavaLanguageLexer.COMMENTS);
2190 final List<Token> tokensToRight =
2191 tokens.getHiddenTokensToRight(tokenIndex, JavaLanguageLexer.COMMENTS);
2192
2193 final DetailAstImpl detailAst = new DetailAstImpl();
2194 detailAst.initialize(token);
2195 if (tokensToLeft != null) {
2196 detailAst.setHiddenBefore(tokensToLeft);
2197 }
2198 if (tokensToRight != null) {
2199 detailAst.setHiddenAfter(tokensToRight);
2200 }
2201 return detailAst;
2202 }
2203
2204
2205
2206
2207
2208
2209
2210
2211 private DetailAstImpl create(TerminalNode node) {
2212 return create((Token) node.getPayload());
2213 }
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223 private DetailAstImpl create(int tokenType, Token startToken) {
2224 final DetailAstImpl ast = create(startToken);
2225 ast.setType(tokenType);
2226 return ast;
2227 }
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237 private DetailAstImpl createTypeDeclaration(ParserRuleContext ctx, int type,
2238 List<? extends ParseTree> modifierList) {
2239 final DetailAstImpl typeDeclaration = createImaginary(type);
2240 typeDeclaration.addChild(createModifiers(modifierList));
2241 processChildren(typeDeclaration, ctx.children);
2242 return typeDeclaration;
2243 }
2244
2245
2246
2247
2248
2249
2250
2251 private DetailAstImpl createModifiers(List<? extends ParseTree> modifierList) {
2252 final DetailAstImpl mods = createImaginary(TokenTypes.MODIFIERS);
2253 processChildren(mods, modifierList);
2254 return mods;
2255 }
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268 private DetailAstImpl createNodeFromFirstToken(int tokenType, ParserRuleContext ctx) {
2269 final DetailAstImpl node = create(tokenType, ctx.start);
2270 processChildren(node, ctx.children.subList(1, ctx.children.size()));
2271 return node;
2272 }
2273
2274
2275
2276
2277
2278
2279
2280 private static void addLastSibling(DetailAstImpl self, DetailAstImpl sibling) {
2281 DetailAstImpl nextSibling = self;
2282 if (nextSibling != null) {
2283 while (nextSibling.getNextSibling() != null) {
2284 nextSibling = nextSibling.getNextSibling();
2285 }
2286 nextSibling.setNextSibling(sibling);
2287 }
2288 }
2289
2290 @Override
2291 public DetailAstImpl visit(ParseTree tree) {
2292 DetailAstImpl ast = null;
2293 if (tree != null) {
2294 ast = tree.accept(this);
2295 }
2296 return ast;
2297 }
2298
2299
2300
2301
2302
2303
2304
2305
2306 private DetailAstImpl buildExpressionNode(ParseTree exprNode) {
2307 final DetailAstImpl expression = visit(exprNode);
2308
2309 final DetailAstImpl exprRoot;
2310 if (TokenUtil.isOfType(expression, EXPRESSIONS_WITH_NO_EXPR_ROOT)) {
2311 exprRoot = expression;
2312 }
2313 else {
2314
2315 exprRoot = createImaginary(TokenTypes.EXPR);
2316 exprRoot.addChild(expression);
2317 }
2318 return exprRoot;
2319 }
2320
2321
2322
2323
2324 private static final class DetailAstPair {
2325
2326
2327 private DetailAstImpl root;
2328
2329
2330 private DetailAstImpl child;
2331
2332
2333
2334
2335 private DetailAstPair() {
2336
2337 }
2338
2339
2340
2341
2342 private void advanceChildToEnd() {
2343 while (child.getNextSibling() != null) {
2344 child = child.getNextSibling();
2345 }
2346 }
2347
2348
2349
2350
2351
2352
2353 private DetailAstImpl getRoot() {
2354 return root;
2355 }
2356
2357
2358
2359
2360
2361
2362
2363
2364 private static void makeAstRoot(DetailAstPair pair, DetailAstImpl ast) {
2365 ast.addChild(pair.root);
2366 pair.child = pair.root;
2367 pair.advanceChildToEnd();
2368 pair.root = ast;
2369 }
2370
2371
2372
2373
2374
2375
2376
2377 private static void addAstChild(DetailAstPair pair, DetailAstImpl ast) {
2378 if (ast != null) {
2379 if (pair.root == null) {
2380 pair.root = ast;
2381 }
2382 else {
2383 pair.child.setNextSibling(ast);
2384 }
2385 pair.child = ast;
2386 }
2387 }
2388 }
2389
2390 }