Search code examples
javaeclipseeclipse-jdt

Adding method parameters using Eclipse AST


Here is the issue:

I have a class for e.g.,

public class EmployeeServiceImpl  {


@Autowired
EmployeeDAO empDAO;

public void findDepartments() throws NoEmployeeFoundException {

        int age = empDAO.findEmployeeById(12).getAge();

        if( age  > 30 ){
            //do something
        }else{
            //do something else.
        }

}
}

My goal is to :

(1) detect the variable assignment (2) remove the variable assignment and (3) add the assigned variable as method parameter.

So, after AST transformation, the code will look like :

public class EmployeeServiceImpl  {


@Autowired
EmployeeDAO empDAO;

public void findDepartments(int age) throws NoEmployeeFoundException {

        if( age  > 30 ){
            //do something
        }else{
            //do something else.
        }

}
}

I am able to do (1) & (2). However, for (3), although the variable assignment node is getting removed, I'm not able to add the parameter to the method. The AST transformer code is given below. What am I missing? (Please forgive the monolithic code and the absolute disregard for sound design)

    MethodVisitor visitor = new MethodVisitor();

            String source = unit.getSource();
            Document document = new Document(source);

            ASTParser parser = ASTParser.newParser(AST.JLS3);
            parser.setSource(unit);

            CompilationUnit astRoot = parse(unit);
            AST ast = astRoot.getAST();


            astRoot.accept(visitor);

            TestGenClassVisitor classVisitor = new TestGenClassVisitor();
            for (MethodDeclaration method : visitor.getMethods()) {
                method.accept( classVisitor );
            }


            // creation of ASTRewrite
            ASTRewrite rewrite = ASTRewrite.create( ast );

            astRoot.recordModifications();

            // for getting insertion position
            TypeDeclaration typeDecl = (TypeDeclaration) astRoot.types()
                    .get(0);
            MethodDeclaration methodDecl = typeDecl.getMethods()[0];
            Block block = methodDecl.getBody();

            List<VariableDeclarationStatement> varDeclarations = classVisitor.getReplaceableVardDeclarationNodes();
            ListRewrite listRewrite = rewrite.getListRewrite(block,
                    Block.STATEMENTS_PROPERTY);

            TextEditGroup textEditGroup = new TextEditGroup("abc");

            for( VariableDeclarationStatement statement : varDeclarations ){


                List<VariableDeclarationFragment> fragments = statement.fragments();

                for( VariableDeclarationFragment fragment : fragments){

                    IVariableBinding varBinding = fragment.resolveBinding();

                    System.out.println("Will replace node with var name :"+ varBinding.getName() +", of type :"+varBinding.getType().getQualifiedName());

                    SingleVariableDeclaration singleVariableDeclaration = ast.newSingleVariableDeclaration();
                    singleVariableDeclaration.setType(ast.newPrimitiveType(PrimitiveType.toCode(varBinding.getType().getQualifiedName())));
                    singleVariableDeclaration.setName(ast.newSimpleName(varBinding.getName()));
                    singleVariableDeclaration.setVarargs(false);
                    singleVariableDeclaration.setExtraDimensions(0);

                    methodDecl.parameters().add(singleVariableDeclaration);

                }

                listRewrite.remove(statement, textEditGroup);


            }


            TextEdit edits = rewrite.rewriteAST();

            // computation of the new source code
            try {
                edits.apply(document);
            } catch (MalformedTreeException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (BadLocationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


            String newSource = document.get();


            FileOutputStream fos = null;
            try {
                File newFile = File.createTempFile("Modified", ".java");

                fos = new FileOutputStream(newFile);
                fos.write(newSource.getBytes());
                fos.flush();

                System.out.println("File created at " + newFile.getCanonicalPath());

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally{
                try {
                    fos.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

Solution

  • The trick was to use ListRewrite properly. Solved it using the following code:

        ASTRewrite rewrite = ASTRewrite.create( ast );
    
                astRoot.recordModifications();
    
                // for getting insertion position
                TypeDeclaration typeDecl = (TypeDeclaration) astRoot.types()
                        .get(0);
                MethodDeclaration methodDecl = typeDecl.getMethods()[0];
    
                Block block = methodDecl.getBody();
    
    
                ListRewrite paramRewrite = rewrite.getListRewrite( methodDecl ,
                        MethodDeclaration.PARAMETERS_PROPERTY);
    
    
                ListRewrite listRewrite = rewrite.getListRewrite( block ,
                        Block.STATEMENTS_PROPERTY );
    
                List<SingleVariableDeclaration> paramList = new ArrayList<SingleVariableDeclaration>();
    
                List<VariableDeclarationStatement> varDeclarations =  classVisitor.getReplaceableVardDeclarationNodes();
    
                for( VariableDeclarationStatement statement : varDeclarations ){
    
    
                    List<VariableDeclarationFragment> fragments = statement.fragments();
    
                    for( VariableDeclarationFragment fragment : fragments){
    
                        IVariableBinding varBinding = fragment.resolveBinding();
    
                        System.out.println("Will replace node with var name :"+ varBinding.getName() +", of type :"+varBinding.getType().getQualifiedName());
    
    
                        SingleVariableDeclaration singleVariableDeclaration = ast.newSingleVariableDeclaration();
                        singleVariableDeclaration.setType(ast.newPrimitiveType(PrimitiveType.toCode(varBinding.getType().getQualifiedName())));
                        singleVariableDeclaration.setName(ast.newSimpleName(varBinding.getName()));
    
                        paramRewrite.insertLast( singleVariableDeclaration, null);
    
    
                    }
    
                    listRewrite.remove(statement, null);
    
    
                }
    
    
                TextEdit edits = rewrite.rewriteAST(document, null);