From 8d9b327853953afa9bda120dfb24afbee2c40545 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Fri, 30 Oct 2026 14:14:34 +0100 Subject: [PATCH 1/3] Bump google-java-format to 2.0.0 and add a cleanup option google-java-format 2.0.0 adds a cleanup pass that makes small non-whitespace changes, and enables it by default: removing redundant semicolons, empty annotation parentheses, and parentheses around a single untyped lambda parameter. Add a `cleanup` option to the googleJavaFormat step in the Gradle and Maven plugins to disable it. Older google-java-format versions don't have cleanups, so `cleanup(false)` has no effect with them. 2.0.0 also indents text block contents as part of the main formatting pass, even when long strings aren't reflowed, so update the expected output of the text block test. https://github.com/google/google-java-format/releases/tag/v2.0.0 --- CHANGES.md | 4 ++ gradle/libs.versions.toml | 2 +- .../java/GoogleJavaFormatFormatterFunc.java | 25 ++++++++++++- .../spotless/java/GoogleJavaFormatStep.java | 37 ++++++++++++++----- plugin-gradle/CHANGES.md | 4 ++ plugin-gradle/README.md | 3 +- .../gradle/spotless/JavaExtension.java | 11 +++++- plugin-maven/CHANGES.md | 4 ++ plugin-maven/README.md | 1 + .../spotless/maven/java/GoogleJavaFormat.java | 8 +++- .../java/googlejavaformat/TextBlock.clean | 6 +-- .../java/GoogleJavaFormatStepTest.java | 15 ++++++++ 12 files changed, 101 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9929ccf7a6..a5304717ea 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,10 @@ This document is intended for Spotless developers. We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Added +- Add a `cleanup` option to `GoogleJavaFormatStep` to disable google-java-format's non-whitespace cleanups. +### Changes +- Bump default `google-java-format` version `1.36.1` -> `2.0.0`. ## [4.10.4] - 2026-10-08 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index acb1161c04..840d24c3e1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -52,7 +52,7 @@ flexmark-all = "com.vladsch.flexmark:flexmark-all:0.64.8" freshmark = "com.diffplug.freshmark:freshmark:1.3.1" cucumber-gherkin = "io.cucumber:gherkin:42.0.1" gherkin-utils = "io.cucumber:gherkin-utils:12.0.2" -google-java-format = "com.google.googlejavaformat:google-java-format:1.36.1" +google-java-format = "com.google.googlejavaformat:google-java-format:2.0.0" gson = "com.google.code.gson:gson:2.14.0" json-simple = "org.json:json:20210307" ktfmt = "org.jetbrains.kotlinx:ktfmt:0.65" diff --git a/lib/src/googleJavaFormat/java/com/diffplug/spotless/glue/java/GoogleJavaFormatFormatterFunc.java b/lib/src/googleJavaFormat/java/com/diffplug/spotless/glue/java/GoogleJavaFormatFormatterFunc.java index d13f8d9d40..d07800fbc8 100644 --- a/lib/src/googleJavaFormat/java/com/diffplug/spotless/glue/java/GoogleJavaFormatFormatterFunc.java +++ b/lib/src/googleJavaFormat/java/com/diffplug/spotless/glue/java/GoogleJavaFormatFormatterFunc.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 DiffPlug + * Copyright 2023-2026 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.diffplug.spotless.glue.java; +import java.lang.reflect.Method; import java.util.Objects; import javax.annotation.Nonnull; @@ -46,7 +47,7 @@ public class GoogleJavaFormatFormatterFunc implements FormatterFunc { private final boolean reorderImports; - public GoogleJavaFormatFormatterFunc(@Nonnull String version, @Nonnull String style, boolean reflowStrings, boolean reorderImports, boolean formatJavadoc) { + public GoogleJavaFormatFormatterFunc(@Nonnull String version, @Nonnull String style, boolean reflowStrings, boolean reorderImports, boolean formatJavadoc, boolean cleanup) { this.version = Objects.requireNonNull(version); this.formatterStyle = Style.valueOf(Objects.requireNonNull(style)); this.reflowStrings = reflowStrings; @@ -56,9 +57,29 @@ public GoogleJavaFormatFormatterFunc(@Nonnull String version, @Nonnull String st if (!formatJavadoc) { builder = builder.formatJavadoc(false); } + if (!cleanup) { + builder = disableCleanup(builder); + } this.formatter = new Formatter(builder.build()); } + // JavaFormatterOptions.Builder.cleanup(boolean) was added in google-java-format 2.0.0, and this + // glue is compiled against an older version. + private static JavaFormatterOptions.Builder disableCleanup(JavaFormatterOptions.Builder builder) { + Method cleanup; + try { + cleanup = JavaFormatterOptions.Builder.class.getMethod("cleanup", boolean.class); + } catch (NoSuchMethodException e) { + // google-java-format versions before 2.0.0 don't have cleanups + return builder; + } + try { + return (JavaFormatterOptions.Builder) cleanup.invoke(builder, false); + } catch (ReflectiveOperationException e) { + throw new IllegalStateException(e); + } + } + @Override @Nonnull public String apply(@Nonnull String input) throws Exception { diff --git a/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java b/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java index 079955a731..13b6dde628 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java @@ -34,6 +34,7 @@ public final class GoogleJavaFormatStep implements Serializable { private static final boolean DEFAULT_REFLOW_LONG_STRINGS = false; private static final boolean DEFAULT_REORDER_IMPORTS = false; private static final boolean DEFAULT_FORMAT_JAVADOC = true; + private static final boolean DEFAULT_CLEANUP = true; private static final String NAME = "google-java-format"; private static final String MAVEN_COORDINATE = "com.google.googlejavaformat:google-java-format"; @@ -44,19 +45,22 @@ public final class GoogleJavaFormatStep implements Serializable { private final boolean reflowLongStrings; private final boolean reorderImports; private final boolean formatJavadoc; + private final boolean cleanup; private GoogleJavaFormatStep(JarState.Promised jarState, String version, String style, boolean reflowLongStrings, boolean reorderImports, - boolean formatJavadoc) { + boolean formatJavadoc, + boolean cleanup) { this.jarState = jarState; this.version = version; this.style = style; this.reflowLongStrings = reflowLongStrings; this.reorderImports = reorderImports; this.formatJavadoc = formatJavadoc; + this.cleanup = cleanup; } /** Creates a step which formats everything - code, import order, and unused imports. */ @@ -89,14 +93,22 @@ public static FormatterStep create(String groupArtifact, String version, String /** Creates a step which formats everything - groupArtifact, code, import order, and unused imports - and optionally reflows long strings. */ public static FormatterStep create(String groupArtifact, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc) { - return createInternally(NAME, groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc, false); + return create(groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc, DEFAULT_CLEANUP); + } + + /** + * Creates a step which formats everything - groupArtifact, code, import order, and unused imports - and optionally reflows long strings. + * If {@code cleanup} is false, google-java-format 2.0.0 and later skip their non-whitespace cleanups (older versions don't have any). + */ + public static FormatterStep create(String groupArtifact, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc, boolean cleanup) { + return createInternally(NAME, groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc, cleanup, false); } static FormatterStep createRemoveUnusedImportsOnly(Provisioner provisioner) { - return createInternally(RemoveUnusedImportsStep.NAME, MAVEN_COORDINATE, defaultVersion(), defaultStyle(), provisioner, defaultReflowLongStrings(), defaultReorderImports(), defaultFormatJavadoc(), true); + return createInternally(RemoveUnusedImportsStep.NAME, MAVEN_COORDINATE, defaultVersion(), defaultStyle(), provisioner, defaultReflowLongStrings(), defaultReorderImports(), defaultFormatJavadoc(), defaultCleanup(), true); } - private static FormatterStep createInternally(String name, String groupArtifact, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc, boolean removeImports) { + private static FormatterStep createInternally(String name, String groupArtifact, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc, boolean cleanup, boolean removeImports) { Objects.requireNonNull(groupArtifact, "groupArtifact"); if (groupArtifact.chars().filter(ch -> ch == ':').count() != 1) { throw new IllegalArgumentException("groupArtifact must be in the form 'groupId:artifactId'"); @@ -105,7 +117,7 @@ private static FormatterStep createInternally(String name, String groupArtifact, Objects.requireNonNull(style, "style"); Objects.requireNonNull(provisioner, "provisioner"); - GoogleJavaFormatStep step = new GoogleJavaFormatStep(JarState.promise(() -> JarState.from(groupArtifact + ":" + version, provisioner)), version, style, reflowLongStrings, reorderImports, formatJavadoc); + GoogleJavaFormatStep step = new GoogleJavaFormatStep(JarState.promise(() -> JarState.from(groupArtifact + ":" + version, provisioner)), version, style, reflowLongStrings, reorderImports, formatJavadoc, cleanup); if (removeImports) { return FormatterStep.create(name, step, @@ -150,8 +162,12 @@ public static boolean defaultFormatJavadoc() { return DEFAULT_FORMAT_JAVADOC; } + public static boolean defaultCleanup() { + return DEFAULT_CLEANUP; + } + private State equalityState() { - return new State(version, style, jarState.get(), reflowLongStrings, reorderImports, formatJavadoc); + return new State(version, style, jarState.get(), reflowLongStrings, reorderImports, formatJavadoc, cleanup); } private static final class State implements Serializable { @@ -164,13 +180,15 @@ private static final class State implements Serializable { private final boolean reflowLongStrings; private final boolean reorderImports; private final boolean formatJavadoc; + private final boolean cleanup; State(String version, String style, JarState jarState, boolean reflowLongStrings, boolean reorderImports, - boolean formatJavadoc) { + boolean formatJavadoc, + boolean cleanup) { JVM_SUPPORT.assertFormatterSupported(version); ModuleHelper.doOpenInternalPackagesIfRequired(); this.jarState = jarState; @@ -179,13 +197,14 @@ private static final class State implements Serializable { this.reflowLongStrings = reflowLongStrings; this.reorderImports = reorderImports; this.formatJavadoc = formatJavadoc; + this.cleanup = cleanup; } FormatterFunc createFormat() throws Exception { final ClassLoader classLoader = jarState.getClassLoader(); Class formatterFunc = classLoader.loadClass("com.diffplug.spotless.glue.java.GoogleJavaFormatFormatterFunc"); - Constructor constructor = formatterFunc.getConstructor(String.class, String.class, boolean.class, boolean.class, boolean.class); - FormatterFunc googleJavaFormatFormatterFunc = (FormatterFunc) constructor.newInstance(version, style, reflowLongStrings, reorderImports, formatJavadoc); + Constructor constructor = formatterFunc.getConstructor(String.class, String.class, boolean.class, boolean.class, boolean.class, boolean.class); + FormatterFunc googleJavaFormatFormatterFunc = (FormatterFunc) constructor.newInstance(version, style, reflowLongStrings, reorderImports, formatJavadoc, cleanup); return JVM_SUPPORT.suggestLaterVersionOnError(version, googleJavaFormatFormatterFunc); } diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index d3249bf262..16dc7e5e39 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -3,6 +3,10 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`). ## [Unreleased] +### Added +- Add `cleanup(false)` to `googleJavaFormat()` to disable google-java-format's non-whitespace cleanups. +### Changes +- Bump default `google-java-format` version `1.36.1` -> `2.0.0`. This version applies some small non-whitespace cleanups by default (removing redundant semicolons, empty annotation parentheses, and parentheses around single lambda parameters), which can be disabled with `cleanup(false)`. ## [8.10.4] - 2026-10-08 diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index f6e9570853..023f78fb2a 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -380,8 +380,9 @@ spotless { googleJavaFormat() // optional: you can specify a specific version (>= 1.8) and/or switch to AOSP style // and/or reflow long strings + // and/or disable non-whitespace cleanups (google-java-format >= 2.0.0) // and/or use custom group artifact (you probably don't need this) - googleJavaFormat('1.8').aosp().reflowLongStrings().formatJavadoc(false).reorderImports(false).groupArtifact('com.google.googlejavaformat:google-java-format') + googleJavaFormat('1.8').aosp().reflowLongStrings().formatJavadoc(false).reorderImports(false).cleanup(false).groupArtifact('com.google.googlejavaformat:google-java-format') ``` ### palantir-java-format diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java index 9411811322..33d9dbac3a 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java @@ -211,6 +211,7 @@ public class GoogleJavaFormatConfig { boolean reflowLongStrings; boolean reorderImports; boolean formatJavadoc = true; + boolean cleanup = true; GoogleJavaFormatConfig(String version) { this.version = Objects.requireNonNull(version); @@ -261,6 +262,13 @@ public GoogleJavaFormatConfig formatJavadoc(boolean formatJavadoc) { return this; } + /** Enables or disables google-java-format's non-whitespace cleanups (google-java-format 2.0.0 and later), which are enabled by default. */ + public GoogleJavaFormatConfig cleanup(boolean cleanup) { + this.cleanup = cleanup; + replaceStep(createStep()); + return this; + } + private FormatterStep createStep() { return GoogleJavaFormatStep.create( groupArtifact, @@ -269,7 +277,8 @@ private FormatterStep createStep() { provisioner(), reflowLongStrings, reorderImports, - formatJavadoc); + formatJavadoc, + cleanup); } } diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 46c259e6e9..459722bc9b 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -3,6 +3,10 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Added +- Add `false` to `` to disable google-java-format's non-whitespace cleanups. +### Changes +- Bump default `google-java-format` version `1.36.1` -> `2.0.0`. This version applies some small non-whitespace cleanups by default (removing redundant semicolons, empty annotation parentheses, and parentheses around single lambda parameters), which can be disabled with `false`. ## [3.10.4] - 2026-10-08 diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 5c57f5eca9..ea7c4c72cf 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -345,6 +345,7 @@ Types in `java.lang` and in the file's own package are shortened without adding true false false. + false com.google.googlejavaformat:google-java-format diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/GoogleJavaFormat.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/GoogleJavaFormat.java index d0a2b24954..e86393f529 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/GoogleJavaFormat.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/GoogleJavaFormat.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2026 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,9 @@ public class GoogleJavaFormat implements FormatterStepFactory { @Parameter private Boolean formatJavadoc; + @Parameter + private Boolean cleanup; + @Override public FormatterStep newFormatterStep(FormatterStepConfig config) { String groupArtifact = this.groupArtifact != null ? this.groupArtifact : GoogleJavaFormatStep.defaultGroupArtifact(); @@ -49,6 +52,7 @@ public FormatterStep newFormatterStep(FormatterStepConfig config) { boolean reflowLongStrings = this.reflowLongStrings != null ? this.reflowLongStrings : GoogleJavaFormatStep.defaultReflowLongStrings(); boolean reorderImports = this.reorderImports != null ? this.reorderImports : GoogleJavaFormatStep.defaultReorderImports(); boolean formatJavadoc = this.formatJavadoc != null ? this.formatJavadoc : GoogleJavaFormatStep.defaultFormatJavadoc(); - return GoogleJavaFormatStep.create(groupArtifact, version, style, config.getProvisioner(), reflowLongStrings, reorderImports, formatJavadoc); + boolean cleanup = this.cleanup != null ? this.cleanup : GoogleJavaFormatStep.defaultCleanup(); + return GoogleJavaFormatStep.create(groupArtifact, version, style, config.getProvisioner(), reflowLongStrings, reorderImports, formatJavadoc, cleanup); } } diff --git a/testlib/src/main/resources/java/googlejavaformat/TextBlock.clean b/testlib/src/main/resources/java/googlejavaformat/TextBlock.clean index bd558ffd96..cf0dc428e0 100644 --- a/testlib/src/main/resources/java/googlejavaformat/TextBlock.clean +++ b/testlib/src/main/resources/java/googlejavaformat/TextBlock.clean @@ -5,9 +5,9 @@ public class Java { public static void main(String[] args) { var a = """ - Howdy - Partner! - """; + Howdy + Partner! + """; System.out.println(a); UsedB.someMethod(); UsedA.someMethod(); diff --git a/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java index cae19f4bca..22a5c82282 100644 --- a/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java @@ -117,6 +117,21 @@ void behaviorWithSkipFormatJavadoc() throws Exception { } } + @Test + void behaviorWithCleanup() throws Exception { + String unformatted = "class T {\n @Deprecated() void f() { g((x) -> x);; }\n}\n"; + try (StepHarness step = StepHarness.forStep(createWithCleanup(true))) { + step.test(unformatted, "class T {\n @Deprecated\n void f() {\n g(x -> x);\n }\n}\n"); + } + try (StepHarness step = StepHarness.forStep(createWithCleanup(false))) { + step.test(unformatted, "class T {\n @Deprecated()\n void f() {\n g((x) -> x);\n ;\n }\n}\n"); + } + } + + private static FormatterStep createWithCleanup(boolean cleanup) { + return GoogleJavaFormatStep.create(GoogleJavaFormatStep.defaultGroupArtifact(), GoogleJavaFormatStep.defaultVersion(), GoogleJavaFormatStep.defaultStyle(), TestProvisioner.mavenCentral(), GoogleJavaFormatStep.defaultReflowLongStrings(), GoogleJavaFormatStep.defaultReorderImports(), GoogleJavaFormatStep.defaultFormatJavadoc(), cleanup); + } + @Test void behaviorWithCustomGroupArtifact() throws Exception { FormatterStep step = GoogleJavaFormatStep.create(GoogleJavaFormatStep.defaultGroupArtifact(), GoogleJavaFormatStep.defaultVersion(), GoogleJavaFormatStep.defaultStyle(), TestProvisioner.mavenCentral(), false); From e6eab79386b218b61f8c99f669f6235abe39e6eb Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Sat, 31 Oct 2026 00:37:24 +0100 Subject: [PATCH 2/3] Apply batched suggestions from code review Co-authored-by: Zongle Wang --- CHANGES.md | 4 ++-- plugin-gradle/CHANGES.md | 5 +++-- plugin-maven/CHANGES.md | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a5304717ea..76f7a0e6f7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,9 +11,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added -- Add a `cleanup` option to `GoogleJavaFormatStep` to disable google-java-format's non-whitespace cleanups. +- Add a `cleanup` option to `GoogleJavaFormatStep` to disable google-java-format's non-whitespace cleanups. ([#3157](https://github.com/diffplug/spotless/pull/3157)) ### Changes -- Bump default `google-java-format` version `1.36.1` -> `2.0.0`. +- Bump default `google-java-format` version `1.36.1` -> `2.0.0`. ([#3157](https://github.com/diffplug/spotless/pull/3157)) ## [4.10.4] - 2026-10-08 diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 16dc7e5e39..ea9fa8cd41 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -4,9 +4,10 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added -- Add `cleanup(false)` to `googleJavaFormat()` to disable google-java-format's non-whitespace cleanups. +- Add `cleanup(false)` to `googleJavaFormat()` to disable google-java-format's non-whitespace cleanups. ([#3157](https://github.com/diffplug/spotless/pull/3157)) ### Changes -- Bump default `google-java-format` version `1.36.1` -> `2.0.0`. This version applies some small non-whitespace cleanups by default (removing redundant semicolons, empty annotation parentheses, and parentheses around single lambda parameters), which can be disabled with `cleanup(false)`. +- Bump default `google-java-format` version `1.36.1` -> `2.0.0`. ([#3157](https://github.com/diffplug/spotless/pull/3157)) + This version applies some small non-whitespace cleanups by default (removing redundant semicolons, empty annotation parentheses, and parentheses around single lambda parameters), which can be disabled with `cleanup(false)`. ## [8.10.4] - 2026-10-08 diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 459722bc9b..59b4ceadbf 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -4,9 +4,10 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added -- Add `false` to `` to disable google-java-format's non-whitespace cleanups. +- Add `false` to `` to disable google-java-format's non-whitespace cleanups. ([#3157](https://github.com/diffplug/spotless/pull/3157)) ### Changes -- Bump default `google-java-format` version `1.36.1` -> `2.0.0`. This version applies some small non-whitespace cleanups by default (removing redundant semicolons, empty annotation parentheses, and parentheses around single lambda parameters), which can be disabled with `false`. +- Bump default `google-java-format` version `1.36.1` -> `2.0.0`. ([#3157](https://github.com/diffplug/spotless/pull/3157)) + This version applies some small non-whitespace cleanups by default (removing redundant semicolons, empty annotation parentheses, and parentheses around single lambda parameters), which can be disabled with `false`. ## [3.10.4] - 2026-10-08 From e8f21cb256c728365435aef71495ad7d6bd91e2a Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Sat, 31 Oct 2026 10:07:13 +0100 Subject: [PATCH 3/3] Handle older google-java-format versions in GoogleJavaFormatStepTest On Java 17 the default google-java-format version is 1.28.0, which doesn't have cleanups and doesn't indent text block contents without reflowing long strings. --- .../java/googlejavaformat/TextBlock.clean | 6 +++--- .../java/googlejavaformat/TextBlockGjf2.clean | 15 +++++++++++++++ .../spotless/java/GoogleJavaFormatStepTest.java | 15 ++++++++++++--- 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 testlib/src/main/resources/java/googlejavaformat/TextBlockGjf2.clean diff --git a/testlib/src/main/resources/java/googlejavaformat/TextBlock.clean b/testlib/src/main/resources/java/googlejavaformat/TextBlock.clean index cf0dc428e0..bd558ffd96 100644 --- a/testlib/src/main/resources/java/googlejavaformat/TextBlock.clean +++ b/testlib/src/main/resources/java/googlejavaformat/TextBlock.clean @@ -5,9 +5,9 @@ public class Java { public static void main(String[] args) { var a = """ - Howdy - Partner! - """; + Howdy + Partner! + """; System.out.println(a); UsedB.someMethod(); UsedA.someMethod(); diff --git a/testlib/src/main/resources/java/googlejavaformat/TextBlockGjf2.clean b/testlib/src/main/resources/java/googlejavaformat/TextBlockGjf2.clean new file mode 100644 index 0000000000..cf0dc428e0 --- /dev/null +++ b/testlib/src/main/resources/java/googlejavaformat/TextBlockGjf2.clean @@ -0,0 +1,15 @@ +import mylib.UsedA; +import mylib.UsedB; + +public class Java { + public static void main(String[] args) { + var a = + """ + Howdy + Partner! + """; + System.out.println(a); + UsedB.someMethod(); + UsedA.someMethod(); + } +} diff --git a/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java index 22a5c82282..5d42ea0d4b 100644 --- a/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java @@ -34,7 +34,8 @@ class GoogleJavaFormatStepTest extends ResourceHarness { @Test void jvm13Features() throws Exception { try (StepHarness step = StepHarness.forStep(GoogleJavaFormatStep.create(TestProvisioner.mavenCentral()))) { - step.testResource("java/googlejavaformat/TextBlock.dirty", "java/googlejavaformat/TextBlock.clean"); + // google-java-format 2.0.0 indents text block contents even when long strings aren't reflowed + step.testResource("java/googlejavaformat/TextBlock.dirty", defaultVersionIsAtLeast2() ? "java/googlejavaformat/TextBlockGjf2.clean" : "java/googlejavaformat/TextBlock.clean"); } } @@ -120,14 +121,22 @@ void behaviorWithSkipFormatJavadoc() throws Exception { @Test void behaviorWithCleanup() throws Exception { String unformatted = "class T {\n @Deprecated() void f() { g((x) -> x);; }\n}\n"; + String withoutCleanups = "class T {\n @Deprecated()\n void f() {\n g((x) -> x);\n ;\n }\n}\n"; + // google-java-format versions before 2.0.0 don't have cleanups + String withCleanups = defaultVersionIsAtLeast2() ? "class T {\n @Deprecated\n void f() {\n g(x -> x);\n }\n}\n" : withoutCleanups; try (StepHarness step = StepHarness.forStep(createWithCleanup(true))) { - step.test(unformatted, "class T {\n @Deprecated\n void f() {\n g(x -> x);\n }\n}\n"); + step.test(unformatted, withCleanups); } try (StepHarness step = StepHarness.forStep(createWithCleanup(false))) { - step.test(unformatted, "class T {\n @Deprecated()\n void f() {\n g((x) -> x);\n ;\n }\n}\n"); + step.test(unformatted, withoutCleanups); } } + /** The default version depends on the JVM, e.g. google-java-format 2.0.0 requires Java 21. */ + private static boolean defaultVersionIsAtLeast2() { + return !GoogleJavaFormatStep.defaultVersion().startsWith("1."); + } + private static FormatterStep createWithCleanup(boolean cleanup) { return GoogleJavaFormatStep.create(GoogleJavaFormatStep.defaultGroupArtifact(), GoogleJavaFormatStep.defaultVersion(), GoogleJavaFormatStep.defaultStyle(), TestProvisioner.mavenCentral(), GoogleJavaFormatStep.defaultReflowLongStrings(), GoogleJavaFormatStep.defaultReorderImports(), GoogleJavaFormatStep.defaultFormatJavadoc(), cleanup); }