0
votes

I'm trying to inline java method using eclipse jdt/ast.

For example, I'd like to make this code

class Hello {
    static void hello() {
        System.out.println("hello");
    }

    public static void main(String[] args) {
        hello();
        System.out.println("z");
        hello();
        System.out.println("h");
        hello();
    }
}

into this.

class Hello {    
    public static void main(String[] args) {
        System.out.println("hello");
        System.out.println("z");
        System.out.println("hello");
        System.out.println("h");
        System.out.println("hello");
    }
}

I could get the body block of hello() method stored in Block bl.

I also have the body block of main() method stored in Block block, and I could delete hello(); ExpressionStatements in the block.

Then, I need to insert the Block bl to where the hello(); is invoked. I tried

block.statements().add(position, bl.getAST());

and

block.statements().add(position, bl);

where position is the location of hello() method in statements(), but both of them raises an error.

What might be wrong? As Block is Statement, I guess one can insert Block in Block#statements().

enter image description here

ADDED

Based on sevenforce answer, I could get the block inserted, but I have the { and } included.

class Hello {
    public static void main(String[] args) {
    {
        System.out.println("hello");
    }
    System.out.println("z");
    {
        System.out.println("hello");
    }
    System.out.println("h");
    {
        System.out.println("hello");
    }
    }
}

Is there any way to remove them?

ADDED2

With this code:

ASTNode singleStmt = (ASTNode) bl.statements().get(0);
block.statements().add(position, ASTNode.copySubtree(bl.getAST(), singleStmt));

It shows only the first statement in hello() method. For example, with

static void hello() {
    System.out.println("hello");
    System.out.println("hello2");
}

I have only System.out.println("hello"); inlined.

2

2 Answers

2
votes

There are several reasons for add throwing an exception. Normally the specific exception should give you a hint. E.g. the node to be added must be in the same AST.

In your case I'd guess, that you attempt to add the same block object, which is already used in the MethodDeclaration node of hello() and each node is allowed to have just one parent.

A possible solution to that is copying the node:

block.statements().add(position, ASTNode.copySubtree(bl.getAST(), bl));

For extracting single statements the following should work:

ASTNode singleStmt = (ASTNode) bl.statements().get(0);
block.statements().add(position, ASTNode.copySubtree(bl.getAST(), singleStmt));

To add all statements from the block you can just loop over:

for (int i = 0; i < bl.statements().size(); i++) {
     ASTNode singleStmt = (ASTNode) bl.statements().get(i);
     block.statements().add(position + i,
         ASTNode.copySubtree(bl.getAST(), singleStmt));
}
1
votes

Instead of adding to the block you might think of replacing the method invocation.

final ASTRewrite rewriter = ASTRewrite.create(compilationUnit.getAST());

rewriter.replace(methodInvocationNode, blockNode, null);