Java 从AST获取方法调用信息
如何使用AST(抽象语法树)解析器获取程序的每个方法声明中调用的方法的名称?到目前为止,我已经获得了方法声明的所有名称和被调用方法的所有名称,但是我想知道哪个方法调用哪个方法。例如,我想看到方法Java 从AST获取方法调用信息,java,eclipse,abstract-syntax-tree,Java,Eclipse,Abstract Syntax Tree,如何使用AST(抽象语法树)解析器获取程序的每个方法声明中调用的方法的名称?到目前为止,我已经获得了方法声明的所有名称和被调用方法的所有名称,但是我想知道哪个方法调用哪个方法。例如,我想看到方法m1调用方法mA和mB,而方法m2调用方法mC和mD,等等 [编辑2011年11月9日IDB,将新手的扩展评论抄写回原始问题正文。我希望我抄写正确。我希望作者回来并根据需要进行修改]: 我的问题似乎是(Eclipse的)MethodDeclaration api没有要调用的GetInvokedMethod
m1
调用方法mA
和mB
,而方法m2
调用方法mC
和mD
,等等
[编辑2011年11月9日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() ); }
公共类MethodVisitor扩展ASTVisitor{
列表方法=新的ArrayList();
@重写公共布尔访问(MethodDeclaration节点){
方法:添加(节点);
return super.visit(node);}
公共列表getMethods()
{返回方法;}
List methods1=新的ArrayList();
@覆盖公共布尔访问(MethodInvocation节点)
{methods1.add(节点);
return super.visit(node);}
公共列表getMethods1()
{返回方法1;}
}
...
for(MethodDeclaration方法:visitor.getMethods())
{System.out.println(“方法名:”+Method.getName()
+“返回类型:”+method.getReturnType2()
+是构造函数:“+method.isConstructor()
+“调用的方法:”+ASTNode.Method\u调用);
); }
for(MethodInvocation method1:visitor.getMethods1())
{System.out.println(“调用的方法名:+method1.getName());}
如果您想知道m1调用了哪一个特定的方法mB(在您庞大的类数组中所有名为“mB”的方法中),您需要的不仅仅是AST。您需要一个完整的符号表,该表将每个符号的使用绑定到与之匹配的可能定义
计算这样一个符号表的过程对于许多语言来说都很困难,对于Java来说也很困难(但没有C++那么糟糕)。必须有人对如何在(本地)作用域、继承、重载、隐含强制转换等方面查找标识符的规则进行编码,Java参考手册的大部分内容都试图解释这一点。你不想自己做这件事
对于要检查的每个方法,您真正需要的是一个完整的Java前端,它同时具有AST和相应的符号表。我认为,您可以从(Sun?)Java编译器的接口(我个人不知道如何做到这一点)、Jikes编译器、EclipseJavaAST(?)模块以及诸如我们的。另一种方法是使用JVM指令都使用符号表构建的advantage处理类文件,这些类文件包含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);
}
});
最终HashMap调用格式方法=
新的HashMap();
CompilationUnit cu=(CompilationUnit)ap.createAST(null);
cu.接受(新的ASTVisitor(){
私有方法;
@凌驾
公共布尔访问(MethodDeclaration节点){
activeMethod=node;
返回超级访问(节点);
}
@凌驾
公共布尔访问(MethodInvocation节点){
if(invocationsForMethods.get(activeMethod)==null){
put(activeMethod,newArrayList());
}
获取(activeMethod).add(node);
返回超级访问(节点);
}
});
现在,您可以要求
invocationsForMethods.keySet()
获取所使用的AST
和invocationsForMethods.get(key)
为作为键给出的声明返回所有方法调用。Spyros:您作为问题背景提供的附加信息,应该真正添加到问题本身。在将代码块分解成注释大小的片段之后,应该很明显,它基本上是不可读的。很可能其他阅读我答案的人会跳过这些评论,而错过额外的评论。你可以编辑你的问题;请参见问题下方的**编辑**“按钮”。我冒昧地将您添加的评论移动到您的问题中(排名很高,用户可以这样做),以帮助您。要完成此清理,可以删除这些注释。