我正在使用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);
}
}
答案 0 :(得分:8)
使用时: parser.setSource(源); 什么是param“source”的类型?
从中获取绑定信息 Java模型。这意味着 必须找到编译单元 相对于Java模型。这个 当源自动发生 代码来自任何一个 setSource(ICompilationUnit)或 的SetSource(IClassFile)。当来源是 由setSource(char [])提供, 必须建立位置 明确地通过调用 setProject(IJavaProject)和 setUnitName(字符串)。
这来自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)
答案 1 :(得分:2)
可能的原因是您不应该直接调用Visitor实例中的方法。你应该做点什么:
unit.accept(visitor);
CompilationUnit , ASTNode 的父类有一个accept方法,它接受类型为 ASTVisitor 的访问者。
您编写的访问者 GenericVisitor 确实是abstarct类 ASTVisitor 的子类,并覆盖了您所关注的节点类型的实现。所以我认为将您的代码更改为以上述形式进行调用可以解决您的问题。
答案 2 :(得分:1)
ASTParser只是解析器:它构建了一个AST,这是编译的第一步。 实际的编译器正在做更多的事情:它运行各种访问者,增强了树的附加信息。其中一个是绑定解析访问者。
特别要看一下身体 org.eclipse.jdt.internal.compiler.Compiler类中的public void process(CompilationUnitDeclaration unit,int i)方法。
答案 3 :(得分: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);
奇怪的是,问题是解决的!我想你也可以尝试一下。
答案 4 :(得分:1)
问题是您的解析器未提供构建其解析绑定所需的Java模型的必要信息。
如果解析器的源是从setSource(ICompilationUnit)
或setSource(IClassFile)
获得的,则此信息会自动提供给解析器。
但是,如果您使用setSource(char[])
,则必须为解析器提供此上下文。这可以通过致电parser.setProject(IJavaProject)
或setEnvironment(String[], String[], String[], boolean)
和setUnitName(String)
答案 5 :(得分: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的事实。你有没有机会尝试使用这段代码,看看会发生什么?
答案 6 :(得分:-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;