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();
}
}
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);