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