7

I am generating some classes with JDT. Afterwards I would like to format the whole ICompilationUnit, just as if I pressed Ctrl+Shift+F (Source > Format) in an open Editor without a selection.

Any pointers for the API in JDT to format the source code programmatically is highly appreciated.

Addition: I tried it like this, but the code isn't changed. What am I mssing?

private void formatUnitSourceCode(ICompilationUnit targetUnit, IProgressMonitor monitor) throws JavaModelException {
    CodeFormatter formatter = ToolFactory.createCodeFormatter(null);
    TextEdit formatEdit = formatter.format(CodeFormatter.K_COMPILATION_UNIT, targetUnit.getSource(), 0, targetUnit.getSource().length(), 0, null);
    targetUnit.applyTextEdit(formatEdit, monitor);
}

3 Answers 3

6

This could be a bug, but using the JDK in Elcipse 4.2.2, it is necessary to create a working copy of the ICompilationUnit in order to apply a TextEdit to the file.

    targetUnit.becomeWorkingCopy(new SubProgressMonitor(monitor, 1));
    ... do work on the source file ...
    formatUnitSourceCode(targetUnit, new SubProgressMonitor(monitor, 1));
    targetUnit.commitWorkingCopy(true, new SubProgressMonitor(monitor, 1));

The formatting itself is done like this:

public static void formatUnitSourceCode(ICompilationUnit unit, IProgressMonitor monitor) throws JavaModelException {
    CodeFormatter formatter = ToolFactory.createCodeFormatter(null);
    ISourceRange range = unit.getSourceRange();
    TextEdit formatEdit = formatter.format(CodeFormatter.K_COMPILATION_UNIT, unit.getSource(), range.getOffset(), range.getLength(), 0, null);
    if (formatEdit != null && formatEdit.hasChildren()) {
        unit.applyTextEdit(formatEdit, monitor);
    } else {
        monitor.done();
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

+1 One minor point: SubProgressMonitor is now deprecated. Something like SubMonitor.convert(monitor) should be used instead.
2

When generating some classes by using JDT, you can put "\t"s in your source code. Or like what you did, using code formatter. I have tested the following code:

public static void main(String[] args)
{
    String code = "public class TestFormatter{public static void main(String[] args){System.out.println(\"Hello World\");}}";
    CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(null);

    TextEdit textEdit = codeFormatter.format(CodeFormatter.K_UNKNOWN, code, 0,code.length(),0,null);
    IDocument doc = new Document(code);
    try {
        textEdit.apply(doc);
        System.out.println(doc.get());
    } catch (MalformedTreeException e) {
        e.printStackTrace();
    } catch (BadLocationException e) {
        e.printStackTrace();
    }   
}

The apply() method does the trick here.

4 Comments

This helps, but it doens't elegantly solve all of the wanted formatting. I. e. you would need to manualy break long method declarations with lots of parameters.
Very interesting problem. I see what you are doing, and I just edited my answer. Thanks.
Hi Ryan, I changed my code above to use CodeFormatter.K_UNKNOWN, but that didn't work either. Afterwards I checked targetUnit.getSource() after the call to targetUnit.applyTextEdit (which does the apply() on the internal IDocument of the ICompilationUnit), and strangely the changes seem to be applied. But they are not applied to the file. Is this a bug, or am I missing something?
I found the solution: I seems to be necessary to create a workingCopy of the ICompilationUnit to be able to apply the edits to the file.
0

I use the following method to format a Java Source file

    public static void formatSource(ICompilationUnit cu, IProgressMonitor progressMonitor) throws JavaModelException{
    String source = cu.getSource();
    IJavaProject javaProject = cu.getJavaProject();

    Map options = javaProject.getOptions(true);


            // Instantiate the default code formatter with the given options
            final CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(options);


            final TextEdit edit = codeFormatter.format(
                CodeFormatter.K_COMPILATION_UNIT, // format a compilation unit
                source, // source to format
                0, // starting position
                source.length(), // length
                0, // initial indentation
                System.getProperty("line.separator") // line separator
            );          

            cu.becomeWorkingCopy(progressMonitor);
            try {
                cu.applyTextEdit(edit, progressMonitor);
                //cu.reconcile();
                cu.commitWorkingCopy(true, progressMonitor);
                //cu.save(progressMonitor, false);

                JavaUI.openInEditor(cu);


            } catch (MalformedTreeException e) {
                e.printStackTrace();
            } catch (PartInitException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }   

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.