我正在使用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的子类,并覆盖了您所关注的节点类型的实现。所以我认为更改代码以上述形式进行调用将解决您的问题。
ASTParser只是解析器:它构建了一个AST,这是编译的第一步。实际的编译器正在做更多的事情:它运行各种访问者,增强了树的附加信息。其中之一是绑定解析访问者。
特别是,看一下org.eclipse.jdt.internal.compiler.Compiler类中public void process(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)
来完成
如果您的绑定为空,我不完全确定您的问题是否被其他解释所涵盖。在我们的代码库中,我们执行以下操作,并且绑定始终存在:
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<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;