使用antlr4解析java代码时导航到不属于上下文的标记

使用antlr4解析java代码时导航到不属于上下文的标记,java,antlr4,Java,Antlr4,我正在使用Antlr4.2解析Java源文件 我的目标是在类中找到具有特定注释的方法 我面临的问题是,语法没有将注释规则作为方法声明规则的一部分(这很有意义),这意味着当我重写JavaBaseListener的enterMethodDeclaration时,上下文对象无法直接使用它: @Override public void enterMethodDeclaration(@NotNull JavaParser.MethodDeclarationContext ctx) { // How

我正在使用Antlr4.2解析Java源文件

我的目标是在类中找到具有特定注释的方法

我面临的问题是,语法没有将
注释
规则作为
方法声明
规则的一部分(这很有意义),这意味着当我重写
JavaBaseListener的
enterMethodDeclaration
时,上下文对象无法直接使用它:

@Override
public void enterMethodDeclaration(@NotNull JavaParser.MethodDeclarationContext ctx) {
   // How do I access the annotation on the method in 'ctx'? 
}
到目前为止,我唯一的想法是获取令牌流,并尝试从方法声明上下文的位置向后遍历它。问题是它非常麻烦(方法上的注释可能在修饰符之前,如果修饰符确实存在,则在修饰符之后),我觉得它缺少了侦听器/访问者方法的要点


是否有一个干净的方法来获得一个方法的注释?

,而不是试图遍历解析树,考虑下去。您可以从
classBodyDeclaration
产品开始,检查是否可以进入
memberDeclaration
并从那里进入
methodDeclaration
。如果是这样的话,你就知道你目前正在使用一种方法。然后只需在
classBodyDeclaration
中的
修饰符列表上迭代即可找到注释

快速演示:

public class Main {

    public static void main(String[] args) throws Exception {

        String input = "@Annotation(\"class\")\n" +
                "class Mu {\n" +
                "\n" +
                "    @Annotation(\"field\")\n" +
                "    int x;\n" +
                "    \n" +
                "    @Annotation(\"method\")\n" +
                "    void withAnnotation(){}\n" +
                "    \n" +
                "    void withoutAnnotation(){}\n" +
                "}";

        JavaLexer lexer = new JavaLexer(new ANTLRInputStream(input));
        JavaParser parser = new JavaParser(new CommonTokenStream(lexer));

        //   classBodyDeclaration
        //       :   ...
        //       |   modifier* memberDeclaration
        //       ;
        //
        //   memberDeclaration
        //       :   methodDeclaration
        //       |   ...
        //       ;
        //
        //   methodDeclaration
        //       :   (type|'void') Identifier formalParameters ...
        //       ;
        //
        //   modifier
        //       :   classOrInterfaceModifier
        //       |   ...
        //       ;
        //
        //   classOrInterfaceModifier
        //       :   annotation
        //       |   ...
        //       ;
        ParseTreeWalker.DEFAULT.walk(new JavaBaseListener(){
            @Override
            public void enterClassBodyDeclaration(@NotNull JavaParser.ClassBodyDeclarationContext ctx) {

                if (!(ctx.memberDeclaration() != null && ctx.memberDeclaration().methodDeclaration() != null)) {
                    // No method declaration.
                    return;
                }

                String methodName = ctx.memberDeclaration().methodDeclaration().Identifier().getText();

                for (JavaParser.ModifierContext mctx : ctx.modifier()) {
                    if (mctx.classOrInterfaceModifier() != null && mctx.classOrInterfaceModifier().annotation() != null) {
                        System.out.println(methodName + " -> " + mctx.classOrInterfaceModifier().annotation().getText());
                    }
                }
            }
        }, parser.compilationUnit());
    }
}
其中打印:

withAnnotation -> @Annotation("method")
withAnnotation->@Annotation(“方法”)正是我想要的。需要一段时间来适应这项技术。谢谢