4

I read this article from Eclipse wiki (http://wiki.eclipse.org/JDT/FAQ#From_an_IJavaElement_to_its_declaring_ASTNode) but I still can not convert from a IMethod to its corresponding MethodDeclaration.

I have an extension point which adds a popup menu to IMethod objects. Possessing this IMethod object, I want to visit it with an ASTVisitor.

Here is how I'm trying to convert from IMethod to MethodDeclaration

public static MethodDeclaration convertToAstNode(final IMethod method) throws JavaModelException
{
    final ICompilationUnit compilationUnit = method.getCompilationUnit();

    final ASTParser astParser = ASTParser.newParser( AST.JLS4 );
    astParser.setSource( compilationUnit );
    astParser.setKind( ASTParser.K_COMPILATION_UNIT );
    astParser.setResolveBindings( true );
    astParser.setBindingsRecovery( true );

    final ASTNode rootNode = astParser.createAST( null );

    final CompilationUnit compilationUnitNode = (CompilationUnit) rootNode;

    final String key = method.getKey();

    final ASTNode javaElement = compilationUnitNode.findDeclaringNode( key );

    final MethodDeclaration methodDeclarationNode = (MethodDeclaration) javaElement;

    return methodDeclarationNode;
}

What am I missing?

EijiAdachi
  • 441
  • 1
  • 3
  • 15
  • what error are u getting. Is it a compile time or run time exception. Inlcude the stack trace in ur question. – Unni Kris Sep 19 '12 at 07:54
  • 1
    compilationUnitNode.findDeclaringNode( key ) always returns null, but the key actually points to a method within the compilationUnit – EijiAdachi Sep 19 '12 at 11:25
  • Check for this 'iMethod.isResolved()', this will return if your method key is resolved and if it can used for finding the declared node. – Unni Kris Sep 21 '12 at 04:27
  • 1
    Thanks UnniKris. That's exactly what I was told in JDT Forum. There I also posted a workaround when isResolved()==false http://www.eclipse.org/forums/index.php/t/378956/ – EijiAdachi Sep 24 '12 at 02:51
  • Thanks Eiji, the workaround was helpful.. – Unni Kris Sep 28 '12 at 10:46

1 Answers1

2

I realize this question is quite old now, but I want to post this solution in case future Googlers happen to stumble upon it :)

The workaround EijiAdachi posted in the comments should work, but there's a more "proper" way to do this that I discovered while searching for a solution.

In order for the ASTNode to correctly resolve the bindings, the contents of the page need to be fully parsed first. This is done via the (somewhat oddly named IMHO) ASTNode.accept(ASTVisitor) method. So if you subclass ASTVisitor, you can override the visit methods for all of the ASTNode types you care about and add them to data structures obtainable after the AST has been fully parsed.

This example will make accessible all of the MethodDeclaration nodes in your CompilationUnit root node (see OP for how to get that via the ASTParser class):

public class MethodVisitor extends ASTVisitor {
  private final List <MethodDeclaration> methods = new ArrayList <> ();

  @Override
  public boolean visit (final MethodDeclaration method) {
    methods.add (method);
    return super.visit (method);
  }

  /**
   * @return an immutable list view of the methods discovered by this visitor
   */
  public List <MethodDeclaration> getMethods () {
    return Collections.unmodifiableList (methods);
  }
}

Any of the other ASTNode subtypes can be rounded up using the exact same process (you could make separate visitor types or put it all in one).

If anyone is interested, you can look for a more complete example in this tutorial article.

bgroenks
  • 1,859
  • 5
  • 34
  • 63