问题
I have this method UpdateProperty:
public void run(ObjectNavigatorModel model, String propertyKey,
String propertyValue) {
// get reference to CompilationUnit
ICompilationUnit cu = model.getICompilationUnit();
try {
cu.becomeWorkingCopy(null);
} catch (JavaModelException e1) {
e1.printStackTrace();
}
// unit instance of CompilationUnit
CompilationUnit unit = model.getCompilationUnit();
AST ast = unit.getAST();
ASTRewrite rewrite = ASTRewrite.create(ast);
// get methods map
MethodVisitor visitor = new MethodVisitor();
unit.accept(visitor);
Map<String, MethodDeclaration> methodMap = new Hashtable<String, MethodDeclaration>();
for (MethodDeclaration methodDeclaration : visitor.getMethods()) {
methodMap.put(methodDeclaration.getName().toString(),
methodDeclaration);
}
// find the reference to the MethodDeclaration
MethodDeclaration methodDecl = null;
@SuppressWarnings("rawtypes")
Hashtable nameIndex = (Hashtable) StatementVisitor.queryTable.get(model.getClass().getSimpleName());
String methodName = (String) ((nameIndex!=null) ? nameIndex.get("modelName") : model.getClass().getSimpleName());
System.out.println("methodName: " + methodName);
if (methodMap.containsKey("get" + methodName + model.getOriginalName())) {
methodDecl = methodMap.get("get" + methodName + model.getOriginalName());
}
if (methodDecl == null)
// failed to find correct method
return;
// finding the existing statement
Block block = methodDecl.getBody();
List<?> statements = block.statements();
Iterator<?> iter = statements.iterator();
System.out.println("property key:"+propertyKey);
System.out.println("property value:"+propertyValue);
while (iter.hasNext()) {
// get each statement
Statement stmt = (Statement) iter.next();
stmt.accept(new UpdatePropertyStatementVisitor(propertyKey,
propertyValue, rewrite));
}
TextEdit edits;
try {
Document document = new Document(cu.getSource());
// computation of the text edits
edits = rewrite.rewriteAST(document, cu.getJavaProject()
.getOptions(true));
// computation of the new source code
edits.apply(document);
String newSource = document.get();
// update of the compilation unit
cu.getBuffer().setContents(newSource);
File file = cu.getResource().getLocation().toFile();
write(newSource, file);
cu.getResource().refreshLocal(0, null);
cu.close();
}
catch (CoreException e) {
e.printStackTrace();
}
}
public static void write(String content, File file)
throws IOException {
// create file if it necessary
if (!file.exists()) {
file.createNewFile();
}
// write to file
// Use printwriter with buffered writer is faster than FileWriter
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
out.write(content);
out.close();
}
and the propertyStatementVisitor to replace ASTNode with updated value: public class UpdatePropertyStatementVisitor extends ASTVisitor{ private String propertyKey; private String propertyValue; private ASTRewrite rewrite;
public UpdatePropertyStatementVisitor(String propertyKey,
String propertyValue, ASTRewrite rewrite) {
this.propertyKey = propertyKey;
this.propertyValue = propertyValue;
this.rewrite = rewrite;
}
/* Auto called by eclipse JDT, see visitor pattern
* (non-Javadoc)
* @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ExpressionStatement)
*/
public boolean visit(ExpressionStatement stmt)
{
// first, go down to MethodInvocation level
Expression expression = stmt.getExpression();
if (expression instanceof MethodInvocation)
{
MethodInvocation mi = (MethodInvocation) expression;
// check method name, e.g. setHeight(5);
String miName = mi.getName().toString();
miName = miName.replaceAll("((?<=[a-z])[A-Z]|[A-Z](?=[a-z]))"," $1");
String[] array = miName.split(" ");
if (array[0].equals("set"))
{
// merge remaining parts of the split method name
StringBuilder key = new StringBuilder();
for (int i = 1; i < array.length; i++) {
key.append(array[i]);
}
if (key.toString().equalsIgnoreCase(propertyKey)) {
System.out.println("found set property");
// do the replace, if the key matches
StringLiteral newValue = mi.getAST().newStringLiteral();
newValue.setEscapedValue("\""+propertyValue+"\"");
// the argument to change update index, so far 1st argument for all cases, i.e. 0
System.out.println("Inside Visit Statement: \npropertyValue:"+propertyValue+ " \n arguments[0]"+(ASTNode) mi.arguments().get(0) + "/n NewValue:"+ newValue );
rewrite.replace((ASTNode) mi.arguments().get(0), newValue, null);
return true;
}
}
}
return false;
}
}
The goal is to set Name property String value in a method of one file:
// Setting alert properties GOT PROBLEM HERE!!!!
alert.setName("Delete_Alert");
alert.setMessage("Are you sure you want to remove this customer? (Note: changes do not become final until you Save them.)");
My problem is, the first time I update value of a statement, it works, but the second time the write back is not accurate, it just eat away the next line of code next-to the supposed to write. Sth like this:
//1st Attempt:
Alert.setName("Delete_Alert_firstAttempt") //(Success)
alert.setMessage("Are you sure you want to remove this customer? (Note: changes do not become final until you Save them.)");
//2nd Attempt:
Alert.setName("Delete_Alert_secondAttempt"Are you sure you want to remove this customer? (Note: changes do not become final until you Save them.)"); //(fail)
Any JDT expert can point out what is the error?
来源:https://stackoverflow.com/questions/12834151/rewrite-method-incorrectly-rewrite-change-to-icompilationunit-the-second-rewrite