Skip to content

Commit 1d451a5

Browse files
authored
Merge pull request #266 from mkurz/plugin-reorder-modifiers-cli
Support `reorderModifiers = false` via google-java-format CLI
2 parents 44800ad + 54eca52 commit 1d451a5

12 files changed

Lines changed: 59 additions & 41 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ jobs:
6565
- name: Build and test (sbt 2.x, Java 21)
6666
if: ${{ matrix.jobtype == 3 }}
6767
shell: bash
68-
run: sbt -v '++ 3.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted sbt-java-formatter/*' 'scripted java-runtime/compatible-21'
68+
run: sbt -v '++ 3.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted sbt-java-formatter/*' 'scripted java-runtime/compatible-21' 'scripted java-runtime/reorder-modifiers'
6969
- name: Build and test (sbt 2.x, Java 25)
7070
if: ${{ matrix.jobtype == 4 }}
7171
shell: bash
72-
run: sbt -v '++ 3.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted java-runtime/compatible-21'
72+
run: sbt -v '++ 3.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted java-runtime/compatible-21' 'scripted java-runtime/reorder-modifiers'
7373
- name: Build and test (sbt 1.x, Java 11 with formatter on Java 25)
7474
if: ${{ matrix.jobtype == 5 }}
7575
shell: bash
@@ -78,4 +78,4 @@ jobs:
7878
SBT_JAVAFMT_JAVA_HOME: ${{ env.JAVA_HOME_25_X64 }}
7979
run: |
8080
export PATH="${JAVA_HOME}/bin:$PATH"
81-
sbt -v '++ 2.12.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted java-runtime/compatible-21'
81+
sbt -v '++ 2.12.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted java-runtime/compatible-21' 'scripted java-runtime/reorder-modifiers'

README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ For available versions see [releases](https://github.com/sbt/sbt-java-formatter/
3838
* The `javafmtRemoveUnusedImports` setting controls whether unused imports are removed (`true` by default).
3939
* The `javafmtReflowLongStrings` setting controls whether long string literals are reflowed (`true` by default).
4040
* The `javafmtFormatJavadoc` setting controls whether Javadoc comments are reformatted (`true` by default).
41+
* The `javafmtReorderModifiers` setting controls whether modifiers are reordered into JLS order (`true` by default). Disabling it requires `javafmtFormatterCompatibleJavaVersion := 21`.
4142
* The `javafmtFormatterCompatibleJavaVersion` setting selects which `google-java-format` runtime line to use (`21` by default).
4243
* The `javafmtJavaMaxHeap` setting controls the maximum heap passed to the forked `google-java-format` JVM (`Some("256m")` by default).
4344

@@ -85,10 +86,11 @@ SBT_JAVAFMT_JAVA_HOME=/path/to/jdk-17 sbt javafmt
8586
> [!NOTE]
8687
> Many projects use Java 17 as their baseline today. If that is true for your build, `ThisBuild / javafmtFormatterCompatibleJavaVersion := 17` is often the simplest setup.
8788
>
88-
> The main Java language support changes in `google-java-format` [after `v1.28.0`](https://github.com/google/google-java-format/compare/v1.28.0...v1.35.0) are:
89+
> The main Java language support changes in `google-java-format` [after `v1.28.0`](https://github.com/google/google-java-format/compare/v1.28.0...v1.36.0) are:
8990
>
9091
> - [Initial support for import module in google-java-format](https://github.com/google/google-java-format/commit/6afe380707ec16884ec2761763ccec998de403d1)
9192
> - [Support Instance Main Methods in google-java-format](https://github.com/google/google-java-format/commit/737b0032b3a18eb6e458271ea440098c166f6c2d)
93+
> - [Initial support for Markdown documentation comments (`///`)](https://github.com/google/google-java-format/commit/53e2a763436abf00268f25ab59e481ca1d99cd29)
9294
>
9395
> If you do not use these language features, setting `ThisBuild / javafmtFormatterCompatibleJavaVersion := 17` lets sbt-java-formatter work out of the box on CI servers and developer machines that run sbt on Java 17.
9496
@@ -114,6 +116,7 @@ ThisBuild / javafmtSortImports := true
114116
ThisBuild / javafmtRemoveUnusedImports := true
115117
ThisBuild / javafmtReflowLongStrings := true
116118
ThisBuild / javafmtFormatJavadoc := true
119+
ThisBuild / javafmtReorderModifiers := true
117120
```
118121

119122
Set any of them to `false` to pass the corresponding `--skip-...` flag to `google-java-format`.
@@ -122,18 +125,14 @@ Set any of them to `false` to pass the corresponding `--skip-...` flag to `googl
122125

123126
- `11` -> `google-java-format 1.24.0`
124127
- `17` -> `google-java-format 1.28.0`
125-
- `21` -> `google-java-format 1.35.0` (default)
128+
- `21` -> `google-java-format 1.36.0` (default)
126129

127130
If the selected formatter runtime is newer than the Java used to launch the formatter JVM, either:
128131

129132
- lower `ThisBuild / javafmtFormatterCompatibleJavaVersion`
130133
- or point the formatter to a newer JDK via `SBT_JAVAFMT_JAVA_HOME` or `-Dsbt-javafmt.java.home=...`
131134

132-
`javafmtOptions` is still available for compatibility, but the preferred sbt-facing configuration is through the dedicated `javafmt...` settings above.
133-
134-
`JavaFormatterOptions.reorderModifiers()` currently has no effect in this plugin.
135-
136-
The plugin now runs `google-java-format` via its CLI in a forked JVM, and the released `google-java-format` CLI used here [does not yet support a corresponding `--skip-reordering-modifiers` flag](https://github.com/google/google-java-format/pull/1373).
135+
`javafmtOptions` is still available for compatibility with upstream `JavaFormatterOptions`, but the preferred sbt-facing configuration is through the dedicated `javafmt...` settings above.
137136

138137
If you want to tweak the format, take a minute to consider whether it is really worth it, and have a look at the motivations in the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html).
139138
If you decide you really need more flexibility, you could consider other plugins such as the [sbt-checkstyle-plugin](https://github.com/etsy/sbt-checkstyle-plugin)

plugin/src/main/scala/com/github/sbt/JavaFormatterPlugin.scala

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,10 @@ object JavaFormatterPlugin extends AutoPlugin {
8282
settingKey[Boolean]("Whether google-java-format should reflow long string literals. Enabled by default.")
8383
val javafmtFormatJavadoc =
8484
settingKey[Boolean]("Whether google-java-format should format Javadoc comments. Enabled by default.")
85+
val javafmtReorderModifiers =
86+
settingKey[Boolean]("Whether google-java-format should reorder modifiers into JLS order. Enabled by default.")
8587
val javafmtOptions = settingKey[JavaFormatterOptions](
86-
"Compatibility setting for upstream JavaFormatterOptions. Prefer the dedicated javafmt... settings; reorderModifiers() currently has no effect with the released google-java-format CLI used by this plugin.")
88+
"Compatibility setting for upstream JavaFormatterOptions. Prefer the dedicated javafmt... settings where available.")
8789
}
8890

8991
import autoImport._
@@ -121,7 +123,8 @@ object JavaFormatterPlugin extends AutoPlugin {
121123
javafmtSortImports := true,
122124
javafmtRemoveUnusedImports := true,
123125
javafmtReflowLongStrings := true,
124-
javafmtFormatJavadoc := true)
126+
javafmtFormatJavadoc := true,
127+
javafmtReorderModifiers := true)
125128

126129
def toBeScopedSettings: Seq[Setting[?]] =
127130
List(
@@ -130,6 +133,7 @@ object JavaFormatterPlugin extends AutoPlugin {
130133
.builder()
131134
.style(javafmtStyle.value)
132135
.formatJavadoc(javafmtFormatJavadoc.value)
136+
.reorderModifiers(javafmtReorderModifiers.value)
133137
.build(),
134138
javafmt := {
135139
val streamz = streams.value
@@ -139,7 +143,8 @@ object JavaFormatterPlugin extends AutoPlugin {
139143
val iF = (javafmt / includeFilter).value
140144
val eF = (javafmt / excludeFilter).value
141145
val cache = streamz.cacheStoreFactory
142-
val options = javafmtOptions.value
146+
val options =
147+
validateOptions(javafmtOptions.value, javafmtFormatterCompatibleJavaVersion.value)
143148
val formatterClasspath = javafmtFormatterClasspath.value.toVector
144149
val javaMaxHeap = javafmtJavaMaxHeap.value
145150
val sortImports = javafmtSortImports.value
@@ -169,7 +174,8 @@ object JavaFormatterPlugin extends AutoPlugin {
169174
val iF = (javafmt / includeFilter).value
170175
val eF = (javafmt / excludeFilter).value
171176
val cache = (javafmt / streams).value.cacheStoreFactory
172-
val options = javafmtOptions.value
177+
val options =
178+
validateOptions(javafmtOptions.value, javafmtFormatterCompatibleJavaVersion.value)
173179
val formatterClasspath = javafmtFormatterClasspath.value.toVector
174180
val javaMaxHeap = javafmtJavaMaxHeap.value
175181
val sortImports = javafmtSortImports.value
@@ -199,7 +205,8 @@ object JavaFormatterPlugin extends AutoPlugin {
199205
val iF = (javafmt / includeFilter).value
200206
val eF = (javafmt / excludeFilter).value
201207
val cache = streamz.cacheStoreFactory
202-
val options = javafmtOptions.value
208+
val options =
209+
validateOptions(javafmtOptions.value, javafmtFormatterCompatibleJavaVersion.value)
203210
val formatterClasspath = javafmtFormatterClasspath.value.toVector
204211
val javaMaxHeap = javafmtJavaMaxHeap.value
205212
val sortImports = javafmtSortImports.value
@@ -229,7 +236,8 @@ object JavaFormatterPlugin extends AutoPlugin {
229236
val iF = (javafmt / includeFilter).value
230237
val eF = (javafmt / excludeFilter).value
231238
val cache = (javafmt / streams).value.cacheStoreFactory
232-
val options = javafmtOptions.value
239+
val options =
240+
validateOptions(javafmtOptions.value, javafmtFormatterCompatibleJavaVersion.value)
233241
val formatterClasspath = javafmtFormatterClasspath.value.toVector
234242
val javaMaxHeap = javafmtJavaMaxHeap.value
235243
val sortImports = javafmtSortImports.value
@@ -279,12 +287,23 @@ object JavaFormatterPlugin extends AutoPlugin {
279287
compatibleJavaVersion match {
280288
case 11 => "1.24.0"
281289
case 17 => "1.28.0"
282-
case 21 => "1.35.0"
290+
case 21 => "1.36.0"
283291
case other =>
284292
throw new MessageOnlyException(
285293
s"Unsupported javafmtFormatterCompatibleJavaVersion: $other. Expected one of: 11, 17, 21.")
286294
}
287295

296+
private def validateOptions(options: JavaFormatterOptions, compatibleJavaVersion: Int): JavaFormatterOptions = {
297+
if (!options.reorderModifiers() && compatibleJavaVersion != 21) {
298+
throw new MessageOnlyException(
299+
"Disabling modifier reordering requires " +
300+
"ThisBuild / javafmtFormatterCompatibleJavaVersion := 21 " +
301+
"because the Java 11 and Java 17 formatter runtime lines do not support " +
302+
"--skip-reordering-modifiers.")
303+
}
304+
options
305+
}
306+
288307
@transient
289308
private val javafmtDoFormatOnCompile =
290309
taskKey[Unit]("Format Java source files if javafmtOnCompile is on.")

plugin/src/main/scala/com/github/sbt/javaformatter/JavaFormatter.scala

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -363,17 +363,15 @@ object JavaFormatter {
363363
sortImports: Boolean,
364364
removeUnusedImports: Boolean,
365365
reflowLongStrings: Boolean): Seq[String] = {
366-
if (!options.reorderModifiers()) {
367-
throw new MessageOnlyException(
368-
"The forked google-java-format CLI does not support reorderModifiers = false. " +
369-
"Please use the default reorderModifiers setting.")
370-
}
371366
val styleFlags =
372367
if (options.style() == JavaFormatterOptions.Style.AOSP) Seq("--aosp")
373368
else Nil
374369
val javadocFlags =
375370
if (options.formatJavadoc()) Nil
376371
else Seq("--skip-javadoc-formatting")
372+
val reorderModifiersFlags =
373+
if (options.reorderModifiers()) Nil
374+
else Seq("--skip-reordering-modifiers")
377375
val fixImportsOnlyFlags =
378376
if (fixImportsOnly) Seq("--fix-imports-only")
379377
else Nil
@@ -386,7 +384,7 @@ object JavaFormatter {
386384
val reflowLongStringsFlags =
387385
if (reflowLongStrings) Nil
388386
else Seq("--skip-reflowing-long-strings")
389-
styleFlags ++ javadocFlags ++ fixImportsOnlyFlags ++ sortImportsFlags ++ removeUnusedImportsFlags ++ reflowLongStringsFlags
387+
styleFlags ++ javadocFlags ++ reorderModifiersFlags ++ fixImportsOnlyFlags ++ sortImportsFlags ++ removeUnusedImportsFlags ++ reflowLongStringsFlags
390388
}
391389

392390
private case class CliResult(exitCode: Int, stdout: Vector[String], stderr: Vector[String])
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ThisBuild / javafmtFormatterCompatibleJavaVersion := 21
2+
ThisBuild / javafmtReorderModifiers := false

plugin/src/sbt-test/sbt-java-formatter/reorder-modifiers-unsupported/project/plugins.sbt renamed to plugin/src/sbt-test/java-runtime/reorder-modifiers/project/plugins.sbt

File renamed without changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.lightbend;
2+
3+
final public class BadFormatting {
4+
static public void main(String[] args) {}
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.lightbend;
2+
3+
final public class BadFormatting{
4+
static public void main(String[] args) {}
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-> javafmtCheck
2+
> javafmt
3+
> javafmtCheck
4+
5+
$ exec diff src/main/java/com/lightbend/BadFormatting.java src/main/java-expected/com/lightbend/BadFormatting.java
6+
7+
> set ThisBuild / javafmtFormatterCompatibleJavaVersion := 17
8+
-> javafmtCheck

plugin/src/sbt-test/sbt-java-formatter/reorder-modifiers-unsupported/build.sbt

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)