使用ANTLR4获取方法的注释

时间:2015-08-19 07:41:13

标签: java antlr antlr4

我正在编写一个简短的程序来扫描Java源文件,并使用ANTLR4查找其中的所有方法。对于每种方法,我都想检查它是否是测试方法,我想通过检查方法是否具有@Test注释来实现。

如何获取我正在访问的每种方法的注释列表?这是我目前的源代码:

public static void main(String... args) throws IOException {
    lexer = new JavaLexer(new ANTLRFileStream(sourceFile, "UTF-8"));
    parser = new JavaParser(new CommonTokenStream(lexer));
    ParseTree tree = parser.compilationUnit();

    ParseTreeWalker walker = new ParseTreeWalker();
    MyListener listener = new MyListener(printToFile);
    walker.walk(listener, tree);
}

public static class MyListener extends JavaBaseListener {
    @Override
    public void enterMethodDeclaration(JavaParser.MethodDeclarationContext ctx) {
        // Mark the method's boundaries and extract the method text
        int begin_offset = ctx.start.getStartIndex();
        int end_offset = ctx.stop.getStopIndex();
        Interval interval = new Interval(begin_offset, end_offset);
        String methodText = ctx.start.getInputStream().getText(interval);

        // Get the list of annotations - how?
    }

}

1 个答案:

答案 0 :(得分:1)

我将使用this Java grammar for antlr。我没有记忆,因为我没有工具来测试我手边的事情。阅读语法,你可以快速学到:

  • 注释对应于规则注释(哇),因此您可以在生成的树中的AnnotationContext中找到它们。
  • 注释链接到classBodyDeclaration规则中的类成员(例如方法)(修饰符可以是classOrInterfaceModifier,可以是注释)

在这种情况下,如果我们只有MethodDeclarationContext,我们就无法获得注释。我们需要访问整个树来查找相应的ClassBodyDeclarationContext。

现在我对听众并不熟悉。根据我的理解(并且不是很多),如果你需要在解析时工作,你应该使用它们。我只是访问解析器生成的树。 ANTLR应为您创建一个名为<your grammar name>ParserBaseVisitor的访问者。您所要做的就是扩展此类并覆盖感兴趣节点的访问方法。

  • 访问ClassBodyDeclarationContext。为此,您必须覆盖visitClassBodyDeclaration(ClassBodyDeclarationContext ctx)
  • 检查它是ctx.memberDeclaration().methodDeclaration()的方法。如果它不是方法声明,它应该为null。否则它应该是MethodDeclarationContext。
  • 如果不是,您可能希望访问子节点(如果它是类声明)。如果扩展由antlr生成的ParserBaseVisitor,则调用super,因为它正是它所做的。
  • 如果是方法,请检索注释列表并随意执行任何操作: - )

您应该能够检索这样的注释:

Set<AnnotationContext> annotations = new HashSet<AnnotationContext>();
for(ClassOrInterfaceModifier modifier: ctx.modifier()) {
    if (modifier.classOrInterfaceModifier().annotation()) {
        annotations.add(modifier.classOrInterfaceModifier().annotation());
    }
}