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