From 6d04f189735f9ddec4a62afa9380f7b81b7b65dc Mon Sep 17 00:00:00 2001 From: Goooler Date: Wed, 31 Jan 2024 22:39:23 +0800 Subject: [PATCH 01/13] Add RoundedStep --- .../extra/EclipseBasedStepBuilder.java | 3 ++- .../spotless/extra/EquoBasedStepBuilder.java | 3 ++- .../com/diffplug/spotless/RoundedStep.java | 20 +++++++++++++++++++ .../diffplug/spotless/generic/IndentStep.java | 5 ++--- .../diffplug/spotless/kotlin/DiktatStep.java | 2 +- 5 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 lib/src/main/java/com/diffplug/spotless/RoundedStep.java diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/EclipseBasedStepBuilder.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/EclipseBasedStepBuilder.java index 0dff3f6898..3e43e49d37 100644 --- a/lib-extra/src/main/java/com/diffplug/spotless/extra/EclipseBasedStepBuilder.java +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/EclipseBasedStepBuilder.java @@ -33,6 +33,7 @@ import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.RoundedStep; import com.diffplug.spotless.SerializedFunction; /** @@ -126,7 +127,7 @@ public void setPreferences(Iterable settingsFiles) { this.settingsFiles = settingsFiles; } - static class EclipseStep implements Serializable { + static class EclipseStep implements RoundedStep { private static final long serialVersionUID = 1; private final String semanticVersion; private final String formatterStepExt; diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/EquoBasedStepBuilder.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/EquoBasedStepBuilder.java index eaedfb55d3..e2b3661d9b 100644 --- a/lib-extra/src/main/java/com/diffplug/spotless/extra/EquoBasedStepBuilder.java +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/EquoBasedStepBuilder.java @@ -34,6 +34,7 @@ import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.RoundedStep; import com.diffplug.spotless.SerializedFunction; import dev.equo.solstice.NestedJars; @@ -149,7 +150,7 @@ private P2Model createModelWithMirrors() { return model; } - static class EquoStep implements Serializable { + static class EquoStep implements RoundedStep { private static final long serialVersionUID = 1; private final String semanticVersion; private final FileSignature.Promised settingsPromise; diff --git a/lib/src/main/java/com/diffplug/spotless/RoundedStep.java b/lib/src/main/java/com/diffplug/spotless/RoundedStep.java new file mode 100644 index 0000000000..8b346273c4 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/RoundedStep.java @@ -0,0 +1,20 @@ +/* + * Copyright 2024 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless; + +import java.io.Serializable; + +public interface RoundedStep extends Serializable {} diff --git a/lib/src/main/java/com/diffplug/spotless/generic/IndentStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IndentStep.java index 91155b1a79..1bd7454c14 100644 --- a/lib/src/main/java/com/diffplug/spotless/generic/IndentStep.java +++ b/lib/src/main/java/com/diffplug/spotless/generic/IndentStep.java @@ -15,14 +15,13 @@ */ package com.diffplug.spotless.generic; -import java.io.Serializable; - import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.RoundedStep; import com.diffplug.spotless.SerializedFunction; /** Simple step which checks for consistent indentation characters. */ -public final class IndentStep implements Serializable { +public final class IndentStep implements RoundedStep { private static final long serialVersionUID = 1L; final Type type; diff --git a/lib/src/main/java/com/diffplug/spotless/kotlin/DiktatStep.java b/lib/src/main/java/com/diffplug/spotless/kotlin/DiktatStep.java index 425786d64e..d1803b16a8 100644 --- a/lib/src/main/java/com/diffplug/spotless/kotlin/DiktatStep.java +++ b/lib/src/main/java/com/diffplug/spotless/kotlin/DiktatStep.java @@ -26,7 +26,7 @@ import com.diffplug.spotless.*; /** Wraps up diktat as a FormatterStep. */ -public class DiktatStep implements Serializable { +public class DiktatStep implements RoundedStep { private static final long serialVersionUID = 1L; private final JarState.Promised jarState; private final String versionDiktat; From 4e10fd47eed24c248e3036c2cc3d13f0f0b88f48 Mon Sep 17 00:00:00 2001 From: Goooler Date: Wed, 31 Jan 2024 22:21:22 +0800 Subject: [PATCH 02/13] Make KtLintStep round-trippable --- .../diffplug/spotless/kotlin/KtLintStep.java | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java b/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java index 6a5374bd68..f76e7763f4 100644 --- a/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java +++ b/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java @@ -15,7 +15,6 @@ */ package com.diffplug.spotless.kotlin; -import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Constructor; import java.util.Collections; @@ -33,17 +32,32 @@ import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.RoundedStep; /** Wraps up ktlint as a FormatterStep. */ -public class KtLintStep { - // prevent direct instantiation - private KtLintStep() {} - +public class KtLintStep implements RoundedStep { + private static final long serialVersionUID = 1L; private static final String DEFAULT_VERSION = "1.1.1"; private static final String NAME = "ktlint"; private static final String MAVEN_COORDINATE_0_DOT = "com.pinterest:ktlint:"; private static final String MAVEN_COORDINATE_1_DOT = "com.pinterest.ktlint:ktlint-cli:"; + private final JarState.Promised jarState; + @Nullable + private final FileSignature.Promised config; + private final Map editorConfigOverride; + private final String version; + + private KtLintStep(String version, + JarState.Promised jarState, + @Nullable FileSignature config, + Map editorConfigOverride) { + this.version = version; + this.jarState = jarState; + this.config = config != null ? config.asPromise() : null; + this.editorConfigOverride = editorConfigOverride; + } + public static FormatterStep create(Provisioner provisioner) { return create(defaultVersion(), provisioner); } @@ -59,8 +73,12 @@ public static FormatterStep create(String version, List customRuleSets) { Objects.requireNonNull(version, "version"); Objects.requireNonNull(provisioner, "provisioner"); - return FormatterStep.createLazy(NAME, - () -> new State(version, provisioner, editorConfig, editorConfigOverride, customRuleSets), + String ktlintCoordinate = (version.startsWith("0.") ? MAVEN_COORDINATE_0_DOT : MAVEN_COORDINATE_1_DOT) + version; + Set mavenCoordinates = new HashSet<>(customRuleSets); + mavenCoordinates.add(ktlintCoordinate); + return FormatterStep.create(NAME, + new KtLintStep(version, JarState.promise(() -> JarState.from(mavenCoordinates, provisioner)), editorConfig, editorConfigOverride), + KtLintStep::equalityState, State::createFormat); } @@ -68,6 +86,10 @@ public static String defaultVersion() { return DEFAULT_VERSION; } + private State equalityState() { + return new State(version, jarState.get(), config != null ? config.get() : null, editorConfigOverride); + } + private static final class State implements Serializable { private static final long serialVersionUID = 1L; /** The jar that contains the formatter. */ @@ -78,16 +100,12 @@ private static final class State implements Serializable { private final FileSignature editorConfigPath; State(String version, - Provisioner provisioner, + JarState jarState, @Nullable FileSignature editorConfigPath, - Map editorConfigOverride, - List customRuleSets) throws IOException { + Map editorConfigOverride) { this.version = version; + this.jarState = jarState; this.editorConfigOverride = new TreeMap<>(editorConfigOverride); - String ktlintCoordinate = (version.startsWith("0.") ? MAVEN_COORDINATE_0_DOT : MAVEN_COORDINATE_1_DOT) + version; - Set mavenCoordinates = new HashSet<>(customRuleSets); - mavenCoordinates.add(ktlintCoordinate); - this.jarState = JarState.from(mavenCoordinates, provisioner); this.editorConfigPath = editorConfigPath; } From 6e6ceaa19531a906147f291f4be472a6145d7a98 Mon Sep 17 00:00:00 2001 From: Goooler Date: Wed, 31 Jan 2024 23:20:54 +0800 Subject: [PATCH 03/13] Make KtfmtStep round-trippable --- .../diffplug/spotless/kotlin/KtfmtStep.java | 79 +++++++++++-------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java b/lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java index cf9a2dd231..768cd335cf 100644 --- a/lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ import static com.diffplug.spotless.kotlin.KtfmtStep.Style.DEFAULT; -import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -30,19 +29,38 @@ import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.RoundedStep; import com.diffplug.spotless.ThrowingEx; /** * Wraps up ktfmt as a FormatterStep. */ -public class KtfmtStep { - // prevent direct instantiation - private KtfmtStep() {} - +public class KtfmtStep implements RoundedStep { + private static final long serialVersionUID = 1L; private static final String DEFAULT_VERSION = "0.46"; - static final String NAME = "ktfmt"; - static final String PACKAGE = "com.facebook"; - static final String MAVEN_COORDINATE = PACKAGE + ":ktfmt:"; + private static final String NAME = "ktfmt"; + private static final String MAVEN_COORDINATE = "com.facebook:ktfmt:"; + + private final String version; + /** + * Option that allows to apply formatting options to perform a 4-space block and continuation indent. + */ + @Nullable + private final Style style; + @Nullable + private final KtfmtFormattingOptions options; + /** The jar that contains the formatter. */ + private final JarState.Promised jarState; + + private KtfmtStep(String version, + JarState.Promised jarState, + @Nullable Style style, + @Nullable KtfmtFormattingOptions options) { + this.version = Objects.requireNonNull(version, "version"); + this.style = style; + this.options = options; + this.jarState = Objects.requireNonNull(jarState, "jarState"); + } /** * Used to allow multiple style option through formatting options and since when is each of them available. @@ -136,39 +154,38 @@ public static FormatterStep create(String version, Provisioner provisioner) { public static FormatterStep create(String version, Provisioner provisioner, @Nullable Style style, @Nullable KtfmtFormattingOptions options) { Objects.requireNonNull(version, "version"); Objects.requireNonNull(provisioner, "provisioner"); - return FormatterStep.createLazy( - NAME, () -> new State(version, provisioner, style, options), State::createFormat); + return FormatterStep.create(NAME, + new KtfmtStep(version, JarState.promise(() -> JarState.from(MAVEN_COORDINATE + version, provisioner)), style, options), + KtfmtStep::equalityState, + State::createFormat); } public static String defaultVersion() { return DEFAULT_VERSION; } - static final class State implements Serializable { - private static final long serialVersionUID = 1L; + private State equalityState() { + return new State(version, jarState.get(), style, options); + } + private static final class State implements Serializable { + private static final long serialVersionUID = 1L; + private static final String PACKAGE = "com.facebook.ktfmt"; private final String version; - - private final String pkg; - /** - * Option that allows to apply formatting options to perform a 4 spaces block and continuation indent. - */ @Nullable private final Style style; - /** - * - */ @Nullable private final KtfmtFormattingOptions options; - /** The jar that contains the formatter. */ - final JarState jarState; + private final JarState jarState; - State(String version, Provisioner provisioner, @Nullable Style style, @Nullable KtfmtFormattingOptions options) throws IOException { + State(String version, + JarState jarState, + @Nullable Style style, + @Nullable KtfmtFormattingOptions options) { this.version = version; this.options = options; - this.pkg = PACKAGE; this.style = style; - this.jarState = JarState.from(MAVEN_COORDINATE + version, provisioner); + this.jarState = jarState; } FormatterFunc createFormat() throws Exception { @@ -259,7 +276,7 @@ private Object getCustomFormattingOptions(ClassLoader classLoader, Style style) // fallback to old, pre-0.19 ktfmt interface. if (style == Style.DEFAULT || style == Style.DROPBOX) { - Class formattingOptionsCompanionClazz = classLoader.loadClass(pkg + ".ktfmt.FormattingOptions$Companion"); + Class formattingOptionsCompanionClazz = classLoader.loadClass(PACKAGE + ".FormattingOptions$Companion"); Object companion = formattingOptionsCompanionClazz.getConstructors()[0].newInstance((Object) null); Method formattingOptionsMethod = formattingOptionsCompanionClazz.getDeclaredMethod("dropboxStyle"); return formattingOptionsMethod.invoke(companion); @@ -271,9 +288,9 @@ private Object getCustomFormattingOptions(ClassLoader classLoader, Style style) private Class getFormatterClazz(ClassLoader classLoader) throws Exception { Class formatterClazz; if (BadSemver.version(version) >= BadSemver.version(0, 31)) { - formatterClazz = classLoader.loadClass(pkg + ".ktfmt.format.Formatter"); + formatterClazz = classLoader.loadClass(PACKAGE + ".format.Formatter"); } else { - formatterClazz = classLoader.loadClass(pkg + ".ktfmt.FormatterKt"); + formatterClazz = classLoader.loadClass(PACKAGE + ".FormatterKt"); } return formatterClazz; } @@ -281,9 +298,9 @@ private Class getFormatterClazz(ClassLoader classLoader) throws Exception { private Class getFormattingOptionsClazz(ClassLoader classLoader) throws Exception { Class formattingOptionsClazz; if (BadSemver.version(version) >= BadSemver.version(0, 31)) { - formattingOptionsClazz = classLoader.loadClass(pkg + ".ktfmt.format.FormattingOptions"); + formattingOptionsClazz = classLoader.loadClass(PACKAGE + ".format.FormattingOptions"); } else { - formattingOptionsClazz = classLoader.loadClass(pkg + ".ktfmt.FormattingOptions"); + formattingOptionsClazz = classLoader.loadClass(PACKAGE + ".FormattingOptions"); } return formattingOptionsClazz; } From 37428703bde4abb78bb0802d1ce1f23959799d79 Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 1 Feb 2024 12:27:17 +0800 Subject: [PATCH 04/13] Make ScalaFmtStep round-trippable --- .../diffplug/spotless/scala/ScalaFmtStep.java | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java b/lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java index 114f4a9f1a..1f7eaf2ba9 100644 --- a/lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,17 +28,26 @@ import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.RoundedStep; /** Wraps up scalafmt as a FormatterStep. */ -public class ScalaFmtStep { - // prevent direct instantiation - private ScalaFmtStep() {} +public class ScalaFmtStep implements RoundedStep { + private static final long serialVersionUID = 1L; static final String DEFAULT_VERSION = "3.7.3"; private static final String DEFAULT_SCALA_MAJOR_VERSION = "2.13"; - static final String NAME = "scalafmt"; - static final String MAVEN_COORDINATE = "org.scalameta:scalafmt-core_"; + private static final String NAME = "scalafmt"; + private static final String MAVEN_COORDINATE = "org.scalameta:scalafmt-core_"; + + private final JarState.Promised jarState; + @Nullable + private final File configFile; + + private ScalaFmtStep(JarState.Promised jarState, @Nullable File configFile) { + this.jarState = jarState; + this.configFile = configFile; + } public static FormatterStep create(Provisioner provisioner) { return create(defaultVersion(), defaultScalaMajorVersion(), provisioner, null); @@ -51,8 +60,9 @@ public static FormatterStep create(String version, Provisioner provisioner, @Nul public static FormatterStep create(String version, @Nullable String scalaMajorVersion, Provisioner provisioner, @Nullable File configFile) { String finalScalaMajorVersion = scalaMajorVersion == null ? DEFAULT_SCALA_MAJOR_VERSION : scalaMajorVersion; - return FormatterStep.createLazy(NAME, - () -> new State(JarState.from(MAVEN_COORDINATE + finalScalaMajorVersion + ":" + version, provisioner), configFile), + return FormatterStep.create(NAME, + new ScalaFmtStep(JarState.promise(() -> JarState.from(MAVEN_COORDINATE + finalScalaMajorVersion + ":" + version, provisioner)), configFile), + ScalaFmtStep::equalityState, State::createFormat); } @@ -64,11 +74,15 @@ public static String defaultScalaMajorVersion() { return DEFAULT_SCALA_MAJOR_VERSION; } - static final class State implements Serializable { + private State equalityState() throws IOException { + return new State(jarState.get(), configFile); + } + + private static final class State implements Serializable { private static final long serialVersionUID = 1L; - final JarState jarState; - final FileSignature configSignature; + private final JarState jarState; + private final FileSignature configSignature; State(JarState jarState, @Nullable File configFile) throws IOException { this.jarState = jarState; From f86c26861b0463c568b0a745acddcdba0290c138 Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 1 Feb 2024 12:07:54 +0800 Subject: [PATCH 05/13] Make PalantirJavaFormatStep round-trippable --- .../spotless/java/PalantirJavaFormatStep.java | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/java/PalantirJavaFormatStep.java b/lib/src/main/java/com/diffplug/spotless/java/PalantirJavaFormatStep.java index a670a6fea7..a41811b57a 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/PalantirJavaFormatStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/PalantirJavaFormatStep.java @@ -23,16 +23,32 @@ /** Wraps up palantir-java-format fork of * google-java-format as a FormatterStep. */ -public class PalantirJavaFormatStep { - // prevent direct instantiation - private PalantirJavaFormatStep() {} - +public class PalantirJavaFormatStep implements RoundedStep { + private static final long serialVersionUID = 1L; private static final boolean DEFAULT_FORMAT_JAVADOC = false; private static final String DEFAULT_STYLE = "PALANTIR"; private static final String NAME = "palantir-java-format"; public static final String MAVEN_COORDINATE = "com.palantir.javaformat:palantir-java-format:"; private static final Jvm.Support JVM_SUPPORT = Jvm. support(NAME).add(8, "1.1.0").add(11, "2.28.0").add(21, "2.39.0"); + /** The jar that contains the formatter. */ + private final JarState.Promised jarState; + /** Version of the formatter jar. */ + private final String formatterVersion; + private final String style; + /** Whether to format Java docs. */ + private final boolean formatJavadoc; + + private PalantirJavaFormatStep(JarState.Promised jarState, + String formatterVersion, + String style, + boolean formatJavadoc) { + this.jarState = jarState; + this.formatterVersion = formatterVersion; + this.style = style; + this.formatJavadoc = formatJavadoc; + } + /** Creates a step which formats everything - code, import order, and unused imports. */ public static FormatterStep create(Provisioner provisioner) { return create(defaultVersion(), provisioner); @@ -60,8 +76,9 @@ public static FormatterStep create(String version, String style, boolean formatJ Objects.requireNonNull(style, "style"); Objects.requireNonNull(provisioner, "provisioner"); - return FormatterStep.createLazy(NAME, - () -> new State(JarState.from(MAVEN_COORDINATE + version, provisioner), version, style, formatJavadoc), + return FormatterStep.create(NAME, + new PalantirJavaFormatStep(JarState.promise(() -> JarState.from(MAVEN_COORDINATE + version, provisioner)), version, style, formatJavadoc), + PalantirJavaFormatStep::equalityState, State::createFormat); } @@ -80,15 +97,16 @@ public static boolean defaultFormatJavadoc() { return DEFAULT_FORMAT_JAVADOC; } + private State equalityState() { + return new State(jarState.get(), formatterVersion, style, formatJavadoc); + } + private static final class State implements Serializable { private static final long serialVersionUID = 1L; - /** The jar that contains the formatter. */ private final JarState jarState; - /** Version of the formatter jar. */ private final String formatterVersion; private final String style; - /** Whether to format Java docs. */ private final boolean formatJavadoc; State(JarState jarState, String formatterVersion, String style, boolean formatJavadoc) { From 2e7ef03845149ab0e92ceff81fea595ad935f3e1 Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 1 Feb 2024 10:48:25 +0800 Subject: [PATCH 06/13] Make GoogleJavaFormatStep round-trippable --- .../spotless/java/GoogleJavaFormatStep.java | 88 +++++++++++-------- 1 file changed, 51 insertions(+), 37 deletions(-) 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 d0312dcc1e..85460c6d27 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java @@ -24,18 +24,39 @@ import com.diffplug.spotless.JarState; import com.diffplug.spotless.Jvm; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.RoundedStep; /** Wraps up google-java-format as a FormatterStep. */ -public class GoogleJavaFormatStep { - // prevent direct instantiation - private GoogleJavaFormatStep() {} - +public class GoogleJavaFormatStep implements RoundedStep { + private static final long serialVersionUID = 1L; private static final String DEFAULT_STYLE = "GOOGLE"; 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; - static final String NAME = "google-java-format"; - public static final String MAVEN_COORDINATE = "com.google.googlejavaformat:google-java-format"; + private static final String NAME = "google-java-format"; + private static final String MAVEN_COORDINATE = "com.google.googlejavaformat:google-java-format"; + + /** The jar that contains the formatter. */ + private final JarState.Promised jarState; + private final String version; + private final String style; + private final boolean reflowLongStrings; + private final boolean reorderImports; + private final boolean formatJavadoc; + + private GoogleJavaFormatStep(JarState.Promised jarState, + String version, + String style, + boolean reflowLongStrings, + boolean reorderImports, + boolean formatJavadoc) { + this.jarState = jarState; + this.version = version; + this.style = style; + this.reflowLongStrings = reflowLongStrings; + this.reorderImports = reorderImports; + this.formatJavadoc = formatJavadoc; + } /** Creates a step which formats everything - code, import order, and unused imports. */ public static FormatterStep create(Provisioner provisioner) { @@ -74,12 +95,13 @@ public static FormatterStep create(String groupArtifact, String version, String Objects.requireNonNull(version, "version"); Objects.requireNonNull(style, "style"); Objects.requireNonNull(provisioner, "provisioner"); - return FormatterStep.createLazy(NAME, - () -> new State(NAME, groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc), + return FormatterStep.create(NAME, + new GoogleJavaFormatStep(JarState.promise(() -> JarState.from(groupArtifact + ":" + version, provisioner)), version, style, reflowLongStrings, reorderImports, formatJavadoc), + GoogleJavaFormatStep::equalityState, State::createFormat); } - static final Jvm.Support JVM_SUPPORT = Jvm. support(NAME) + private static final Jvm.Support JVM_SUPPORT = Jvm. support(NAME) .addMin(11, "1.8") // we only support google-java-format >= 1.8 due to api changes .addMin(16, "1.10.0") // java 16 requires at least 1.10.0 due to jdk api changes in JavaTokenizer .addMin(21, "1.17.0") // java 21 requires at least 1.17.0 due to https://github.com/google/google-java-format/issues/898 @@ -91,7 +113,7 @@ public static String defaultGroupArtifact() { /** Get default formatter version */ public static String defaultVersion() { - return JVM_SUPPORT.getRecommendedFormatterVersion(); + return Objects.requireNonNull(JVM_SUPPORT.getRecommendedFormatterVersion()); } public static String defaultStyle() { @@ -110,39 +132,33 @@ public static boolean defaultFormatJavadoc() { return DEFAULT_FORMAT_JAVADOC; } + private State equalityState() { + return new State(version, style, jarState.get(), reflowLongStrings, reorderImports, formatJavadoc); + } + static final class State implements Serializable { private static final long serialVersionUID = 1L; - /** The jar that contains the formatter. */ - final JarState jarState; - final String stepName; - final String version; - final String style; - final boolean reflowLongStrings; - final boolean reorderImports; - final boolean formatJavadoc; - - State(String stepName, String version, Provisioner provisioner) throws Exception { - this(stepName, version, DEFAULT_STYLE, provisioner); - } + private final JarState jarState; + private final String version; + private final String style; + private final boolean reflowLongStrings; + private final boolean reorderImports; + private final boolean formatJavadoc; - State(String stepName, String version, String style, Provisioner provisioner) throws Exception { - this(stepName, version, style, provisioner, DEFAULT_REFLOW_LONG_STRINGS); + State(String version, JarState jarState) { + this(version, DEFAULT_STYLE, jarState, DEFAULT_REFLOW_LONG_STRINGS, DEFAULT_REORDER_IMPORTS, DEFAULT_FORMAT_JAVADOC); } - State(String stepName, String version, String style, Provisioner provisioner, boolean reflowLongStrings) throws Exception { - this(stepName, version, style, provisioner, reflowLongStrings, DEFAULT_REORDER_IMPORTS); - } - - State(String stepName, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports) throws Exception { - this(stepName, MAVEN_COORDINATE, version, style, provisioner, reflowLongStrings, reorderImports, DEFAULT_FORMAT_JAVADOC); - } - - State(String stepName, String groupArtifact, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc) throws Exception { + State(String version, + String style, + JarState jarState, + boolean reflowLongStrings, + boolean reorderImports, + boolean formatJavadoc) { JVM_SUPPORT.assertFormatterSupported(version); ModuleHelper.doOpenInternalPackagesIfRequired(); - this.jarState = JarState.from(groupArtifact + ":" + version, provisioner); - this.stepName = stepName; + this.jarState = jarState; this.version = version; this.style = style; this.reflowLongStrings = reflowLongStrings; @@ -167,7 +183,5 @@ FormatterFunc createRemoveUnusedImportsOnly() throws Exception { return JVM_SUPPORT.suggestLaterVersionOnError(version, googleJavaFormatRemoveUnusedImporterFormatterFunc); } - } - } From 4747a73b8aa41259c9a00e9d82a02eb8a27c1903 Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 1 Feb 2024 11:05:24 +0800 Subject: [PATCH 07/13] Make CleanthatJavaStep round-trippable --- .../spotless/java/CleanthatJavaStep.java | 91 +++++++++++-------- .../java/RemoveUnusedImportsStep.java | 4 +- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/java/CleanthatJavaStep.java b/lib/src/main/java/com/diffplug/spotless/java/CleanthatJavaStep.java index 91439a1767..f829d20329 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/CleanthatJavaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/CleanthatJavaStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 DiffPlug + * Copyright 2023-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package com.diffplug.spotless.java; -import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -27,6 +26,7 @@ import com.diffplug.spotless.JarState; import com.diffplug.spotless.Jvm; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.RoundedStep; /** * Enables CleanThat as a SpotLess step. @@ -34,23 +34,43 @@ * @author Benoit Lacelle */ // https://github.com/diffplug/spotless/blob/main/CONTRIBUTING.md#how-to-add-a-new-formatterstep -public final class CleanthatJavaStep { - +public final class CleanthatJavaStep implements RoundedStep { + private static final long serialVersionUID = 1L; private static final String NAME = "cleanthat"; private static final String MAVEN_COORDINATE = "io.github.solven-eu.cleanthat:java"; - - // CleanThat changelog is available at https://github.com/solven-eu/cleanthat/blob/master/CHANGES.MD + /** + * CleanThat changelog is available at here. + */ private static final Jvm.Support JVM_SUPPORT = Jvm. support(NAME).add(11, "2.16"); - // prevent direct instantiation - private CleanthatJavaStep() {} + private final JarState.Promised jarState; + private final String version; + private final String sourceJdkVersion; + private final List included; + private final List excluded; + private final boolean includeDraft; + + private CleanthatJavaStep(JarState.Promised jarState, + String version, + String sourceJdkVersion, + List included, + List excluded, + boolean includeDraft) { + this.jarState = jarState; + this.version = version; + + this.sourceJdkVersion = sourceJdkVersion; + this.included = included; + this.excluded = excluded; + this.includeDraft = includeDraft; + } - /** Creates a step which apply default CleanThat mutators. */ + /** Creates a step that applies default CleanThat mutators. */ public static FormatterStep create(Provisioner provisioner) { return create(defaultVersion(), provisioner); } - /** Creates a step which apply default CleanThat mutators. */ + /** Creates a step that applies default CleanThat mutators. */ public static FormatterStep create(String version, Provisioner provisioner) { return create(MAVEN_COORDINATE, version, defaultSourceJdk(), defaultMutators(), defaultExcludedMutators(), defaultIncludeDraft(), provisioner); } @@ -64,7 +84,6 @@ public static String defaultSourceJdk() { /** * By default, we include only safe and consensual mutators - * @return */ public static List defaultMutators() { // see ICleanthatStepParametersProperties.SAFE_AND_CONSENSUAL @@ -79,7 +98,7 @@ public static boolean defaultIncludeDraft() { return false; } - /** Creates a step which apply selected CleanThat mutators. */ + /** Creates a step that applies selected CleanThat mutators. */ public static FormatterStep create(String groupArtifact, String version, String sourceJdkVersion, @@ -93,57 +112,51 @@ public static FormatterStep create(String groupArtifact, } Objects.requireNonNull(version, "version"); Objects.requireNonNull(provisioner, "provisioner"); - return FormatterStep.createLazy(NAME, - () -> new JavaRefactorerState(NAME, groupArtifact, version, sourceJdkVersion, included, excluded, includeDraft, provisioner), - JavaRefactorerState::createFormat); + return FormatterStep.create(NAME, + new CleanthatJavaStep(JarState.promise(() -> JarState.from(groupArtifact + ":" + version, provisioner)), version, sourceJdkVersion, included, excluded, includeDraft), + CleanthatJavaStep::equalityState, + State::createFormat); } /** Get default formatter version */ public static String defaultVersion() { - return JVM_SUPPORT.getRecommendedFormatterVersion(); + return Objects.requireNonNull(JVM_SUPPORT.getRecommendedFormatterVersion()); } public static String defaultGroupArtifact() { return MAVEN_COORDINATE; } - static final class JavaRefactorerState implements Serializable { - private static final long serialVersionUID = 1L; - - final JarState jarState; - final String stepName; - final String version; + private State equalityState() { + return new State(jarState.get(), version, sourceJdkVersion, included, excluded, includeDraft); + } - final String sourceJdkVersion; - final List included; - final List excluded; - final boolean includeDraft; + static final class State implements Serializable { + private static final long serialVersionUID = 1L; - JavaRefactorerState(String stepName, String version, Provisioner provisioner) throws IOException { - this(stepName, MAVEN_COORDINATE, version, defaultSourceJdk(), defaultMutators(), defaultExcludedMutators(), defaultIncludeDraft(), provisioner); - } + private final JarState jarState; + private final String version; + private final String sourceJdkVersion; + private final List included; + private final List excluded; + private final boolean includeDraft; - JavaRefactorerState(String stepName, - String groupArtifact, + State(JarState jarState, String version, String sourceJdkVersion, List included, List excluded, - boolean includeDraft, - Provisioner provisioner) throws IOException { + boolean includeDraft) { JVM_SUPPORT.assertFormatterSupported(version); ModuleHelper.doOpenInternalPackagesIfRequired(); - this.jarState = JarState.from(groupArtifact + ":" + version, provisioner); - this.stepName = stepName; + this.jarState = jarState; this.version = version; - this.sourceJdkVersion = sourceJdkVersion; this.included = included; this.excluded = excluded; this.includeDraft = includeDraft; } - @SuppressWarnings("PMD.UseProperClassLoader") FormatterFunc createFormat() { ClassLoader classLoader = jarState.getClassLoader(); @@ -159,9 +172,7 @@ FormatterFunc createFormat() { throw new IllegalStateException("Issue executing the formatter", e); } - return JVM_SUPPORT.suggestLaterVersionOnError(version, input -> { - return (String) formatterMethod.invoke(formatter, input); - }); + return JVM_SUPPORT.suggestLaterVersionOnError(version, input -> (String) formatterMethod.invoke(formatter, input)); } } } diff --git a/lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java b/lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java index a4c460e929..af04d3ec66 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java @@ -52,8 +52,8 @@ public static FormatterStep create(String unusedImportRemover, Provisioner provi GoogleJavaFormatStep.State::createRemoveUnusedImportsOnly); } else if (CLEANTHAT.equals(unusedImportRemover)) { return FormatterStep.createLazy(NAME, - () -> new CleanthatJavaStep.JavaRefactorerState(NAME, CleanthatJavaStep.defaultGroupArtifact(), CleanthatJavaStep.defaultVersion(), "99.9", Arrays.asList(CLEANTHAT_MUTATOR), Arrays.asList(), false, provisioner), - CleanthatJavaStep.JavaRefactorerState::createFormat); + () -> new CleanthatJavaStep.State(NAME, CleanthatJavaStep.defaultGroupArtifact(), CleanthatJavaStep.defaultVersion(), "99.9", Arrays.asList(CLEANTHAT_MUTATOR), Arrays.asList(), false, provisioner), + CleanthatJavaStep.State::createFormat); } else { throw new IllegalArgumentException("Invalid unusedImportRemover: " + unusedImportRemover); } From 0b66cca74fe1ba1cded57ec59f58ddd0b073c405 Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 1 Feb 2024 11:18:20 +0800 Subject: [PATCH 08/13] Make RemoveUnusedImportsStep round-trippable --- .../spotless/java/CleanthatJavaStep.java | 2 +- .../spotless/java/GoogleJavaFormatStep.java | 31 +++++++++++++------ .../java/RemoveUnusedImportsStep.java | 28 ++++++++--------- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/java/CleanthatJavaStep.java b/lib/src/main/java/com/diffplug/spotless/java/CleanthatJavaStep.java index f829d20329..93a3b7662c 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/CleanthatJavaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/CleanthatJavaStep.java @@ -131,7 +131,7 @@ private State equalityState() { return new State(jarState.get(), version, sourceJdkVersion, included, excluded, includeDraft); } - static final class State implements Serializable { + private static final class State implements Serializable { private static final long serialVersionUID = 1L; private final JarState jarState; 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 85460c6d27..00452fef46 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java @@ -88,6 +88,14 @@ 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(groupArtifact, version, style, provisioner, reflowLongStrings, reorderImports, formatJavadoc, false); + } + + static FormatterStep createRemoveUnusedImportsOnly(Provisioner provisioner) { + return createInternally(MAVEN_COORDINATE, defaultVersion(), defaultStyle(), provisioner, defaultReflowLongStrings(), defaultReorderImports(), defaultFormatJavadoc(), true); + } + + private static FormatterStep createInternally(String groupArtifact, String version, String style, Provisioner provisioner, boolean reflowLongStrings, boolean reorderImports, boolean formatJavadoc, 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'"); @@ -95,10 +103,19 @@ public static FormatterStep create(String groupArtifact, String version, String Objects.requireNonNull(version, "version"); Objects.requireNonNull(style, "style"); Objects.requireNonNull(provisioner, "provisioner"); - return FormatterStep.create(NAME, - new GoogleJavaFormatStep(JarState.promise(() -> JarState.from(groupArtifact + ":" + version, provisioner)), version, style, reflowLongStrings, reorderImports, formatJavadoc), - GoogleJavaFormatStep::equalityState, - State::createFormat); + + GoogleJavaFormatStep step = new GoogleJavaFormatStep(JarState.promise(() -> JarState.from(groupArtifact + ":" + version, provisioner)), version, style, reflowLongStrings, reorderImports, formatJavadoc); + if (removeImports) { + return FormatterStep.create(NAME, + step, + GoogleJavaFormatStep::equalityState, + State::createRemoveUnusedImportsOnly); + } else { + return FormatterStep.create(NAME, + step, + GoogleJavaFormatStep::equalityState, + State::createFormat); + } } private static final Jvm.Support JVM_SUPPORT = Jvm. support(NAME) @@ -136,7 +153,7 @@ private State equalityState() { return new State(version, style, jarState.get(), reflowLongStrings, reorderImports, formatJavadoc); } - static final class State implements Serializable { + private static final class State implements Serializable { private static final long serialVersionUID = 1L; private final JarState jarState; @@ -146,10 +163,6 @@ static final class State implements Serializable { private final boolean reorderImports; private final boolean formatJavadoc; - State(String version, JarState jarState) { - this(version, DEFAULT_STYLE, jarState, DEFAULT_REFLOW_LONG_STRINGS, DEFAULT_REORDER_IMPORTS, DEFAULT_FORMAT_JAVADOC); - } - State(String version, String style, JarState jarState, diff --git a/lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java b/lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java index af04d3ec66..89129e8171 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,17 @@ */ package com.diffplug.spotless.java; -import java.util.Arrays; +import java.util.List; import java.util.Objects; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.RoundedStep; /** Uses google-java-format or cleanthat.UnnecessaryImport, but only to remove unused imports. */ -public class RemoveUnusedImportsStep { - static final String NAME = "removeUnusedImports"; +public class RemoveUnusedImportsStep implements RoundedStep { + private static final long serialVersionUID = 1L; + private static final String NAME = "removeUnusedImports"; static final String GJF = "google-java-format"; static final String CLEANTHAT = "cleanthat-javaparser-unnecessaryimport"; @@ -34,7 +36,7 @@ public class RemoveUnusedImportsStep { // prevent direct instantiation private RemoveUnusedImportsStep() {} - public static final String defaultFormatter() { + public static String defaultFormatter() { return GJF; } @@ -45,16 +47,12 @@ public static FormatterStep create(Provisioner provisioner) { public static FormatterStep create(String unusedImportRemover, Provisioner provisioner) { Objects.requireNonNull(provisioner, "provisioner"); - - if (GJF.equals(unusedImportRemover)) { - return FormatterStep.createLazy(NAME, - () -> new GoogleJavaFormatStep.State(NAME, GoogleJavaFormatStep.defaultVersion(), provisioner), - GoogleJavaFormatStep.State::createRemoveUnusedImportsOnly); - } else if (CLEANTHAT.equals(unusedImportRemover)) { - return FormatterStep.createLazy(NAME, - () -> new CleanthatJavaStep.State(NAME, CleanthatJavaStep.defaultGroupArtifact(), CleanthatJavaStep.defaultVersion(), "99.9", Arrays.asList(CLEANTHAT_MUTATOR), Arrays.asList(), false, provisioner), - CleanthatJavaStep.State::createFormat); - } else { + switch (unusedImportRemover) { + case GJF: + return GoogleJavaFormatStep.createRemoveUnusedImportsOnly(provisioner); + case CLEANTHAT: + return CleanthatJavaStep.create(CleanthatJavaStep.defaultGroupArtifact(), CleanthatJavaStep.defaultVersion(), "99.9", List.of(CLEANTHAT_MUTATOR), List.of(), false, provisioner); + default: throw new IllegalArgumentException("Invalid unusedImportRemover: " + unusedImportRemover); } } From 931e106f2dbd3a6d4aacaf92cef288da9647cef5 Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 1 Feb 2024 11:58:08 +0800 Subject: [PATCH 09/13] Make FormatAnnotationsStep round-trippable --- .../spotless/java/FormatAnnotationsStep.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/java/FormatAnnotationsStep.java b/lib/src/main/java/com/diffplug/spotless/java/FormatAnnotationsStep.java index 5a2d856850..bb74f7a0bc 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/FormatAnnotationsStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/FormatAnnotationsStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 DiffPlug + * Copyright 2022-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.RoundedStep; /** * Some formatters put every annotation on its own line @@ -36,7 +37,8 @@ *

* Note: A type annotation is an annotation that is meta-annotated with {@code @Target({ElementType.TYPE_USE})}. */ -public final class FormatAnnotationsStep { +public final class FormatAnnotationsStep implements RoundedStep { + private static final long serialVersionUID = 1L; /** * Simple names of type annotations. @@ -389,7 +391,7 @@ public final class FormatAnnotationsStep { ); - static final String NAME = "No line break between type annotation and type"; + private static final String NAME = "No line break between type annotation and type"; public static FormatterStep create() { return create(Collections.emptyList(), Collections.emptyList()); @@ -432,13 +434,13 @@ private static final class State implements Serializable { } FormatterFunc toFormatter() { - return unixStr -> fixupTypeAnnotations(unixStr); + return this::fixupTypeAnnotations; } /** * Removes line break between type annotations and the following type. * - * @param the text of a Java file + * @param unixStr the text of a Java file * @return corrected text of the Java file */ String fixupTypeAnnotations(String unixStr) { From f5e3dd326772f42603efa9734678d6cdf13b0ff0 Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 1 Feb 2024 12:01:14 +0800 Subject: [PATCH 10/13] Make ImportOrderStep round-trippable --- .../spotless/java/ImportOrderStep.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java b/lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java index e1e63458d9..ad4cead559 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,12 +34,16 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.annotation.Nullable; + import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.RoundedStep; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -public final class ImportOrderStep { +public final class ImportOrderStep implements RoundedStep { + private static final long serialVersionUID = 1L; private static final boolean WILDCARDS_LAST_DEFAULT = false; private static final boolean SEMANTIC_SORT_DEFAULT = false; private static final Set TREAT_AS_PACKAGE_DEFAULT = Set.of(); @@ -84,9 +88,8 @@ public FormatterStep createFrom(boolean wildcardsLast, boolean semanticSort, Set private FormatterStep createFrom(boolean wildcardsLast, boolean semanticSort, Set treatAsPackage, Set treatAsClass, Supplier> importOrder) { - return FormatterStep.createLazy("importOrder", - () -> new State(importOrder.get(), lineFormat, wildcardsLast, semanticSort, treatAsPackage, - treatAsClass), + return FormatterStep.create("importOrder", + new State(importOrder.get(), lineFormat, wildcardsLast, semanticSort, treatAsPackage, treatAsClass), State::toFormatter); } @@ -121,8 +124,12 @@ private static final class State implements Serializable { private final TreeSet treatAsPackage; private final TreeSet treatAsClass; - State(List importOrder, String lineFormat, boolean wildcardsLast, boolean semanticSort, - Set treatAsPackage, Set treatAsClass) { + State(List importOrder, + String lineFormat, + boolean wildcardsLast, + boolean semanticSort, + @Nullable Set treatAsPackage, + @Nullable Set treatAsClass) { this.importOrder = importOrder; this.lineFormat = lineFormat; this.wildcardsLast = wildcardsLast; From adb6ec77e0041f9c415ca4535697be36d7b196ce Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 1 Feb 2024 16:36:42 +0800 Subject: [PATCH 11/13] Make RemoveSemicolonsStep round-trippable --- .../spotless/groovy/RemoveSemicolonsStep.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/groovy/RemoveSemicolonsStep.java b/lib/src/main/java/com/diffplug/spotless/groovy/RemoveSemicolonsStep.java index e24feb5cd3..31ebb069e0 100644 --- a/lib/src/main/java/com/diffplug/spotless/groovy/RemoveSemicolonsStep.java +++ b/lib/src/main/java/com/diffplug/spotless/groovy/RemoveSemicolonsStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 DiffPlug + * Copyright 2023-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,13 +21,15 @@ import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.RoundedStep; /** * Removes all semicolons from the end of lines. * * @author Jose Luis Badano */ -public final class RemoveSemicolonsStep { +public final class RemoveSemicolonsStep implements RoundedStep { + private static final long serialVersionUID = 1L; private static final String NAME = "Remove unnecessary semicolons"; private RemoveSemicolonsStep() { @@ -35,9 +37,9 @@ private RemoveSemicolonsStep() { } public static FormatterStep create() { - return FormatterStep.createLazy(NAME, - State::new, - RemoveSemicolonsStep.State::toFormatter); + return FormatterStep.create(NAME, + new State(), + State::toFormatter); } private static final class State implements Serializable { @@ -64,7 +66,7 @@ FormatterFunc toFormatter() { * @return the line without the last semicolon */ private String removeSemicolon(String line) { - // find last semicolon in a string a remove it + // Find the last semicolon in a string and remove it. int lastSemicolon = line.lastIndexOf(";"); if (lastSemicolon != -1 && lastSemicolon == line.length() - 1) { return line.substring(0, lastSemicolon); From 8910c687cbdccc7cfb2220bd14e24b95b0d955ea Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 12 Feb 2024 20:43:38 -0800 Subject: [PATCH 12/13] Adjust `StepHarnessBase` so that the newly fixed roundtrips get tested. --- .../src/main/java/com/diffplug/spotless/StepHarnessBase.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testlib/src/main/java/com/diffplug/spotless/StepHarnessBase.java b/testlib/src/main/java/com/diffplug/spotless/StepHarnessBase.java index c82de128a1..fb1ef97d43 100644 --- a/testlib/src/main/java/com/diffplug/spotless/StepHarnessBase.java +++ b/testlib/src/main/java/com/diffplug/spotless/StepHarnessBase.java @@ -17,6 +17,7 @@ import java.util.Locale; import java.util.Objects; +import java.util.Set; import org.assertj.core.api.Assertions; @@ -48,6 +49,10 @@ protected StepHarnessBase(Formatter formatter) { supportsRoundTrip = true; } else if (onlyStepName.equals("fence")) { supportsRoundTrip = true; + } else if (Set.of("ktlint", "ktfmt", "scalafmt", "palantir-java-format", "google-java-format", + "removeUnusedImports", "cleanthat", "No line break between type annotation and type", + "importOrder", "Remove unnecessary semicolons").contains(onlyStepName)) { + supportsRoundTrip = true; } } } From a5b7bec10805779e43e187aaee802c59c3ff3464 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 12 Feb 2024 20:54:10 -0800 Subject: [PATCH 13/13] Add missing arguments to make `FormatAnnotationsStep` and `ImportOrderStep` serializable. --- .../java/com/diffplug/spotless/java/FormatAnnotationsStep.java | 3 ++- .../main/java/com/diffplug/spotless/java/ImportOrderStep.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/src/main/java/com/diffplug/spotless/java/FormatAnnotationsStep.java b/lib/src/main/java/com/diffplug/spotless/java/FormatAnnotationsStep.java index bb74f7a0bc..18b6444606 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/FormatAnnotationsStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/FormatAnnotationsStep.java @@ -27,6 +27,7 @@ import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.RoundedStep; +import com.diffplug.spotless.SerializedFunction; /** * Some formatters put every annotation on its own line @@ -398,7 +399,7 @@ public static FormatterStep create() { } public static FormatterStep create(List addedTypeAnnotations, List removedTypeAnnotations) { - return FormatterStep.create(NAME, new State(addedTypeAnnotations, removedTypeAnnotations), State::toFormatter); + return FormatterStep.create(NAME, new State(addedTypeAnnotations, removedTypeAnnotations), SerializedFunction.identity(), State::toFormatter); } private FormatAnnotationsStep() {} diff --git a/lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java b/lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java index ad4cead559..8e359eece2 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java @@ -39,6 +39,7 @@ import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.RoundedStep; +import com.diffplug.spotless.SerializedFunction; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -90,6 +91,7 @@ private FormatterStep createFrom(boolean wildcardsLast, boolean semanticSort, Se Set treatAsClass, Supplier> importOrder) { return FormatterStep.create("importOrder", new State(importOrder.get(), lineFormat, wildcardsLast, semanticSort, treatAsPackage, treatAsClass), + SerializedFunction.identity(), State::toFormatter); }