问题
I am trying to edit several Java classes with the Java AST. But my changes wont show in the Java class files.
What specifically do I want to do? I want to take an IPackageFragment
and visit all the ICompilationUnit
s. For every declared class I want to set the super class to a specific class (using the qualified name of the super class, because it is an Xtend class). I also tried applying the edits via the Document
class.
For example: A class main.model.someClass
should inherit from wrappers.main.model.someClassWrapper
I am relatively new to the JDT API, so I cannot find the reason why the class files are not changed. I already checked this post, but it did not help me. I tried to stay as close as possible to the examples from How To Train the JDT Dragon other tips/examples I got from Stackoverflow. But it will not work.
This is how I do it:
private void editTypesIn(IPackageFragment myPackage) throws JavaModelException {
for (ICompilationUnit unit : myPackage.getCompilationUnits()) {
TypeVisitor visitor = new TypeVisitor(myPackage.getElementName(), unit);
unit.becomeWorkingCopy(new NullProgressMonitor());
CompilationUnit parse = parse(unit);
parse.recordModifications();
parse.accept(visitor);
}
}
private static CompilationUnit parse(ICompilationUnit unit) {
ASTParser parser = ASTParser.newParser(AST.JLS8);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(unit);
parser.setResolveBindings(true);
return (CompilationUnit) parser.createAST(null); // parse
}
And this is the visitor class:
public class TypeVisitor extends ASTVisitor {
private final String currentPackage;
private final ICompilationUnit compilationUnit;
public TypeVisitor(String currentPackage, ICompilationUnit compilationUnit) {
this.currentPackage = currentPackage;
this.compilationUnit = compilationUnit;
}
@Override
public boolean visit(TypeDeclaration node) {
if (!node.isInterface()) { // is class
setSuperClass(node, "wrappers." + currentPackage + "." + node.getName().toString() + "Wrapper");
}
return super.visit(node);
}
public void setSuperClass(TypeDeclaration declaration, String qualifiedName) {
try {
// create ast and rewrite:
AST ast = declaration.getAST();
ASTRewrite astRewrite = ASTRewrite.create(ast);
// set super:
Name name = ast.newName(qualifiedName);
Type type = ast.newSimpleType(name);
declaration.setSuperclassType(type);
// apply changes
TextEdit edits = astRewrite.rewriteAST();
compilationUnit.applyTextEdit(edits, new NullProgressMonitor());
compilationUnit.commitWorkingCopy(true, new NullProgressMonitor());
} catch (JavaModelException exception) {
exception.printStackTrace();
} catch (IllegalArgumentException exception) {
exception.printStackTrace();
} catch (MalformedTreeException exception) {
exception.printStackTrace();
}
}
}
Thanks in advance for any help!
回答1:
I guess your edits will be empty, right?
By calling CompilationUnit.recordModifications()
you tell the AST to internally create an ASTRewrite
into which modifications will be recorded.
By ASTRewrite.create(..)
you are creating a second ASTRewrite
which knows nothing of the modifications being recorded.
The only API for consuming the recorded modifications is CompilationUnit.rewrite(IDocument,Map)
(see references to field AST.rewriter
).
If you need to use your own ASTRewrite
apply the "Descriptive approach", using, e.g., ASTRewrite.set(..)
.
来源:https://stackoverflow.com/questions/42279095/eclipse-ast-not-changing-class-files-when-changing-typedeclaration