Skip to content

Add a Maven plugin with format and check goals #26

Description

@abashev

Why

Maven users have no way to run open-java-format from their build today.

Proposal

A plugin dev.openjavaformat:open-java-format-maven-plugin, released together with the formatter and under the same version, with two goals modelled on spotify/fmt-maven-plugin:

Goal Default phase What it does
format process-sources Formats the Java files in place
check verify Fails the build and lists the files that are not formatted
<plugin>
  <groupId>dev.openjavaformat</groupId>
  <artifactId>open-java-format-maven-plugin</artifactId>
  <version><!-- the formatter version --></version>
  <executions>
    <execution>
      <goals>
        <goal>check</goal>
      </goals>
    </execution>
  </executions>
</plugin>

From the command line the prefix gives mvn open-java-format:format and mvn open-java-format:check.

As few settings as possible, in line with a formatter that has none: the source roots, which default to the module's compile and test source roots, includes and excludes, and skip. The style is always OJF.

How the formatter runs

The formatter needs javac's internal packages exported. Running it inside the Maven JVM would make every project add the five --add-exports flags to .mvn/jvm.config, which is what Cosium/git-code-format-maven-plugin asks its users to do. Two ways avoid that:

  • Fork one JVM per module. Start the current JDK with the flags and the formatter's classpath, and hand all files of the module to com.palantir.javaformat.java.Main in a single call through an @argfile: --replace for format, --dry-run --set-exit-if-changed for check. BootstrappingFormatterService in open-java-format-jdk-bootstrap already builds this command line, although it starts one process per file. spotify/fmt-maven-plugin forks by default for the same reason, see its forkMode.
  • The native binary from open-java-format-native, as the Gradle plugin does with openjavaformat.native.formatter, on Linux with glibc and on macOS.

The formatter comes from the plugin's own dependencies, so it needs nothing from the project's repositories. That is the principle of #20 for the Gradle plugin.

Building it here

The repository builds with Gradle, and a Maven plugin needs a plugin descriptor. org.gradlex.maven-plugin-development generates it from the mojo annotations; the alternative is a small Maven build for this one module. Publishing goes through the existing JReleaser conventions together with the other jars.

Done when

  • the plugin is on Maven Central under the formatter's version;
  • an integration test runs real mvn on a sample multi-module project against the locally published plugin, for both goals, on Java 21 and without .mvn/jvm.config;
  • the output of format is byte-identical to the command line with --ojf;
  • the website gets a Maven page under Get started, and the Maven parts of the Spotless and Migrate pages point to it.

Related

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 request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions