Skip to content

Commit c18d8e8

Browse files
authored
Merge pull request #272 from mkurz/formatter-all-deps-runtime
Select formatter runtimes explicitly and add Java compatibility coverage
2 parents f98dd76 + c313f69 commit c18d8e8

45 files changed

Lines changed: 361 additions & 27 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@ jobs:
1919
java: 17
2020
distribution: zulu
2121
jobtype: 2
22+
- os: ubuntu-latest
23+
java: 21
24+
distribution: zulu
25+
jobtype: 3
26+
- os: ubuntu-latest
27+
java: 25
28+
distribution: zulu
29+
jobtype: 4
30+
- os: ubuntu-latest
31+
java: 11
32+
distribution: zulu
33+
jobtype: 5
2234
runs-on: ${{ matrix.os }}
2335
env:
2436
# define Java options for both official sbt and sbt-extras
@@ -35,12 +47,35 @@ jobs:
3547
distribution: "${{ matrix.distribution }}"
3648
java-version: "${{ matrix.java }}"
3749
cache: sbt
50+
- name: Setup formatter JDK
51+
if: ${{ matrix.jobtype == 5 }}
52+
uses: actions/setup-java@v5
53+
with:
54+
distribution: zulu
55+
java-version: "25"
3856
- uses: sbt/setup-sbt@v1
3957
- name: Build and test (sbt 1.x)
4058
if: ${{ matrix.jobtype == 1 }}
4159
shell: bash
42-
run: sbt -v '++ 2.12.x' clean scalafmtSbtCheck scalafmtCheckAll test scripted
60+
run: sbt -v '++ 2.12.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted sbt-java-formatter/*' 'scripted java-runtime/compatible-11'
4361
- name: Build and test (sbt 2.x)
4462
if: ${{ matrix.jobtype == 2 }}
4563
shell: bash
46-
run: sbt -v '++ 3.x' clean scalafmtSbtCheck scalafmtCheckAll test scripted
64+
run: sbt -v '++ 3.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted sbt-java-formatter/*' 'scripted java-runtime/compatible-17' 'scripted java-runtime/incompatible-21-on-java-17'
65+
- name: Build and test (sbt 2.x, Java 21)
66+
if: ${{ matrix.jobtype == 3 }}
67+
shell: bash
68+
run: sbt -v '++ 3.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted sbt-java-formatter/*' 'scripted java-runtime/compatible-21'
69+
- name: Build and test (sbt 2.x, Java 25)
70+
if: ${{ matrix.jobtype == 4 }}
71+
shell: bash
72+
run: sbt -v '++ 3.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted java-runtime/compatible-21'
73+
- name: Build and test (sbt 1.x, Java 11 with formatter on Java 25)
74+
if: ${{ matrix.jobtype == 5 }}
75+
shell: bash
76+
env:
77+
JAVA_HOME: ${{ env.JAVA_HOME_11_X64 }}
78+
SBT_JAVAFMT_JAVA_HOME: ${{ env.JAVA_HOME_25_X64 }}
79+
run: |
80+
export PATH="${JAVA_HOME}/bin:$PATH"
81+
sbt -v '++ 2.12.x' clean scalafmtSbtCheck scalafmtCheckAll test 'scripted java-runtime/compatible-21'

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ For available versions see [releases](https://github.com/sbt/sbt-java-formatter/
3737
* The `javafmtRemoveUnusedImports` setting controls whether unused imports are removed (`true` by default).
3838
* The `javafmtReflowLongStrings` setting controls whether long string literals are reflowed (`true` by default).
3939
* The `javafmtFormatJavadoc` setting controls whether Javadoc comments are reformatted (`true` by default).
40+
* The `javafmtFormatterCompatibleJavaVersion` setting selects which `google-java-format` runtime line to use (`21` by default).
4041
* The `javafmtJavaMaxHeap` setting controls the maximum heap passed to the forked `google-java-format` JVM (`Some("256m")` by default).
4142

4243
This plugin requires sbt 1.3.0+.
@@ -66,6 +67,20 @@ To make the plugin launch the formatter with a different Java installation, set
6667

6768
If both are set, `sbt-javafmt.java.home` takes precedence.
6869

70+
The selected Java home must still be compatible with the `google-java-format` runtime line chosen by `javafmtFormatterCompatibleJavaVersion`.
71+
72+
This is useful if your build runs sbt on one JDK but needs to launch the formatter on another one. For example, you can keep sbt on Java 11 and still run the formatter on a newer JDK by setting `SBT_JAVAFMT_JAVA_HOME` or `-Dsbt-javafmt.java.home=...`.
73+
74+
For example:
75+
76+
```scala
77+
ThisBuild / javafmtFormatterCompatibleJavaVersion := 21
78+
```
79+
80+
```bash
81+
SBT_JAVAFMT_JAVA_HOME=/path/to/jdk-21 sbt javafmt
82+
```
83+
6984
Use `javafmtJavaMaxHeap` to control the maximum heap size passed to that JVM:
7085

7186
```scala
@@ -83,6 +98,7 @@ ThisBuild / javafmtJavaMaxHeap := None
8398
The plugin also exposes a few `google-java-format` CLI options directly:
8499

85100
```scala
101+
ThisBuild / javafmtFormatterCompatibleJavaVersion := 21
86102
ThisBuild / javafmtSortImports := true
87103
ThisBuild / javafmtRemoveUnusedImports := true
88104
ThisBuild / javafmtReflowLongStrings := true
@@ -91,6 +107,17 @@ ThisBuild / javafmtFormatJavadoc := true
91107

92108
Set any of them to `false` to pass the corresponding `--skip-...` flag to `google-java-format`.
93109

110+
`javafmtFormatterCompatibleJavaVersion` maps to these formatter versions:
111+
112+
- `11` -> `google-java-format 1.24.0`
113+
- `17` -> `google-java-format 1.28.0`
114+
- `21` -> `google-java-format 1.35.0`
115+
116+
If the selected formatter runtime is newer than the Java used to launch the formatter JVM, either:
117+
118+
- lower `ThisBuild / javafmtFormatterCompatibleJavaVersion`
119+
- or point the formatter to a newer JDK via `SBT_JAVAFMT_JAVA_HOME` or `-Dsbt-javafmt.java.home=...`
120+
94121
`javafmtOptions` is still available for compatibility, but the preferred sbt-facing configuration is through the dedicated `javafmt...` settings above.
95122

96123
`JavaFormatterOptions.reorderModifiers()` currently has no effect in this plugin.

build.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ lazy val plugin = project
1616
ScmInfo(url("https://github.com/sbt/sbt-java-formatter"), "scm:git:git@github.com:sbt/sbt-java-formatter.git")),
1717
developers := List(
1818
Developer("ktoso", "Konrad 'ktoso' Malawski", "<ktoso@project13.pl>", url("https://github.com/ktoso"))),
19+
// Compile the plugin against the Java 11-compatible google-java-format API line; actual formatter execution uses a separately selected forked runtime.
1920
libraryDependencies ++= Seq("com.google.googlejavaformat" % "google-java-format" % "1.24.0"),
2021
startYear := Some(2015),
2122
description := "Formats Java code in your project.",

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ object AutomateJavaFormatterPlugin extends AutoPlugin {
3232

3333
object JavaFormatterPlugin extends AutoPlugin {
3434

35+
private val JavafmtRuntime = config("javafmtRuntime").hide.extend(Runtime)
36+
37+
@transient
38+
private val javafmtFormatterClasspath =
39+
taskKey[Seq[File]]("Resolved classpath for the forked google-java-format CLI.")
40+
3541
object autoImport {
3642
@transient
3743
val javafmt: TaskKey[Unit] = taskKey("Format Java sources")
@@ -58,6 +64,9 @@ object JavaFormatterPlugin extends AutoPlugin {
5864
"Execute the javafmtFixImportsCheck task for all configurations in which it is enabled. " +
5965
"(By default this means the Compile and Test configurations.)")
6066
val javafmtOnCompile = settingKey[Boolean]("Format Java source files on compile, off by default.")
67+
val javafmtFormatterCompatibleJavaVersion =
68+
settingKey[Int](
69+
"Selects the google-java-format runtime line by compatible Java version. Supported values: 11, 17, 21.")
6170
val javafmtStyle =
6271
settingKey[JavaFormatterOptions.Style]("Define formatting style, Google Java Style (default) or AOSP")
6372
val javafmtJavaMaxHeap =
@@ -103,6 +112,7 @@ object JavaFormatterPlugin extends AutoPlugin {
103112
override def globalSettings: Seq[Def.Setting[?]] =
104113
Seq(
105114
javafmtOnCompile := false,
115+
javafmtFormatterCompatibleJavaVersion := 21,
106116
javafmtStyle := JavaFormatterOptions.Style.GOOGLE,
107117
javafmtJavaMaxHeap := Some("256m"),
108118
javafmtSortImports := true,
@@ -125,6 +135,7 @@ object JavaFormatterPlugin extends AutoPlugin {
125135
val eF = (javafmt / excludeFilter).value
126136
val cache = streamz.cacheStoreFactory
127137
val options = javafmtOptions.value
138+
val formatterClasspath = javafmtFormatterClasspath.value.toVector
128139
val javaMaxHeap = javafmtJavaMaxHeap.value
129140
val sortImports = javafmtSortImports.value
130141
val removeUnusedImports = javafmtRemoveUnusedImports.value
@@ -136,6 +147,7 @@ object JavaFormatterPlugin extends AutoPlugin {
136147
streamz,
137148
cache,
138149
options,
150+
formatterClasspath,
139151
javaMaxHeap,
140152
sortImports,
141153
removeUnusedImports,
@@ -149,6 +161,7 @@ object JavaFormatterPlugin extends AutoPlugin {
149161
val eF = (javafmt / excludeFilter).value
150162
val cache = (javafmt / streams).value.cacheStoreFactory
151163
val options = javafmtOptions.value
164+
val formatterClasspath = javafmtFormatterClasspath.value.toVector
152165
val javaMaxHeap = javafmtJavaMaxHeap.value
153166
val sortImports = javafmtSortImports.value
154167
val removeUnusedImports = javafmtRemoveUnusedImports.value
@@ -161,6 +174,7 @@ object JavaFormatterPlugin extends AutoPlugin {
161174
streamz,
162175
cache,
163176
options,
177+
formatterClasspath,
164178
javaMaxHeap,
165179
sortImports,
166180
removeUnusedImports,
@@ -173,6 +187,7 @@ object JavaFormatterPlugin extends AutoPlugin {
173187
val eF = (javafmt / excludeFilter).value
174188
val cache = streamz.cacheStoreFactory
175189
val options = javafmtOptions.value
190+
val formatterClasspath = javafmtFormatterClasspath.value.toVector
176191
val javaMaxHeap = javafmtJavaMaxHeap.value
177192
val sortImports = javafmtSortImports.value
178193
val removeUnusedImports = javafmtRemoveUnusedImports.value
@@ -184,6 +199,7 @@ object JavaFormatterPlugin extends AutoPlugin {
184199
streamz,
185200
cache,
186201
options,
202+
formatterClasspath,
187203
javaMaxHeap,
188204
sortImports,
189205
removeUnusedImports,
@@ -197,6 +213,7 @@ object JavaFormatterPlugin extends AutoPlugin {
197213
val eF = (javafmt / excludeFilter).value
198214
val cache = (javafmt / streams).value.cacheStoreFactory
199215
val options = javafmtOptions.value
216+
val formatterClasspath = javafmtFormatterClasspath.value.toVector
200217
val javaMaxHeap = javafmtJavaMaxHeap.value
201218
val sortImports = javafmtSortImports.value
202219
val removeUnusedImports = javafmtRemoveUnusedImports.value
@@ -209,6 +226,7 @@ object JavaFormatterPlugin extends AutoPlugin {
209226
streamz,
210227
cache,
211228
options,
229+
formatterClasspath,
212230
javaMaxHeap,
213231
sortImports,
214232
removeUnusedImports,
@@ -224,7 +242,28 @@ object JavaFormatterPlugin extends AutoPlugin {
224242
compile / compileInputs := (compile / compileInputs).dependsOn(javafmtDoFormatOnCompile).value)
225243

226244
def notToBeScopedSettings: Seq[Setting[?]] =
227-
List(javafmt / includeFilter := "*.java")
245+
List(
246+
ivyConfigurations += JavafmtRuntime,
247+
libraryDependencies +=
248+
("com.google.googlejavaformat" % "google-java-format" % formatterVersionForCompatibleJavaVersion(
249+
javafmtFormatterCompatibleJavaVersion.value) % JavafmtRuntime.name).classifier("all-deps").intransitive(),
250+
javafmtFormatterClasspath := update.value
251+
.matching(
252+
configurationFilter(JavafmtRuntime.name) && moduleFilter(
253+
organization = "com.google.googlejavaformat",
254+
name = "google-java-format"))
255+
.distinct,
256+
javafmt / includeFilter := "*.java")
257+
258+
private def formatterVersionForCompatibleJavaVersion(compatibleJavaVersion: Int): String =
259+
compatibleJavaVersion match {
260+
case 11 => "1.24.0"
261+
case 17 => "1.28.0"
262+
case 21 => "1.35.0"
263+
case other =>
264+
throw new MessageOnlyException(
265+
s"Unsupported javafmtFormatterCompatibleJavaVersion: $other. Expected one of: 11, 17, 21.")
266+
}
228267

229268
@transient
230269
private val javafmtDoFormatOnCompile =

0 commit comments

Comments
 (0)