Skip to content

Support external Eclipse formatter profile via compiler argument #278

Description

@AndreasIgel

Summary

Currently, the Eclipse JDT formatter profile is bundled as a classpath resource (eclipse-java-format.xml) and cannot be customized by users. This ticket proposes adding a compiler argument -Asimplebuilder.formatterProfile that allows users to specify an external Eclipse formatter profile XML file, enabling project-specific code formatting conventions for generated builder source files.

Motivation

  • Project-specific formatting: Teams have their own formatting conventions (indentation size, brace placement, line wrapping, etc.). Currently, generated builders use the bundled profile, which may not match the consuming project's style.
  • Consistency with hand-written code: Generated builders should visually match the surrounding hand-written code in the project.
  • No workaround today: The only way to change formatting is to fork the processor and replace the bundled eclipse-java-format.xml, which is not maintainable.

Proposed API

Compiler argument

-Asimplebuilder.formatterProfile=<path>
  • <path> can be:
    • An absolute or relative file system path (e.g., config/eclipse-formatter.xml, /home/user/profiles/custom.xml)
    • A classpath resource path (e.g., eclipse-java-format.xml) — this is the current default behavior
  • Default: eclipse-java-format.xml (bundled resource, current behavior)
  • Empty/unset: Falls back to the bundled default

Resolution logic

  1. If -Asimplebuilder.formatterProfile is set:
    • Try to resolve as a file system path first (relative to the current working directory or absolute)
    • If the file does not exist, try to resolve as a classpath resource
    • If neither works, log a warning and fall back to the bundled default
  2. If not set, use the bundled eclipse-java-format.xml (current behavior)

Example usage

# Maven
mvn compile -Dsimplebuilder.formatterProfile=src/main/config/eclipse-formatter.xml

# Gradle
compileJava {
    options.compilerArgs += ['-Asimplebuilder.formatterProfile=config/formatter.xml']
}

Implementation outline

1. New CompilerArgumentsEnum constant

Add to CompilerArgumentsEnum:

/** Option for external Eclipse formatter profile XML file path. */
FORMATTER_PROFILE("formatterProfile"),

2. Read the argument in ProcessingContext

In ProcessingContext constructor (or a new method on CompilerArgumentsReader):

String formatterProfilePath = argReader.readValue(CompilerArgumentsEnum.FORMATTER_PROFILE);

Pass this path through to RoasterSourceFormatter (or RoasterCodeGenerator) alongside the FormattingMode.

3. Update RoasterSourceFormatter to resolve the profile

Currently RoasterSourceFormatter loads the profile from the classpath via getResourceAsStream(). Extend loadFormatterProperties() to:

  1. If an external path is provided, try to load it as a file first (new FileInputStream(path))
  2. If the file doesn't exist, try the classpath with the given path
  3. If both fail, fall back to the bundled default (DEFAULT_FORMATTER_PROFILE_RESOURCE)
  4. Log appropriate warnings at each fallback step

The formatterProfileResource field (already injectable for testing) would carry the resolved path.

4. Thread the parameter through the pipeline

  • ProcessingContext → stores formatterProfilePath (like formattingMode)
  • RoasterCodeGenerator → passes it to RoasterSourceFormatter constructor
  • RoasterSourceFormatter → uses it in loadFormatterProperties()

5. Documentation

Update CONFIGURATION.md with a new section:

### Formatter Profile

| Option | Compiler argument | Default | Description |
|--------|-------------------|---------|-------------|
| `formatterProfile` | `-Asimplebuilder.formatterProfile` | `eclipse-java-format.xml` (bundled) | Path to an external Eclipse formatter profile XML file. Can be a file system path or classpath resource. |

6. Tests

  • File system path: Create a temp file with a custom profile, pass its path, verify generated code uses the custom formatting (e.g., different indentation size)
  • Classpath resource: Pass a custom classpath resource name, verify it's loaded
  • Fallback to bundled default: Pass a non-existent path, verify warning is logged and bundled profile is used
  • No argument: Verify current behavior is unchanged
  • Per-annotation override (future): Consider adding formatterProfile to @SimpleBuilder.Options for per-builder customization (similar to formattingMode)

Scope

  • In scope: Compiler argument -Asimplebuilder.formatterProfile for global configuration
  • Future consideration: Per-annotation @SimpleBuilder.Options(formatterProfile = "...") override (same priority resolution as formattingMode)
  • Out of scope: Support for multiple formatter profiles per generated class, non-Eclipse formatter formats

Affected files

File Change
CompilerArgumentsEnum.java Add FORMATTER_PROFILE constant
CompilerArgumentsReader.java Add readFormatterProfile() method
ProcessingContext.java Read and store formatterProfilePath
RoasterCodeGenerator.java Pass formatterProfilePath to RoasterSourceFormatter
RoasterSourceFormatter.java Extend loadFormatterProperties() to resolve file system paths
CONFIGURATION.md Document the new option
RoasterSourceFormatterTest.java Add tests for external profile loading

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestfuture-ideaLonger-term idea, not scheduled work

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions