Search code examples
javaeclipse-jdt

Is there any way to convert the test code to a MethodDeclaration using Eclipse JDT?


Assume that I already had a CompilationUnit unit parsed from a Java file. Now, I want to add some new complex methods to Java file. With the simple method such as

public static void main(String[] args) {
    System.out.println("Hello" + " world");
}

we can manually program as example: http://publib.boulder.ibm.com/infocenter/rsmhelp/v7r0m0/index.jsp?topic=/org.eclipse.jdt.doc.isv/guide/jdt_api_manip.htm

However, with complex method, it seems to be impossible. I think another solution is that: store the entire method to a String, then parse it and add the result to existing compilation unit.

Is there any way to convert the test code to a MethodDeclaration, then append to the existing compilation unit using eclipse JDT?


Solution

  • I assume here, that you are speaking of a CompilationUnit and a MethodDeclaration in the org.eclipse.jdt.core.dom package.

    However, with complex method, it seems to be impossible.

    Actually you could theoretically create any possible legal Java code using the org.eclipse.jdt.core.dom API, by creating and linking the corresponding ASTNodes using the various AST#new-methods.

    For complex code, it is however more convenient to parse existing statements using an ASTParser. To do that, you must first set the source of the parser to the code of the statements, and then set the parser kind to ASTParser.K_STATEMENTS. Then, when creating an ASTNode by calling ASTParser#createAST, the returned node will be of type Block. Before you can set this block as e.g. the block of a MethodDeclaration, you must copy the block to the existing AST by calling ASTNode.copySubtree(ast, block).

    Here is a complete example, that shows how this could be done:

    import org.eclipse.jdt.core.dom.AST;
    import org.eclipse.jdt.core.dom.ASTNode;
    import org.eclipse.jdt.core.dom.ASTParser;
    import org.eclipse.jdt.core.dom.Block;
    import org.eclipse.jdt.core.dom.CompilationUnit;
    import org.eclipse.jdt.core.dom.MethodDeclaration;
    import org.eclipse.jdt.core.dom.TypeDeclaration;
    
    public class JdtDomExample {
    
        public static void main(String[] args) {
    
            // (1) somehow get an org.eclipse.jdt.core.dom.CompilationUnit, a TypeDeclaration, and a MethodDeclaration
            AST ast = AST.newAST(AST.JLS8);
            CompilationUnit cu =  ast.newCompilationUnit();
            TypeDeclaration typeDecl = ast.newTypeDeclaration();
            typeDecl.setName(ast.newSimpleName("MyClass"));
            cu.types().add(typeDecl);
            MethodDeclaration method = cu.getAST().newMethodDeclaration();
            method.setName(ast.newSimpleName("myMethod"));
            typeDecl.bodyDeclarations().add(method);
    
            // (2) create an ASTParser and parse the method body as ASTParser.K_STATEMENTS
            ASTParser parser = ASTParser.newParser(AST.JLS8);
            parser.setSource("System.out.println(\"Hello\" + \" world\");".toCharArray());
            parser.setKind(ASTParser.K_STATEMENTS);
            Block block = (Block) parser.createAST(null);
    
            // (3) copy the statements to the existing AST
            block = (Block) ASTNode.copySubtree(ast, block);
            method.setBody(block);
    
            // show the result
            System.out.println(cu);
        }
    }
    

    Output:

    class MyClass {
      void myMethod(){
        System.out.println("Hello" + " world");
      }
    }