Reputation: 59
How can I get the names of the methods invoked in each method declaration of a program using AST (Abstract Syntax Tree) parser? So far, I have managed to get all the names of the methods' declaration and all the names of the methods being invoked, but I want to know which method call which methods. For example, I want to see that method m1
calls methods mA
and mB
, while method m2
calls methods mC
and mD
, etc.
[EDIT 11/9/2011 IDB, transcribing newbie's extended comment back in the body of the original question. I hope I have transcribed it correctly. I hope the author comes back and revises as necessary]:
My problem seems to be that (Eclipse's) MethodDeclaration api doesn't have a GetInvokedMethodName function to call. Here is my code:
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() ); }
Upvotes: 4
Views: 5013
Reputation: 148
I had the same problem. This was my solution to it:
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);
}
});
Now, one can ask the invocationsForMethods.keySet()
to get all the method declarations for the used AST
and invocationsForMethods.get(key)
returns all method invocations for the declaration given as a key.
Upvotes: 3
Reputation: 95334
If you want to know which specific method mB (of all the ones named "mB" throughout your vast array of classes) is invoked by m1, you need more than just the AST. You need a full symbol table, that binds each symbol use to the possible definitions that match it.
The process of computing such a symbol table is difficult for many languages and very hard for Java (but not nearly as bad as it is for C++). Somebody has to encode the rules of how an identifier is looked up in the face of (local) scopes, inheritance, overloads, implied casts, etc, and the Java reference manual devotes a significant portion of its content trying to explain that. You don't want to have to do this yourself.
What you really need is a full Java front end, that has both ASTs and the corresponding symbol tables, for each method you want to inspect. You can get this, I think, from interfaces to the (Sun?) Java compiler (I don't personally know how to do this), from the Jikes compiler, from the Eclipse Java AST (?) module, and from tools such as our Java Front End. Another approach is to process class files, which contain the method calls in JVM form, with the advavntage that the JVM instructions all have built with the benefit of a symbol table.
If you want to compute m1 calls mA calls mQ calls .... mZ, you need a tool that is willing to read in the entire source code base at once. The compilers won't do that for you, but you can use Eclipse or our front end to do that.
Upvotes: 2