2016-03-07 66 views
0

我怎样才能得到org.eclipse.jdt.core.dom.Statement在给定的行号?如何获得给定行号的所有JDT AST语句?

假设我有这个类:

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 } 

这是我所期望的:

  • 3号线 - >BlockStatement
  • 4号线 - >IfStatement
  • 5号线 - >ReturnStatement

这段代码有效,但它有点笨重,因为每个主体和声明都必须在精心设计的案例中访问。有没有更好/更简单的方法来做到这一点?

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

回答

0

您可能需要使用

org.eclipse.jdt.core.dom.CompilationUnit.getPosition(int, int) 

随着该偏移可以使用org.eclipse.jdt.core.dom.NodeFinder检索ASTNode在该位置的行号转换成(基于字节)的位置,S.T.像:

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

编辑: 这种做法,但是,有空白问题,因为开头或结尾空白字符不包括在受到追捧的声明。

我看到两种可能的策略,以避免这个问题:直到你确信它是“中”行的显著文本

  1. 增量的offset,或者
  2. 从下面的注释应用技巧:将该区域延伸至文件结尾并请求完全由该区域覆盖的最大的ASTNode(使用getCoveredNode()而不是getCoveringNode())。

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

+0

我试过你的解决方案,它不会返回给定行的语句,而是返回当前范围中所有行的整个块。如果我为'IfStatement'使用'cu.getPosition(lineNumber + 1,0)',但它不适用于ReturnStatement,那么它特别有效。换句话说:如果我计算一个返回语句的偏移量,我得到一个块,而不是预期的ReturnStatement。 – Chriss

+0

好吧,我在你的例子中发现了两个问题:'新的NodeFinder'的第三个参数不能是0,而是'cu.getLength()'。而不是'finder.getCoveringNode()'方法'finder.getGoveredNode()'必须被调用。你能更新你的答案吗? – Chriss

相关问题