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