从AST获取方法调用信息
如何使用AST(抽象语法树)分析器获取程序的每个方法声明中调用的方法的名称?到目前为止,我已经设法获得了方法声明的所有名称和被调用方法的所有名称,但是我想知道哪个方法调用哪些方法。例如,我想看看m1
调用方法mA
和mB
该方法,而方法调用m2
方法mC
和mD
等从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或我们的前端来做到这一点。
我有同样的问题。这是我的解决之道:
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)
回报给作为重点申报所有的方法调用的方法声明。
Spyros:您提供的作为背景的附加信息应该真正添加到问题本身中。在将你的代码块分解为注释大小的部分之后,它应该是显而易见的,它基本上是不可读的。阅读我的答案的其他人很可能会跳过这些评论,并会错过额外的内容。你可以编辑你的问题;请参阅您的问题下的**编辑**“按钮”。我冒昧将您的补充评论转移到您的问题中(高级SO用户可以这么做)来帮助您。要完成此清理,*您*可以删除这些注释。 –