Reputation: 307
I´m trying to remove a LineComment from a java file via AST. I read the document from a source file, create an AST parser (AST.JLS3) and afterwards create a CompilationUnit and an ASTRewrite instance.
doc = new Document( doctext );
parser = ASTParser.newParser( AST.JLS3 );
parser.setSource( doc.get().toCharArray() );
cu = (CompilationUnit) parser.createAST( null );
astRewrite = ASTRewrite.create( cu.getAST() );
Nothing special so far, I´m able to add and remove fields a.s.o. Now I´m trying to remove comments from the unit with the following code:
@SuppressWarnings( "unchecked" )
final List<Comment> comments = (List<Comment>) cu.getCommentList();
final Iterator<Comment> commentIter = comments.iterator();
while ( commentIter.hasNext() ) {
final Comment curComment = commentIter.next();
if ( curComment.isLineComment() ) {
final LineComment lineComment = (LineComment) curComment;
lineComment.accept( new CommentCopyrightFieldVisitor( cu, document.get(), astRewrite ) );
}
}
Here´s the visitor that should perform the action and remove the comment.
public class CommentFieldVisitor extends ASTVisitor {
final CompilationUnit cu;
final String sourceCode;
final ASTRewrite astRewrite;
public CommentFieldVisitor( final CompilationUnit cu, final String sourceCode, final ASTRewrite astRewrite ) {
this.cu = cu;
this.sourceCode = sourceCode;
this.astRewrite = astRewrite;
}
@Override
public boolean visit( final LineComment commentNode ) {
int start = commentNode.getStartPosition();
int end = start + commentNode.getLength();
final String comment = sourceCode.substring( start, end );
final String fieldComment = Config.INSTANCE.getTargetFieldComment();
if ( comment != null && comment.equalsIgnoreCase( fieldComment ) ) {
System.out.println( "REMOVE COMMENT" );
assert astRewrite != null : "ERROR: AST Rewriter is null";
astRewrite.remove( commentNode, null );
}
return false;
}
}
I iterate all comments in the compilation unit, I create a visitor for every comment in the list. This visitor checks, if the content of the comment equals a preconfigured string. If it does, it should be removed. Though if I call
astRewrite.remove( commentNode, null );
I always get a NPE from inside the remove method. astRewrite and commentNode are defined (because the remove-code is reached.
Does anyone have an idea, what I might be doing wrong? Or another approach how to remove such a comment via AST?
Upvotes: 2
Views: 727
Reputation: 1374
A tiny bit late here but I'm sure the answer will help other people.
I can confirm the NPE with remove
method when it lacks the required context of a ICompilationUnit
to execute. This results in :
REMOVE COMMENT
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "org.eclipse.jdt.core.dom.StructuralPropertyDescriptor.isChildListProperty()" because "property" is null
at org.eclipse.jdt.core.dom.rewrite.ASTRewrite.remove(ASTRewrite.java:398)
Here's how I do when I don't have such context:
String sourceCode = "/* block comment */ public class Hello {} // line comment";
Document doc = new Document(sourceCode);
ASTParser parser = ASTParser.newParser(AST.getJLSLatest());
parser.setSource(doc.get().toCharArray());
CompilationUnit cu = (CompilationUnit) parser.createAST(null);
ASTRewrite astRewrite = ASTRewrite.create(cu.getAST());
TextEdit edits = astRewrite.rewriteAST(doc, null);
final List<Comment> comments = cu.getCommentList();
List<TextEdit> textEdits = new ArrayList<>();
for (Comment curComment : comments) {
if (curComment.isLineComment()) {
final LineComment lineComment = (LineComment) curComment;
int commentStart = lineComment.getStartPosition();
int commentLength = lineComment.getLength();
int commentEnd = commentStart + commentLength;
String comment = sourceCode.substring(commentStart, commentEnd);
if (comment != null && comment.equalsIgnoreCase("// line comment")) {
textEdits.add(new DeleteEdit(commentStart, commentLength));
}
}
}
edits.addChildren(textEdits.toArray(TextEdit[]::new));
try {
edits.apply(doc);
System.out.println(doc.get());
} catch (MalformedTreeException | BadLocationException e) {
e.printStackTrace();
}
See also this project https://github.com/JnRouvignac/AutoRefactor and especially these 2 classes below:
DeleteEdit
ASTRewrite.remove()
Upvotes: 0
Reputation: 307
I managed it via a workaround which uses Comment.getStartPosition()
and Comment.getLength()
. I use these methods to exract the comments from my source code file and replace them with "". After that I need to re-create the AST tree from the modified source code. This is far away from perfect, but I didn´t find an alternative solution.
Upvotes: 1