Use records instead of Immutables for plain value types - #98
Merged
Merged
Conversation
FormatterCliArgs and FormatterNativeImageArgs only gathered the arguments of a formatter process and turned them into its command line; Immutables generated a builder for each. They are records now, built through their constructors, and jvmArgsForVersion does what the builder's withJvmArgsForVersion did. open-java-format-jdk-bootstrap no longer runs the Immutables processor. FormatterServicesTest, which runs both services against a JDK and the native image, passes with -PnativeImage=true.
Six of the types Immutables generated in open-java-format were plain values: State's BreakState, LevelState and TokState, Level's SplitsBreaks, OpsBuilder's OpsOutput and InputMetadata. They are records now. The call sites use their constructors instead of builders and of(...) factories, and the accessors keep their names. InputMetadata keeps @immutable, which Error Prone now checks against the record's components instead of skipping a generated class. That needed BlankLineWanted to say it is immutable as well, and it is: its two subclasses hold an Optional<Boolean> and an ImmutableList<BreakTag>. OpenOp, Break and State stay on Immutables. OpenOp and Break extend HasUniqueId, whose per-instance id orders the formatter's persistent collections, and a record cannot extend a class. State copies itself through its builder in a dozen places. The 15,747 files of the JDK 21 sources format exactly as before.
This was referenced Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows #97: it builds on that PR's conventions.
Immutables generated eleven types. This turns the eight that are plain values into records and leaves the three that cannot be records as they stand.
What changes
FormatterCliArgsandFormatterNativeImageArgs, the arguments of a formatter process, are records built through their constructors. The module no longer runs the Immutables processor.State'sBreakState,LevelStateandTokState,Level'sSplitsBreaks,OpsBuilder'sOpsOutputandInputMetadataare records. The call sites use constructors instead of builders andof(...); the accessors keep their names.What stays on Immutables
OpenOpandBreakextendHasUniqueId, whose per-instance id orders the formatter's persistent collections, and a record cannot extend a class. They need theDochierarchy reworked first.Statecopies itself through its builder in about a dozen places. As a record each copy would list all ten components, or it would need a hand-written builder. It is created in the layout's hot loop, so that change wants a JMH measurement of its own.Worth a look
InputMetadatakeeps@Immutable, which Error Prone now checks against the record's components; before, the generated class was excluded from analysis. That needed@ImmutableonOpsBuilder.BlankLineWantedas well. Its two subclasses hold only anOptional<Boolean>and anImmutableList<BreakTag>, and Error Prone verifies them.Checked
diff -rqof the trees formatted by theallJarof Replace palantir's Gradle plugins with plain Gradle #97's head, whichmainnow holds, and of this branch../gradlew test: 1597 tests in:open-java-formatand 10 in the IDEA plugin. With-PnativeImage=true, 60 in the Gradle plugin and 8 in jdk-bootstrap, whoseFormatterServicesTestruns both changed services against a JDK and the native image.formatDiffthrough the released plugin.