从AST获取方法调用信息

问题描述:

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

[编辑11/9/2011 IDB,抄录新手的扩展评论回来的身体原来的问题。我希望我已经正确地转录了它。我希望作者回来,并根据需要修改]:

我的问题似乎是(Eclipse的)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()); } 

如果你想知道哪个(都命名为“MB”在整个庞大的类数组的)具体方法MB内存由M1调用,您需要的不仅仅是AST更多。您需要一个完整的符号表,它将每个符号使用绑定到与其匹配的可能定义。

计算这样一个符号表的过程对很多语言来说都很困难,而且对于Java来说非常困难(但并不像C++那样糟糕)。有人必须编码如何在(本地)作用域,继承,重载,隐式强制转换等方面查找标识符的规则,而且Java参考手册中的大部分内容试图解释这些规则。你不想自己做这个。

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

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

+0

Spyros:您提供的作为背景的附加信息应该真正添加到问题本身中。在将你的代码块分解为注释大小的部分之后,它应该是显而易见的,它基本上是不可读的。阅读我的答案的其他人很可能会跳过这些评论,并会错过额外的内容。你可以编辑你的问题;请参阅您的问题下的**编辑**“按钮”。我冒昧将您的补充评论转移到您的问题中(高级SO用户可以这么做)来帮助您。要完成此清理,*您*可以删除这些注释。 –

我有同样的问题。这是我的解决之道:

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()让所有的使用ASTinvocationsForMethods.get(key)回报给作为重点申报所有的方法调用的方法声明。