【问题标题】:bindings not resolving with AST processing in eclipseEclipse 中的 AST 处理无法解析绑定
【发布时间】:2017-12-20 00:31:00
【问题描述】:

我正在使用 eclipse JDT AST 解析器来处理一些 Java 代码,并尝试提取字段和方法声明的类型绑定。这样做的逻辑在我的访问者类中(见下文)。不幸的是,我没有任何运气,并且没有任何绑定正在解决(它们始终为空)。有趣的是,绑定确实使用 eclipse ASTView 插件在相同的代码上工作。我做错了什么?

这里有一些相关的代码 sn-ps,希望能帮助人们弄清楚发生了什么!

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

【问题讨论】:

    标签: java eclipse parsing


    【解决方案1】:

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

    绑定信息来自 Java 模型。这意味着 编译单元必须位于 相对于 Java 模型。这个 当源自动发生 代码来自任一 setSource(ICompilationUnit) 或 设置源(IClassFile)。当源是 由 setSource(char[]) 提供, 必须说明位置 通过调用显式 setProject(IJavaProject) 和 设置单位名称(字符串)。

    这是来自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)

    【讨论】:

    • 也可以使用parser.setEnvironment(...):“设置没有IJavaProject可用时可以使用的环境。”
    【解决方案2】:

    问题是您的解析器没有提供必要的信息来构造解析绑定所需的 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)

    【讨论】:

      【解决方案3】:

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

      unit.accept(visitor);
      

      CompilationUnit 的父类ASTNode 有一个accept 方法,该方法接收ASTVisitor 类型的访问者。

      您编写的访问者 GenericVisitor 确实继承了抽象类 ASTVisitor 并覆盖了您感兴趣的节点类型的实现。所以我认为将您的代码更改为以上述形式进行调用将解决您的问题。

      【讨论】:

        【解决方案4】:

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

        特别是看看身体 org.eclipse.jdt.internal.compiler.Compiler 类中的 public void process(CompilationUnitDeclaration unit, int i) 方法。

        【讨论】:

          【解决方案5】:

          有时,如果您在引用的源文件中遇到错误,则无法解析与这些类型的绑定。例如,确保您使用正确的编码和 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;
          

          【讨论】:

          • 我正在尝试实现类似的东西,这里的类路径和源变量是什么?你能举例说明他们的价值观吗?
          • 类路径和源是具有实际路径的字符串数组,就像您在 java -classpath 选项中给出的那样。抱歉这么久才回复...
          【解决方案6】:

          好的,这是我在 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);
          

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

          【讨论】:

          • 似乎 setEnvironment 仅从 JDT 3.6 开始可用,但 Maven 最多只有 3.3?你是如何安装 3.6 的?
          【解决方案7】:

          如果您的绑定为空,我不完全确定其他解释是否涵盖了您的问题。在我们的代码库中,我们执行以下操作,并且绑定始终存在:

          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 的事实。你有没有机会用这段代码试一试,看看会发生什么?

          【讨论】:

            猜你喜欢
            • 2015-01-22
            • 1970-01-01
            • 2013-08-03
            • 2013-03-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多