2010-01-07 26 views
7

我正在使用eclipse JDT AST解析器来处理一些Java代码,并试图提取字段和方法声明的类型绑定。这样做的逻辑是在我的Visitor类中(见下文)。不幸的是,我没有任何运气,也没有任何绑定解决(它们始终为空)。有趣的是,绑定可以在日食ASTView插件上使用相同的代码。我究竟做错了什么?在eclipse中无法通过AST处理来解决绑定

这里有一些相关的代码片段,希望能帮助别人找出发生了什么!

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

可能的原因是您不应直接在Visitor实例中调用方法。你应该这样做:

unit.accept(visitor); 

父类 CompilationUnit ASTNode的,有一个accept方法,这需要一个访问者是类型的ASTVisitor的。你写

访客, GenericVisitor,确实子类abstarct类的ASTVisitor和覆盖实现你中位数的节点类型,所以我想改变你的代码做调用上述形式将解决您的问题。

1

ASTParser只是解析器:它构建了一个AST,这是编译的第一步。 实际的编译器做的不止于此:它运行各种访问者,通过附加信息增强树。其中之一是具有约束力的解析访问者。

尤其要看 public void process(CompilationUnitDeclaration unit,int i)方法中的org.eclipse.jdt.internal.compiler.Compiler类。

0

如果您的绑定为空,我不完全确定您的问题已被其他解释所覆盖。在我们的代码库,我们做到以下几点,并绑定总是在那里:

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); 
} 

所以我可以看到,唯一的区别是调用的顺序来解析绑定,而事实上,我们不叫解析器上的setKind。任何机会,你可以试试这个代码,看看会发生什么?

8

当您使用: parser.setSource(source); 参数“源”的类型是什么?

绑定信息从 Java模型获得。这意味着 编译单元必须位于相对于Java模型的 。当源 代码来自 setSource(ICompilationUnit)或 setSource(IClassFile)时,此 会自动发生。当源为由setSource(char [])提供的 时,必须通过调用 setProject(IJavaProject)和 setUnitName(String)明确地建立 位置 。

这是http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ASTParser.html 我想,也许你只需要使用的SetSource(的char []),而无需调用setProject(IJavaProject)和setUnitName(字符串)

+0

你也可以使用parser.setEnvironment(...):“设置时,没有IJavaProject可用,可用于环境” – roesslerj 2012-06-19 10:10:47

-1

有时候,如果你在引用的源文件有错误,那么这些类型的绑定就不会被解析。例如,确保您使用了正确的编码和Java版本的源代码。

ASTParser parser = ASTParser.newParser(AST.JLS3); 
    parser.setKind(ASTParser.K_COMPILATION_UNIT); 
    parser.setResolveBindings(true); 
    parser.setBindingsRecovery(true); 
    Hashtable<String, String> options = JavaCore.getDefaultOptions(); 
    options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6); 
    parser.setCompilerOptions(options); 
    parser.setEnvironment(classpath, sources, new String[] { "UTF-8", "UTF-8" }, true); 
    parser.setSource(fileContents.toCharArray()); 
    CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null); 
    IProblem[] problems = compilationUnit.getProblems(); 
    if (problems != null && problems.length > 0) { 
     logger.warn("Got {} problems compiling the source file: ", problems.length); 
     for (IProblem problem : problems) { 
      logger.warn("{}", problem); 
     } 
    } 
    return compilationUnit; 
+0

我试图实现类似这样的东西,这里的类路径和源变量是什么?你能举一个他们的价值的例子吗? – Braden 2012-07-17 23:49:35

+0

classpath和sources是String的数组,其实际路径与您在java -classpath选项中给出的一样。对不起,我花了这么长的时间来回应... – roesslerj 2012-09-06 20:19:09

1

好的,这是我在Stack Overflow上的第一个答案。神经...

我得到了同样的问题与你,因为你已经这样做了:

parser.setResolveBindings(true); 

让我们来看看它是否工作通过检查这一点:

if (unit.getAST().hasResolvedBindings()) { 
    System.out.println("Binding activated."); 
} 
else { 
    Ststem.out.println("Binding is not activated."); 
} 

而且我觉得结果是“绑定未激活”。这就是为什么你总是得到空指针的原因。

然后,我这个语句添加到我的代码:

parser.setEnvironment(null, null, null, true); 

奇妙的是,在解决问题!我想你也可以试试这个。

+0

看起来setEnvironment只能从JDT 3.6开始提供,但Maven只能达到3.3?你是如何安装3.6的? – 2017-01-07 16:34:56

1

问题是您的解析器尚未提供必要的信息来构建其解析绑定所需的Java模型。

如果解析器的源是从setSource(ICompilationUnit)setSource(IClassFile)获得的,则将此信息自动提供给解析器。

但是,如果使用setSource(char[])代替,则必须为解析器提供此上下文。这可以通过调用parser.setProject(IJavaProject)setEnvironment(String[], String[], String[], boolean)setUnitName(String)

完成来源:http://help.eclipse.org/kepler/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ASTParser.html#setResolveBindings(boolean)

相关问题