Rewrite method incorrectly rewrite change to ICompilationUnit the second rewrite update

岁酱吖の 提交于 2019-12-25 00:17:35

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!