Java 不使用eclipse中的AST处理解析绑定
我正在使用EclipseJDTAST解析器来处理一些Java代码,并试图提取字段和方法声明的类型绑定。这样做的逻辑在我的Visitor类中(见下文)。不幸的是,我没有任何运气,并且没有一个绑定正在解析(它们始终为null)。有趣的是,这些绑定与EclipseAstView插件在同一代码上工作。我做错了什么 下面是一些相关的代码片段,希望能帮助人们了解到底发生了什么Java 不使用eclipse中的AST处理解析绑定,java,eclipse,parsing,Java,Eclipse,Parsing,我正在使用EclipseJDTAST解析器来处理一些Java代码,并试图提取字段和方法声明的类型绑定。这样做的逻辑在我的Visitor类中(见下文)。不幸的是,我没有任何运气,并且没有一个绑定正在解析(它们始终为null)。有趣的是,这些绑定与EclipseAstView插件在同一代码上工作。我做错了什么 下面是一些相关的代码片段,希望能帮助人们了解到底发生了什么 ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setKind(
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);
}
}
可能的原因是您不应该直接在Visitor实例中调用该方法。你应该这样做:
unit.accept(visitor);
CompilationUnit的父类ASTNode有一个方法,该方法接受类型为ASTVisitor的访问者
您编写的访问者GenericVisitor确实将Abstract类ASTVisitor子类化,并覆盖您感兴趣的节点类型的实现。因此,我认为更改代码以执行上述形式的调用可以解决您的问题。ASTParser就是解析器:它构建AST,这是编译的第一步。 实际的编译器所做的不止这些:它运行各种访问者,这些访问者使用附加信息增强了树。其中之一是具有约束力的决议访问者 特别是,请看一下
类中的public void process(CompilationUnitDeclaration unit,int i)方法。如果绑定为null,我不能完全确定其他解释是否涵盖了您的问题。在我们的代码库中,我们执行以下操作,并且绑定始终存在:
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的事实。您是否有可能尝试使用此代码,看看会发生什么情况?当您使用:
parser.setSource(source);
参数“源”的类型是什么
绑定信息来自
Java模型。这意味着
编译单元必须位于
相对于Java模型。这
当源
代码来自任何一个
设置源(ICompilationUnit)或
setSource(IClassFile)。当来源是
由setSource(char[])提供
位置必须被删除
通过调用
setProject(IJavaProject)和
setUnitName(字符串)
这是从
我想也许您只是使用setSource(char[]),而不调用setProject(IJavaProject)和setUnitName(String)有时,如果引用的源文件中出现错误,那么这些类型的绑定将无法解决。例如,确保使用正确的编码和源代码的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;
ASTParser=ASTParser.newParser(AST.JLS3);
setKind(ASTParser.K_编译单元);
setResolveBindings(true);
parser.setBindingsRecovery(true);
Hashtable options=JavaCore.getDefaultOptions();
options.put(JavaCore.COMPILER\u源代码,JavaCore.VERSION\u 1\u 6);
设置编译器选项(选项);
setEnvironment(类路径,源,新字符串[]{“UTF-8”,“UTF-8”},true);
setSource(fileContents.toCharArray());
CompilationUnit CompilationUnit=(CompilationUnit)parser.createAST(null);
IProblem[]problems=compilationUnit.getProblems();
if(problems!=null&&problems.length>0){
warn(“编译源文件时遇到了{}个问题:”,problems.length);
对于(i问题:问题){
logger.warn(“{}”,问题);
}
}
返回编译单元;
好的,这是我关于堆栈溢出的第一个答案。紧张的
我和你有同样的问题,既然你这么做了:
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[],String[],boolean)
和setUnitName(String)
Source:也可以使用parser.setEnvironment(…):“设置在没有IJavaProject可用时可以使用的环境。”我正在尝试实现类似的功能,这里的classpath和sources变量是什么?你能举个例子说明它们的值吗?classpath和sources是字符串数组,具有实际的路径,就像你在java-classpath选项中给出的那样。抱歉,我花了这么长时间才回复…似乎setEnvironment只在JDT3.6之后才可用,但Maven最多只有3.3?你是如何安装3.6的?