Search code examples
javaparsingcommentsabstract-syntax-treeeclipse-jdt

How to preserve comments in Eclipse JDT


I'm using Eclipse JDT to modify java source code. This happens in three steps:

  • At first I create an instance of org.eclipse.jdt.core.dom.CompilationUnit and call it's accept() method with an ASTVisitor
  • Then I manipulate the CompilationUnit. I remove and add ASTNodes to the tree (this is not shown here)
  • Then I write compilationUnit.toString() back to a file.

Creation of the compilation unit:

ASTParser parser = ASTParser.newParser(AST.JLS11);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(readSourceCode("FooBar.java"));
parser.setStatementsRecovery(false);
Hashtable<String, String> options = JavaCore.getDefaultOptions();
options.put("org.eclipse.jdt.core.compiler.doc.comment.support", "enabled");
parser.setCompilerOptions(options);
CompilationUnit compUnit = (CompilationUnit) parser.createAST(null);
compUnit.accept(new FooBarVisitor());

Write changed compUnit to a file:

writer = new BufferedWriter(new FileWriter(newFilePath));
Map options = DefaultCodeFormatterConstants.getEclipseDefaultSettings();
CodeFormatter formatter = ToolFactory.createCodeFormatter(options);
String sourceCode = result.getCompilationUnit().toString();
int formatType = CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS | CodeFormatter.K_UNKNOWN;
TextEdit edit = formatter.format(formatType, sourceCode, 0, sourceCode.length(), 0, System.getProperty("line.separator"));
Document document = new Document(sourceCode);
edit.apply(document);
writer.write(document.get());
writer.close();

Example file which contains multiple comments:

package foo.bar;
/**
 * Multiline
 * Javadoc
 */
public class FooBar {
    // inline comment
    private String foo = "bar";
    public String getFoo() {
        /*
         * Multiline
         * comment
         */
        return foo;
    }
}

Corresponding output:

package foo.bar;
/**
 * Multiline Javadoc
 */
public class FooBar {
    private String foo = "bar";
    public String getFoo() {
        return foo;
    }
}

There are two problems: Firstly the multiline javadoc is compressed to only one line. Secondly, the other two comments are removed completely.

How can i fix this?


Solution

  • I believe you start losing information when you do compilationUnit.toString(). Later when you format the text, you finally lose any existing formatting.

    Instead, I recommend to learn how to use ASTRewrite, which allows you to incrementally apply your changes into the existing AST. The goal is to let the rewrite generate the minimal TextEdits that can be applied to the (original!) document.

    If using ASTRewrite inside your visitor is not an option, you could even try using ASTRewrite in "recording" mode, see org.eclipse.jdt.core.dom.CompilationUnit.recordModifications().