从AST获取方法调用信息

时间:2011-11-09 18:17:52

标签: java eclipse abstract-syntax-tree

如何使用AST(抽象语法树)解析器获取程序的每个方法声明中调用的方法的名称?到目前为止,我已经设法得到所有方法的名称'声明和被调用的方法的所有名称,但我想知道哪个方法调用哪些方法。例如,我希望方法m1调用方法mAmB,而方法m2调用方法mCmD

[编辑2011年11月9日IDB,在原始问题的正文中抄写新手的延伸评论。我希望我已经正确地转录了它。我希望作者回来并在必要时进行修改]:

我的问题似乎是(Eclipse' s)MethodDeclaration api没有要调用的GetInvokedMethodName函数。这是我的代码:

 public class MethodVisitor extends ASTVisitor { 

         List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();

         @Override public boolean visit(MethodDeclaration node) { 
             methods.add(node); 
             return super.visit(node); } 

         public List<MethodDeclaration> getMethods() 
             { return methods; }

         List<MethodInvocation> methods1 = new ArrayList<MethodInvocation>();

         @Override public boolean visit(MethodInvocation node)
             { methods1.add(node); 
               return super.visit(node); } 

        public List<MethodInvocation> getMethods1() 
             { return methods1; } 
        } 

    ...

    for (MethodDeclaration method : visitor .getMethods()) 
        { System.out.println("Method name: " + method.getName() 
                            + " Return type: " + method.getReturnType2() 
                            + " Is constructor: " + method.isConstructor()
                            + " Method invoked: " + ASTNode.METHOD_INVOCATION );
           ); }

    for (MethodInvocation method1 : visitor .getMethods1())
           { System.out.println("Method name invoked: " + method1.getName() ); }

2 个答案:

答案 0 :(得分:3)

我遇到了同样的问题。这是我的解决方案:

final HashMap<MethodDeclaration, ArrayList<MethodInvocation>> invocationsForMethods =
    new HashMap<MethodDeclaration, ArrayList<MethodInvocation>>();

        CompilationUnit cu = (CompilationUnit) ap.createAST(null);
        cu.accept(new ASTVisitor() {

            private MethodDeclaration activeMethod;

            @Override
            public boolean visit(MethodDeclaration node) {
                activeMethod = node;
                return super.visit(node);
            }

            @Override
            public boolean visit(MethodInvocation node) {
                if (invocationsForMethods.get(activeMethod) == null) {
                    invocationsForMethods.put(activeMethod, new ArrayList<MethodInvocation>());
                }
                invocationsForMethods.get(activeMethod).add(node);
                return super.visit(node);
            }

        });

现在,可以要求invocationsForMethods.keySet()获取所使用的AST的所有方法声明,并且invocationsForMethods.get(key)返回作为键给出的声明的所有方法调用。

答案 1 :(得分:2)

如果你想知道m1调用哪个特定方法mB(在你的大量类中所有名为“mB”的方法),你需要的不仅仅是AST。您需要一个完整的符号表,它将每个符号用法绑定到与其匹配的可能定义。

计算这样一个符号表的过程对于许多语言来说都很困难,对Java来说很难(但不像C ++那么糟糕)。有人必须编码在(本地)范围,继承,重载,隐含强制转换等方面如何查找标识符的规则,Java参考手册将其内容的很大一部分用于解释。你不想自己做这件事。

您真正需要的是一个完整的Java前端,它具有AST和相应的符号表,用于您要检查的每个方法。我认为,你可以从接口到(Sun?)Java编译器(我个人不知道如何做),Jikes编译器,Eclipse Java AST(?)模块以及工具等作为我们的Java Front End。另一种方法是处理类文件,其中包含JVM形式的方法调用,以及JVM指令都是利用符号表构建的advavntage。

如果你想计算m1调用mA调用mQ调用.... mZ,你需要一个愿意一次读取整个源代码库的工具。编译器不会为您执行此操作,但您可以使用Eclipse或我们的前端来执行此操作。