绑定不能解决eclipse中的AST处理问题
我正在使用eclipse JDT AST解析器来处理一些Java代码,并试图提取字段和方法声明的类型绑定。 这样做的逻辑在我的Visitor类中(见下文)。 不幸的是,我没有任何运气,也没有任何绑定解析(它们始终为空)。 有趣的是,绑定确实与eclipse ASTView插件在相同的代码上工作。 我究竟做错了什么?
这里有一些相关的代码片段,希望能帮助有人弄清楚发生了什么!
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); } }
当你使用:parser.setSource(source); 什么是param“source”的类型?
绑定信息从Java模型获得。 这意味着编译单元必须相对于Java模型。 当源代码来自setSource(ICompilationUnit)或setSource(IClassFile)时,会自动发生这种情况。 当source由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(String)
可能的原因是您不应该直接调用Visitor实例中的方法。 你应该做的事情如下:
unit.accept(visitor);
CompilationUnit的父类ASTNode有一个accept方法,它接受ASTVisitor类型的访问者 。
您编写的访问者GenericVisitor确实是abstarct类ASTVisitor的子类,并覆盖了您所关注的节点类型的实现。因此,我认为更改代码以上述forms进行调用将解决您的问题。
ASTParser只是解析器:它构建了一个AST,这是编译的第一步。 实际的编译器正在做更多的事情:它运行各种访问者,增强了树的附加信息。 其中之一是绑定解析访问者。
特别是,请查看org.eclipse.jdt.internal.compiler.Compiler类中的public void进程(CompilationUnitDeclaration unit,int i)方法的主体。
好的,这是我在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);
神奇的是,问题是解决的! 而且我想你也可以尝试一下。
问题是您的解析器没有提供构建其解析绑定所需的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)
如果您的绑定为空,我不完全确定您的问题是否被其他解释所涵盖。 在我们的代码库中,我们执行以下操作,并且绑定始终存在:
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的事实。 你有没有机会尝试使用这个代码,看看会发生什么?
有时,如果引用的源文件中存在错误,则不会解析对这些类型的绑定。 例如,确保使用源的正确编码和Java版本。
ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setKind(ASTParser.K_COMPILATION_UNIT); parser.setResolveBindings(true); parser.setBindingsRecovery(true); Hashtable 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;