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