Formatting Source Code programmatically with JDT
Asked Answered
C

3

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);
}
Conspecific answered 15/4, 2013 at 12:32 Comment(0)
C
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();
    }
}
Conspecific answered 16/4, 2013 at 9:26 Comment(1)
+1 One minor point: SubProgressMonitor is now deprecated. Something like SubMonitor.convert(monitor) should be used instead.Othaothe
P
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.

Pehlevi answered 15/4, 2013 at 12:43 Comment(4)
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.Conspecific
Very interesting problem. I see what you are doing, and I just edited my answer. Thanks.Pehlevi
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?Conspecific
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.Conspecific
O
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();
            }   

}
Outright answered 29/11, 2013 at 12:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.