diff --git a/CHANGES.md b/CHANGES.md index 76f7a0e6f7..dc5223bb34 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,8 @@ 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. ([#3157](https://github.com/diffplug/spotless/pull/3157)) +- Add a `maxLineLength` option to `GoogleJavaFormatStep`. ([#3151](https://github.com/diffplug/spotless/issues/3151)) + Overrides the 100-column limit prescribed by the GOOGLE and AOSP styles. Requires `google-java-format` `2.0.0` or later, the bug-fixing major release which stabilized the configurable `JavaFormatterOptions.Style` introduced experimentally in `1.37.0` (no `1.38.0` was ever published). ### Changes - Bump default `google-java-format` version `1.36.1` -> `2.0.0`. ([#3157](https://github.com/diffplug/spotless/pull/3157)) 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 d07800fbc8..859d728151 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 @@ -15,6 +15,7 @@ */ package com.diffplug.spotless.glue.java; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Objects; @@ -47,13 +48,17 @@ public class GoogleJavaFormatFormatterFunc implements FormatterFunc { private final boolean reorderImports; - public GoogleJavaFormatFormatterFunc(@Nonnull String version, @Nonnull String style, boolean reflowStrings, boolean reorderImports, boolean formatJavadoc, boolean cleanup) { + public GoogleJavaFormatFormatterFunc(@Nonnull String version, @Nonnull String style, boolean reflowStrings, boolean reorderImports, boolean formatJavadoc, boolean cleanup, int maxLineLength) { this.version = Objects.requireNonNull(version); this.formatterStyle = Style.valueOf(Objects.requireNonNull(style)); this.reflowStrings = reflowStrings; this.reorderImports = reorderImports; - JavaFormatterOptions.Builder builder = JavaFormatterOptions.builder().style(formatterStyle); + Style effectiveStyle = formatterStyle; + if (maxLineLength > 0) { + effectiveStyle = withMaxLineLength(formatterStyle, maxLineLength, version); + } + JavaFormatterOptions.Builder builder = JavaFormatterOptions.builder().style(effectiveStyle); if (!formatJavadoc) { builder = builder.formatJavadoc(false); } @@ -63,6 +68,33 @@ public GoogleJavaFormatFormatterFunc(@Nonnull String version, @Nonnull String st this.formatter = new Formatter(builder.build()); } + /** + * Sets the column limit on the style's builder. That builder was introduced experimentally in + * google-java-format 1.37.0 and stabilized in 2.0.0, the bug-fixing major release (no 1.38.0 + * was ever published, see google/google-java-format#1477), while this glue code is compiled + * against 1.28.0 so that it keeps working on older versions, hence the reflection + * (https://github.com/diffplug/spotless/issues/3151). + * Methods are looked up on the public {@code Style$Builder} type rather than on the runtime + * class of the builder, because the runtime class generated by AutoBuilder is package-private. + */ + @Nonnull + private static Style withMaxLineLength(@Nonnull Style style, int maxLineLength, @Nonnull String version) { + try { + Method createBuilder = Style.class.getMethod("builder"); + Class builderType = createBuilder.getReturnType(); + Object builder = createBuilder.invoke(null); + builder = builderType.getMethod(style == Style.AOSP ? "aosp" : "google").invoke(builder); + builder = builderType.getMethod("maxLineLength", int.class).invoke(builder, maxLineLength); + return (Style) builderType.getMethod("build").invoke(builder); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException( + "maxLineLength requires google-java-format 2.0.0 or later (you are using " + version + ")", e); + } catch (IllegalAccessException | InvocationTargetException e) { + Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e; + throw new IllegalArgumentException("Failed to apply maxLineLength " + maxLineLength, cause); + } + } + // 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) { 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 13b6dde628..5c4a4fe790 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java @@ -18,6 +18,7 @@ import java.io.Serial; import java.io.Serializable; import java.lang.reflect.Constructor; +import java.util.Arrays; import java.util.Objects; import com.diffplug.spotless.FormatterFunc; @@ -35,6 +36,16 @@ public final class GoogleJavaFormatStep implements Serializable { private static final boolean DEFAULT_REORDER_IMPORTS = false; private static final boolean DEFAULT_FORMAT_JAVADOC = true; private static final boolean DEFAULT_CLEANUP = true; + /** 0 means "not set", i.e. use whatever column limit the formatter's style prescribes. */ + private static final int DEFAULT_MAX_LINE_LENGTH = 0; + /** + * The minimum version for the {@code maxLineLength} option: google-java-format {@code 2.0.0}, + * the bug-fixing major release which stabilized the configurable {@code JavaFormatterOptions.Style} + * introduced experimentally in 1.37.0 (no 1.38.0 was ever published), see + * [google/google-java-format#1477](https://github.com/google/google-java-format/pull/1477) and + * [#3151](https://github.com/diffplug/spotless/issues/3151). + */ + static final String MIN_VERSION_FOR_MAX_LINE_LENGTH = "2.0.0"; private static final String NAME = "google-java-format"; private static final String MAVEN_COORDINATE = "com.google.googlejavaformat:google-java-format"; @@ -46,6 +57,7 @@ public final class GoogleJavaFormatStep implements Serializable { private final boolean reorderImports; private final boolean formatJavadoc; private final boolean cleanup; + private final int maxLineLength; private GoogleJavaFormatStep(JarState.Promised jarState, String version, @@ -53,7 +65,8 @@ private GoogleJavaFormatStep(JarState.Promised jarState, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc, - boolean cleanup) { + boolean cleanup, + int maxLineLength) { this.jarState = jarState; this.version = version; this.style = style; @@ -61,6 +74,7 @@ private GoogleJavaFormatStep(JarState.Promised jarState, this.reorderImports = reorderImports; this.formatJavadoc = formatJavadoc; this.cleanup = cleanup; + this.maxLineLength = maxLineLength; } /** Creates a step which formats everything - code, import order, and unused imports. */ @@ -93,7 +107,15 @@ 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 create(groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc, DEFAULT_CLEANUP); + return create(groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc, DEFAULT_CLEANUP, DEFAULT_MAX_LINE_LENGTH); + } + + /** + * Creates a step which formats everything - groupArtifact, code, import order, and unused imports - and optionally reflows long strings. + * A positive {@code maxLineLength} overrides the column limit prescribed by the style, and requires google-java-format {@code 2.0.0} or later. + */ + public static FormatterStep create(String groupArtifact, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc, int maxLineLength) { + return create(groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc, DEFAULT_CLEANUP, maxLineLength); } /** @@ -101,14 +123,23 @@ public static FormatterStep create(String groupArtifact, String version, String * 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); + return create(groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc, cleanup, DEFAULT_MAX_LINE_LENGTH); + } + + /** + * Creates a step which formats everything - groupArtifact, code, import order, and unused imports - and optionally reflows long strings. + * A positive {@code maxLineLength} overrides the column limit prescribed by the style, and requires google-java-format {@code 2.0.0} or later. + * 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, int maxLineLength) { + return createInternally(NAME, groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc, cleanup, maxLineLength, false); } static FormatterStep createRemoveUnusedImportsOnly(Provisioner provisioner) { - return createInternally(RemoveUnusedImportsStep.NAME, MAVEN_COORDINATE, defaultVersion(), defaultStyle(), provisioner, defaultReflowLongStrings(), defaultReorderImports(), defaultFormatJavadoc(), defaultCleanup(), true); + return createInternally(RemoveUnusedImportsStep.NAME, MAVEN_COORDINATE, defaultVersion(), defaultStyle(), provisioner, defaultReflowLongStrings(), defaultReorderImports(), defaultFormatJavadoc(), defaultCleanup(), DEFAULT_MAX_LINE_LENGTH, true); } - private static FormatterStep createInternally(String name, String groupArtifact, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc, boolean cleanup, boolean removeImports) { + private static FormatterStep createInternally(String name, String groupArtifact, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc, boolean cleanup, int maxLineLength, 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'"); @@ -116,8 +147,14 @@ private static FormatterStep createInternally(String name, String groupArtifact, Objects.requireNonNull(version, "version"); Objects.requireNonNull(style, "style"); Objects.requireNonNull(provisioner, "provisioner"); + if (maxLineLength < 0) { + throw new IllegalArgumentException("maxLineLength must be positive, but was: " + maxLineLength); + } + if (maxLineLength > 0 && compareVersions(version, MIN_VERSION_FOR_MAX_LINE_LENGTH) < 0) { + throw new IllegalArgumentException("maxLineLength requires google-java-format " + MIN_VERSION_FOR_MAX_LINE_LENGTH + " or later (you are using " + version + ")"); + } - GoogleJavaFormatStep step = new GoogleJavaFormatStep(JarState.promise(() -> JarState.from(groupArtifact + ":" + version, provisioner)), version, style, reflowLongStrings, reorderImports, formatJavadoc, cleanup); + GoogleJavaFormatStep step = new GoogleJavaFormatStep(JarState.promise(() -> JarState.from(groupArtifact + ":" + version, provisioner)), version, style, reflowLongStrings, reorderImports, formatJavadoc, cleanup, maxLineLength); if (removeImports) { return FormatterStep.create(name, step, @@ -166,8 +203,36 @@ public static boolean defaultCleanup() { return DEFAULT_CLEANUP; } + public static int defaultMaxLineLength() { + return DEFAULT_MAX_LINE_LENGTH; + } + + /** Compares dotted numeric versions, e.g. {@code compareVersions("1.36.1", "1.37.0") < 0}. */ + private static int compareVersions(String left, String right) { + int[] lhs = parseVersion(left); + int[] rhs = parseVersion(right); + int numberOfElements = Math.max(lhs.length, rhs.length); + lhs = Arrays.copyOf(lhs, numberOfElements); + rhs = Arrays.copyOf(rhs, numberOfElements); + for (int i = 0; i < numberOfElements; i++) { + if (lhs[i] != rhs[i]) { + return lhs[i] > rhs[i] ? 1 : -1; + } + } + return 0; + } + + private static int[] parseVersion(String version) { + try { + String withoutSuffix = version.endsWith("-SNAPSHOT") ? version.substring(0, version.length() - "-SNAPSHOT".length()) : version; + return Arrays.stream(withoutSuffix.split("\\.")).mapToInt(Integer::parseInt).toArray(); + } catch (Exception e) { + throw new IllegalArgumentException("Not a semantic version: " + version, e); + } + } + private State equalityState() { - return new State(version, style, jarState.get(), reflowLongStrings, reorderImports, formatJavadoc, cleanup); + return new State(version, style, jarState.get(), reflowLongStrings, reorderImports, formatJavadoc, cleanup, maxLineLength); } private static final class State implements Serializable { @@ -181,6 +246,7 @@ private static final class State implements Serializable { private final boolean reorderImports; private final boolean formatJavadoc; private final boolean cleanup; + private final int maxLineLength; State(String version, String style, @@ -188,7 +254,8 @@ private static final class State implements Serializable { boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc, - boolean cleanup) { + boolean cleanup, + int maxLineLength) { JVM_SUPPORT.assertFormatterSupported(version); ModuleHelper.doOpenInternalPackagesIfRequired(); this.jarState = jarState; @@ -198,13 +265,14 @@ private static final class State implements Serializable { this.reorderImports = reorderImports; this.formatJavadoc = formatJavadoc; this.cleanup = cleanup; + this.maxLineLength = maxLineLength; } 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, boolean.class); - FormatterFunc googleJavaFormatFormatterFunc = (FormatterFunc) constructor.newInstance(version, style, reflowLongStrings, reorderImports, formatJavadoc, cleanup); + Constructor constructor = formatterFunc.getConstructor(String.class, String.class, boolean.class, boolean.class, boolean.class, boolean.class, int.class); + FormatterFunc googleJavaFormatFormatterFunc = (FormatterFunc) constructor.newInstance(version, style, reflowLongStrings, reorderImports, formatJavadoc, cleanup, maxLineLength); return JVM_SUPPORT.suggestLaterVersionOnError(version, googleJavaFormatFormatterFunc); } diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index ea9fa8cd41..20b2ff2952 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -5,6 +5,8 @@ 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. ([#3157](https://github.com/diffplug/spotless/pull/3157)) +- Add `maxLineLength(int)` to `googleJavaFormat()`. ([#3151](https://github.com/diffplug/spotless/issues/3151)) + Overrides the 100-column limit prescribed by the GOOGLE and AOSP styles; requires `google-java-format` `2.0.0` or later. ### Changes - 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)`. diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 023f78fb2a..12c8b2e20e 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -380,9 +380,10 @@ spotless { googleJavaFormat() // optional: you can specify a specific version (>= 1.8) and/or switch to AOSP style // and/or reflow long strings + // and/or override the 100-column limit (requires google-java-format 2.0.0+) // 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).cleanup(false).groupArtifact('com.google.googlejavaformat:google-java-format') + googleJavaFormat('2.0.0').aosp().reflowLongStrings().maxLineLength(120).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 33d9dbac3a..f065c14f1b 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 @@ -212,6 +212,7 @@ public class GoogleJavaFormatConfig { boolean reorderImports; boolean formatJavadoc = true; boolean cleanup = true; + int maxLineLength = GoogleJavaFormatStep.defaultMaxLineLength(); GoogleJavaFormatConfig(String version) { this.version = Objects.requireNonNull(version); @@ -269,6 +270,16 @@ public GoogleJavaFormatConfig cleanup(boolean cleanup) { return this; } + /** + * Overrides the column limit prescribed by the style (100 for both GOOGLE and AOSP). + * Requires google-java-format 2.0.0 or later. + */ + public GoogleJavaFormatConfig maxLineLength(int maxLineLength) { + this.maxLineLength = maxLineLength; + replaceStep(createStep()); + return this; + } + private FormatterStep createStep() { return GoogleJavaFormatStep.create( groupArtifact, @@ -278,7 +289,8 @@ private FormatterStep createStep() { reflowLongStrings, reorderImports, formatJavadoc, - cleanup); + cleanup, + maxLineLength); } } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoogleJavaFormatIntegrationTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoogleJavaFormatIntegrationTest.java index dde872d3e5..c65023a746 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoogleJavaFormatIntegrationTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GoogleJavaFormatIntegrationTest.java @@ -15,6 +15,8 @@ */ package com.diffplug.gradle.spotless; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + import java.io.IOException; import org.junit.jupiter.api.Test; @@ -101,4 +103,28 @@ void integrationWithSkipJavadocFormatting() throws IOException { "googleJavaFormat()"); checkRunsThenUpToDate(); } + + @Test + void integrationWithMaxLineLength() throws IOException { + assumeTrue(Jvm.version() >= 21, "google-java-format 2.0.0 requires JVM 21+"); + + setFile("build.gradle").toLines( + "plugins {", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "", + "spotless {", + " java {", + " target file('test.java')", + " googleJavaFormat('2.0.0').maxLineLength(240)", + " }", + "}"); + + setFile("test.java").toResource("java/googlejavaformat/JavaCodeUnformatted.test"); + gradleRunner().withArguments("spotlessApply").build(); + assertFile("test.java").sameAsResource("java/googlejavaformat/JavaCodeFormattedMaxLineLength240.test"); + + checkRunsThenUpToDate(); + } } diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 59b4ceadbf..7f61370408 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -5,6 +5,8 @@ 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. ([#3157](https://github.com/diffplug/spotless/pull/3157)) +- Add a `` parameter to ``. ([#3151](https://github.com/diffplug/spotless/issues/3151)) + Overrides the 100-column limit prescribed by the GOOGLE and AOSP styles; requires `google-java-format` `2.0.0` or later. ### Changes - 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`. diff --git a/plugin-maven/README.md b/plugin-maven/README.md index ea7c4c72cf..5a1b9bc5d7 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -340,9 +340,10 @@ Types in `java.lang` and in the file's own package are shortened without adding ```xml - 1.8 + 2.0.0 true + 120 false false. false 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 e86393f529..3c1dab763e 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 @@ -44,6 +44,9 @@ public class GoogleJavaFormat implements FormatterStepFactory { @Parameter private Boolean cleanup; + @Parameter + private Integer maxLineLength; + @Override public FormatterStep newFormatterStep(FormatterStepConfig config) { String groupArtifact = this.groupArtifact != null ? this.groupArtifact : GoogleJavaFormatStep.defaultGroupArtifact(); @@ -53,6 +56,7 @@ public FormatterStep newFormatterStep(FormatterStepConfig config) { boolean reorderImports = this.reorderImports != null ? this.reorderImports : GoogleJavaFormatStep.defaultReorderImports(); boolean formatJavadoc = this.formatJavadoc != null ? this.formatJavadoc : GoogleJavaFormatStep.defaultFormatJavadoc(); boolean cleanup = this.cleanup != null ? this.cleanup : GoogleJavaFormatStep.defaultCleanup(); - return GoogleJavaFormatStep.create(groupArtifact, version, style, config.getProvisioner(), reflowLongStrings, reorderImports, formatJavadoc, cleanup); + int maxLineLength = this.maxLineLength != null ? this.maxLineLength : GoogleJavaFormatStep.defaultMaxLineLength(); + return GoogleJavaFormatStep.create(groupArtifact, version, style, config.getProvisioner(), reflowLongStrings, reorderImports, formatJavadoc, cleanup, maxLineLength); } } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/GoogleJavaFormatTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/GoogleJavaFormatTest.java index 0723d73c0e..6337a64da9 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/GoogleJavaFormatTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/GoogleJavaFormatTest.java @@ -15,8 +15,11 @@ */ package com.diffplug.spotless.maven.java; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + import org.junit.jupiter.api.Test; +import com.diffplug.spotless.Jvm; import com.diffplug.spotless.java.GoogleJavaFormatStep; import com.diffplug.spotless.maven.MavenIntegrationHarness; @@ -76,6 +79,19 @@ void specificVersionSkipJavadocFormatting() throws Exception { runTest("java/googlejavaformat/JavaCodeFormattedSkipJavadocFormatting.test"); } + @Test + void specificVersionMaxLineLength() throws Exception { + assumeTrue(Jvm.version() >= 21, "google-java-format 2.0.0 requires JVM 21+"); + + writePomWithJavaSteps( + "", + " 2.0.0", + " 240", + ""); + + runTest("java/googlejavaformat/JavaCodeFormattedMaxLineLength240.test"); + } + private void runTest(String targetResource) throws Exception { runTest(targetResource, "java/googlejavaformat/JavaCodeUnformatted.test"); } diff --git a/testlib/src/main/resources/java/googlejavaformat/JavaCodeFormattedMaxLineLength240.test b/testlib/src/main/resources/java/googlejavaformat/JavaCodeFormattedMaxLineLength240.test new file mode 100644 index 0000000000..2000494af2 --- /dev/null +++ b/testlib/src/main/resources/java/googlejavaformat/JavaCodeFormattedMaxLineLength240.test @@ -0,0 +1,11 @@ +import mylib.UsedA; +import mylib.UsedB; + +public class Java { + /** Some javadoc. */ + public static void main(String[] args) { + System.out.println("A very very very very very very very very very very very very very very very very very very very very very long string that goes beyond the 100-character line length."); + 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 5d42ea0d4b..fe2c536726 100644 --- a/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/java/GoogleJavaFormatStepTest.java @@ -15,6 +15,8 @@ */ package com.diffplug.spotless.java; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.condition.JRE.JAVA_20; import static org.junit.jupiter.api.condition.JRE.JAVA_21; import static org.junit.jupiter.api.condition.JRE.JAVA_25; @@ -164,6 +166,29 @@ void behaviorWithReorderImports() throws Exception { } } + @Test + @EnabledForJreRange(min = JAVA_21) + void behaviorWithMaxLineLength() throws Exception { + FormatterStep step = GoogleJavaFormatStep.create( + GoogleJavaFormatStep.defaultGroupArtifact(), + "2.0.0", + GoogleJavaFormatStep.defaultStyle(), + TestProvisioner.mavenCentral(), + GoogleJavaFormatStep.defaultReflowLongStrings(), + GoogleJavaFormatStep.defaultReorderImports(), + GoogleJavaFormatStep.defaultFormatJavadoc(), + 240); + StepHarness.forStep(step) + .testResource("java/googlejavaformat/JavaCodeUnformatted.test", "java/googlejavaformat/JavaCodeFormattedMaxLineLength240.test"); + } + + @Test + void maxLineLengthRequiresVersion2Dot0OrLater() { + IllegalArgumentException error = assertThrows(IllegalArgumentException.class, + () -> GoogleJavaFormatStep.create(GoogleJavaFormatStep.defaultGroupArtifact(), "1.38.0", GoogleJavaFormatStep.defaultStyle(), TestProvisioner.mavenCentral(), false, false, true, 120)); + assertTrue(error.getMessage().contains("maxLineLength requires google-java-format 2.0.0 or later"), error.getMessage()); + } + @Test @EnabledForJreRange(max = JAVA_20) void equality() throws Exception {