14 Replies Latest reply on Nov 7, 2014 2:49 AM by Daniel Cunha (soro)

    ROASTER: Using the formatter (feedback)

    Jeremie Bresson Newbie

      I have tried to use the Formatter with a custom format (modifications introduced with ROASTER-37):

       

      Formatter.format(Properties, JavaClassSource)

       

      Here some findings / information:

       

      1/ Obtain the Properties object

       

      When you export the Java Formatter format from Eclipse (see screenshot: export_eclipse_formatter_profile.png), you obtain an xml file. The settings contained in the file are correct (setting tag: id attribute & value attribute) but I think that the format is not suitable.

       

      Alternative is to check the /.settings/org.eclipse.jdt.core.prefs of your java project (if you have checked the “Enabled project specific settings” in the project preferences, the current formatter settings will also be stored there).

      I my opinion this file contains too much entries (non jdt-formatter stuff), but the format is suitable and it can be loaded into a java.util.Properties object.

       

      Here is how (based on google guava):

       

      //imports: com.google.common.io.Files, com.google.common.base.Charsets

      //propFile is a java.io.File

       

      BufferedReader inputStream = Files.newReader(propFile, Charsets.UTF_8);

      Properties prop = new Properties();

      1. prop.load(inputStream);

       

      If you want to do some cleanup, you can extract the lines from the org.eclipse.jdt.core.prefs file into a roaster_formatter.properties file. Basically you will need the lines starting with org.eclipse.jdt.core.formatter. The keys are defined in this Javadoc: DefaultCodeFormatterConstants.

       

       

      2/ Make the formatter working: set the version of the java source

       

      I noticed that my formatter was not working with all my JavaClassSource classes.

       

      After a long debug session, I found out why it was not working.

       

      A breakpoint in RecordedParsingInformation.updateRecordedParsingInformation(CompilationResult) shows that is some cases, compilationResult.problems is not null:

       

      Pb(596) Syntax error, annotations are only available if source level is 1.5 or greater

       

      The JDT cannot compile a file that cannot be parsed. It took me a while to understand how to set the source level. If you do nothing, the method DefaultCodeFormatter.getDefaultCompilerOptions() sets the version to "1.3". Here the corresponding code snippet:

       

      Object sourceOption = this.options.get(CompilerOptions.OPTION_Source);

      if (sourceOption != null) {

             this.defaultCompilerOptions.put(CompilerOptions.OPTION_Source, sourceOption);

      } else {

             this.defaultCompilerOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);

      }

       

      To set the version to another version (1.7 for example), just add the line in your properties file:

      org.jboss.forge.roaster._shade.org.eclipse.jdt.core.compiler.source=1.7

       

      I am not sure why this org.jboss..._shade prefix is necessary, but without this prefix, it is not working. This might be related with ROASTER-12.

       

       

      3/ Side-note: Formatter.format(Properties, JavaClassSource) calls the formatter twice.

       

      The current implementation of org.jboss.forge.roaster.model.util.Formatter.format(Properties, JavaClassSource) calls the JDT Formatter twice.

       

      The implementation looks like this:

         /**

          * Format the given {@link JavaClassSource}, using the given Eclipse code format {@link Properties}.

          */

         public static String format(Properties prefs, JavaClassSource javaClass)

         {

            return format(prefs, javaClass.toString());

         }

       

      A break point at the beginning of the private method: Formatter._format(String, CodeFormatter) shows why:

      - First call: because of the AbstractJavaSource#toString() implementation. The class gets formatted with the default settings.

      - Second call: the expected one.

       

      I hope this feedback is useful for other developers using roaster.