Search code examples
eclipseabstract-syntax-treeeclipse-jdt

Eclipse JDT ListRewrite inserts new node at wrong places


I'm trying to add an annotation to some selected fields using Eclipse JDT infrastructure. However, this is not run as a plugin. I added all the required dependencies to a separate project so this can be run in batch mode. However I found out that, the ListRewrite is not inserting my annotation at the right place. I have given the code below. I initially get all the field declarations in a map using a visitor and then add them one by one using the code below.

FieldDeclaration fld = lVrblDet.listStringVarMap.get(propName);
final MarkerAnnotation autoWiredAnnotate = ast.newMarkerAnnotation();                           autoWiredAnnotate.setTypeName(ast.newName("MyAnnot"));
lrw = rewriter.getListRewrite(fld, FieldDeclaration.MODIFIERS2_PROPERTY);
lrw.insertLast(autoWiredAnnotate, null);
Document document = new Document(cu.toString());
try {
    TextEdit edits = rewriter.rewriteAST(document, null);
    edits.apply(document);
} catch (MalformedTreeException | IllegalArgumentException | BadLocationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
}

However the expected output is sometimes offset by 1 character.The input and output classes have been given below.

Input Class:

@SuppressWarnings("unchecked")
public class SampleClassA {

    public SampleClassB classB;

    public SampleClassB getClassB() {
        return classB;
    }

    public void setClassB(SampleClassB classB) {
        this.classB = classB;
    }

    @Deprecated
    public void printNameFromSmapleClassB() {
        System.out.println(this.classB.name);
    }

}

Output Class:

@SuppressWarnings("unchecked") public class SampleClassA {
  p @MyAnnot
ublic SampleClassB classB;
  public SampleClassB getClassB(){
    return classB;
  }
  public void setClassB(  SampleClassB classB){
    this.classB=classB;
  }
  @Deprecated public void printNameFromSmapleClassB(){
    System.out.println(this.classB.name);
  }
}

As you can see in the code above, the Annotation messed with the modifier. I have tried multiple combinations of insertFirst,insertLast.Examples on the net are incomplete. Can somebody point me the mistake/the right resource ?


Solution

  • I just couldn't get it to work with ListRewrite. I don't know what I was doing wrong. So I wrote a visitor to store all the FieldDeclarations in a map.

    @Override
    public boolean visit(FieldDeclaration node) {
        for (Object obj : node.fragments()) {
            listStringVarMap.put(((VariableDeclarationFragment) obj).getName().toString(), node);
        }
        return false;
    }
    

    I looped through the map and inserted the annotation nodes as a modifiers, for the declarations that met my criteria. Please do remember to turn on recormodifications for the compilation unit you are modifying.

    CompilationUnit cu = jFileAst.getEquivCompilUnit();
    cu.recordModifications();
    FieldDeclaration fldDecl = lVrblDet.listStringVarMap.get(propName);
    importVo = (JavaAnnotImportVo) javaAstNodeCreator
                .createASTNode(SpringAnnotationEnum.AutowireAnnotation, ast);
    cu.imports().add(importVo.getImpDecl());
    fldDecl.modifiers().add(0, importVo.getAnnotNode());
    

    Finally write to file on disk/save back. Formatting(optional) before saving is a good idea, because the node insertions mess up with the code formatting.