views:

103

answers:

3

Hi everyone,

I'm using the eclipse JDT AST parser to process some Java code and am trying to extract the type bindings for fields and method declarations. The logic for doing that is inside my Visitor class (see below). Unfortunately, I'm not having any luck and none of the bindings are resolving (they are consistently null). The interesting thing is that the bindings do work on the same code with the eclipse ASTView plugin. What am I doing wrong?

Here are some relevant code snippets which will hopefully help someone figure out what is going on!

ASTParser parser = ASTParser.newParser(AST.JLS3); 
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(source);
parser.setResolveBindings(true);
CompilationUnit unit = (CompilationUnit) parser.createAST(null);

GenericVisitor visitor = new GenericVisitor(outDir + "//" + file.getName() + ".xml");
visitor.process(unit);


public class GenericVisitor extends ASTVisitor 
{
    public void endVisit(FieldDeclaration node) 
    {
        String bindingInfo = "";    
        ITypeBinding binding = node.getType().resolveBinding();

        if(binding == null)
        {                    
         System.out.println("field declaration binding = null");
        }
        else
        {
         bindingInfo = binding.getQualifiedName();
        }

        endVisitNode(node, bindingInfo); 
    }

    public void endVisit(MethodInvocation node) 
    {
         String bindingInfo = "";   
         IMethodBinding binding = node.resolveMethodBinding();

     if(binding == null)
     {                    
        System.out.println("method binding = null");
     }
     else
     {
         bindingInfo = binding.toString();
     }

    endVisitNode(node, bindingInfo); 
    }
} 
+2  A: 

The probable reason is that you should not be calling the method in Visitor instance directly. You should do something like :

unit.accept(visitor);

The parent class of CompilationUnit, ASTNode, has an accept method which takes a visitor that is of type ASTVisitor.

The Visitor you have written, GenericVisitor, does subclasses the abstarct class ASTVisitor and overrides implementation for the node types you are intersted in. So I think changing your code to do the invocation in above form would fix your problem.

sateesh
+1  A: 

ASTParser is just the parser: It builds an AST which is the first step in compilation. The actual compiler is doing more than that: it runs various visitor which enhance the tree with additional information. One of them is the binding resolution visitor.

In particular, take a look at the body of the public void process(CompilationUnitDeclaration unit, int i) method in the org.eclipse.jdt.internal.compiler.Compiler class.

Itay
A: 

If your bindings are null, I am not entirely sure that your problem is covered by the other explanations. In our code base, we do the following, and the bindings are always there:

public static ASTNode getASTNodeFromCompilationUnit(ICompilationUnit compUnit) {
    ASTParser parser = ASTParser.newParser(AST.JLS3);
    parser.setResolveBindings(true);
    parser.setSource(compUnit);
    return parser.createAST(/* passing in monitor messes up previous monitor state */ null);
}

So the only differences I can see are the order of the calls to resolve bindings, and the fact that we don't call setKind on the parser. Any chance you could try it with exactly this code and see what happens?

Nels Beckman