如何获取给定行号处的所有 JDT AST 语句?

How to get all JDT AST Statement's at a given line number?

如何在给定的行号处获得 org.eclipse.jdt.core.dom.Statement

假设我有这个 class:

 1 package foo;
 2 public class Operations {
 3  public static int calc(int a, int b) {
 4      if (a >= b)
 5          return a - b;
 6      if (a<b || b==2)
 7          return -1;
 8      return 0;
 9  }
10 }

这是我所期望的:

此代码有效,但有点笨重,因为在最坏的情况下必须访问每个主体和语句。有 better/simpler 的方法吗?

List<Statement> getStatementsAtLine(final CompilationUnit cu, final int lineNumber) {
        final List<Statement> result = new ArrayList<Statement>();
        cu.accept(new ASTVisitor() {
            @Override
            public boolean visit(MethodDeclaration node) {
                Block body = node.getBody();

                for (Statement s : (List<Statement>) body.statements()) {
                    int l=cu.getLineNumber(s.getStartPosition());
                    if (l==lineNumber){
                        result.add(s);
                    }
                }
                return true;
            }
        });

        return result;
    }

您可能希望使用

将行号转换为(字符)位置
org.eclipse.jdt.core.dom.CompilationUnit.getPosition(int, int)

使用该偏移量,您可以使用 org.eclipse.jdt.core.dom.NodeFinder 在该位置 s.t 检索 ASTNode。喜欢:

NodeFinder finder= new NodeFinder(cu, offset, 0);
ASTNode node= finder.getCoveringNode();
while (node != null && !(node instanceof Statement)) {
    node= node.getParent();
}
return node;

编辑: 但是,这种方法对于白色 space 有问题,因为前导或尾随的白色 space 字符未包含在所查找的语句中。

我看到了两种可能的策略来避免这个问题:

  1. 增加 offset 直到您确定它是 "within" 该行的重要文本,或者
  2. 应用下面评论中的技巧:将区域扩展到文件末尾并要求最大的 ASTNode 完全被该区域覆盖(使用 getCoveredNode() 而不是 getCoveringNode()).

策略 (1) 需要通过 IDocument 检索相关行的文本,这可能不容易获得。 策略 (2) 可能会产生这样的效果,即可以选择跨越多行的语句,但不确定这是否违反任何要求。如果需要更高的精度,计算 getPosition() 的长度参数作为当前行开始和下一行开始之间的差异。