How can I get the org.eclipse.jdt.core.dom.Statement
at a given line number?
Assume I have this 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 }
This is what i expect:
BlockStatement
IfStatement
ReturnStatement
This code works but it is a bit bulky because every body and statement must be visited in the worsed case. Is there a better/simpler way to do it?
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;
}
You may want to convert the line number into a (character-) position using
org.eclipse.jdt.core.dom.CompilationUnit.getPosition(int, int)
With that offset you can use the org.eclipse.jdt.core.dom.NodeFinder
to retrieve the ASTNode
at that position, s.t. like:
NodeFinder finder= new NodeFinder(cu, offset, 0);
ASTNode node= finder.getCoveringNode();
while (node != null && !(node instanceof Statement)) {
node= node.getParent();
}
return node;
EDIT: This approach, however, has a problem with white space, because leading or trailing white space characters are not covered by the statement being sought.
I see two possible strategies to avoid this problem:
offset
until you are sure it is "within" the significant text of the line, orASTNode
completely covered by this region (using getCoveredNode()
instead of getCoveringNode()
).Strategy (1) requires to retrieve the text of the line in question via the IDocument, which may not be readily available.
Strategy (2) may have the effect that a statement spanning several lines may be selected, not sure if this is against any requirement. If more precision is needed, calculate the length argument for getPosition()
as the difference between the current line start and the next line start.