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