From 8134fc318d9420fa296068f152ac5131b29e9dc7 Mon Sep 17 00:00:00 2001 From: Peter Laggner Date: Thu, 4 Sep 2025 23:54:56 +0200 Subject: [PATCH 01/10] fix: add support for ktfmt's TrailingCommaManagementStrategy (WIP) NOTE: also updated JVM version to 17 --- gradle.properties | 2 +- gradle/java-publish.gradle | 2 +- lib/build.gradle | 2 +- .../glue/ktfmt/KtfmtFormatterFunc.java | 34 ++-- .../glue/ktfmt/KtfmtFormattingOptions.java | 22 +-- .../KtfmtTrailingCommaManagementStrategy.java | 17 ++ .../diffplug/spotless/kotlin/KtfmtStep.java | 170 +++++++++++++----- plugin-gradle/README.md | 2 +- .../gradle/spotless/KotlinExtensionTest.java | 3 +- .../spotless/maven/kotlin/KtfmtTest.java | 2 + .../spotless/kotlin/KtfmtStepTest.java | 6 +- 11 files changed, 176 insertions(+), 86 deletions(-) create mode 100644 lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtTrailingCommaManagementStrategy.java diff --git a/gradle.properties b/gradle.properties index 3c9cdddbfd..7c72729992 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ artifactIdMaven=spotless-maven-plugin artifactIdGradle=spotless-plugin-gradle # Build requirements -VER_JAVA=11 +VER_JAVA=17 VER_JSR_305=3.0.2 # Dependencies provided by Spotless plugin diff --git a/gradle/java-publish.gradle b/gradle/java-publish.gradle index 52a6ae7137..dad3328f5a 100644 --- a/gradle/java-publish.gradle +++ b/gradle/java-publish.gradle @@ -77,7 +77,7 @@ javadoc { // // Thus, no javadoc warnings. options.addStringOption('Xdoclint:none', '-quiet') - options.addStringOption('source', '11') + options.addStringOption('source', '17') // setup the header options.header javadocInfo // setup links diff --git a/lib/build.gradle b/lib/build.gradle index 745a8b410b..a95a4ce819 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -104,7 +104,7 @@ dependencies { jacksonCompileOnly "com.fasterxml.jackson.core:jackson-databind:$VER_JACKSON" jacksonCompileOnly "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$VER_JACKSON" // ktfmt - ktfmtCompileOnly "com.facebook:ktfmt:0.53" + ktfmtCompileOnly "com.facebook:ktfmt:0.58" ktfmtCompileOnly("com.google.googlejavaformat:google-java-format") { version { strictly '1.7' // for JDK 8 compatibility diff --git a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormatterFunc.java b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormatterFunc.java index bb4c9050bd..c911c759b0 100644 --- a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormatterFunc.java +++ b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormatterFunc.java @@ -55,29 +55,23 @@ public String apply(@Nonnull String input) throws Exception { } private FormattingOptions createFormattingOptions() throws Exception { - FormattingOptions formattingOptions; - switch (style) { - case META: - formattingOptions = Formatter.META_FORMAT; - break; - case GOOGLE: - formattingOptions = Formatter.GOOGLE_FORMAT; - break; - case KOTLIN_LANG: - formattingOptions = Formatter.KOTLINLANG_FORMAT; - break; - default: - throw new IllegalStateException("Unknown formatting option " + style); - } + FormattingOptions formattingOptions = switch (style) { + case META -> Formatter.META_FORMAT; + case GOOGLE -> Formatter.GOOGLE_FORMAT; + case KOTLIN_LANG -> Formatter.KOTLINLANG_FORMAT; + default -> throw new IllegalStateException("Unknown formatting option " + style); + }; if (ktfmtFormattingOptions != null) { formattingOptions = formattingOptions.copy( - ktfmtFormattingOptions.getMaxWidth().orElse(formattingOptions.getMaxWidth()), - ktfmtFormattingOptions.getBlockIndent().orElse(formattingOptions.getBlockIndent()), - ktfmtFormattingOptions.getContinuationIndent().orElse(formattingOptions.getContinuationIndent()), - ktfmtFormattingOptions.getManageTrailingCommas().orElse(formattingOptions.getManageTrailingCommas()), - ktfmtFormattingOptions.getRemoveUnusedImports().orElse(formattingOptions.getRemoveUnusedImports()), - formattingOptions.getDebuggingPrintOpsAfterFormatting()); + ktfmtFormattingOptions.getMaxWidth().orElse(formattingOptions.getMaxWidth()), + ktfmtFormattingOptions.getBlockIndent().orElse(formattingOptions.getBlockIndent()), + ktfmtFormattingOptions.getContinuationIndent().orElse(formattingOptions.getContinuationIndent()), + ktfmtFormattingOptions.getTrailingCommaManagementStrategy() + .map(KtfmtTrailingCommaManagementStrategy::toFormatterTrailingCommaManagementStrategy) + .orElse(formattingOptions.getTrailingCommaManagementStrategy()), + ktfmtFormattingOptions.getRemoveUnusedImports().orElse(formattingOptions.getRemoveUnusedImports()), + formattingOptions.getDebuggingPrintOpsAfterFormatting()); } return formattingOptions; diff --git a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormattingOptions.java b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormattingOptions.java index 0a810152b6..c25e74fcb7 100644 --- a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormattingOptions.java +++ b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormattingOptions.java @@ -35,19 +35,19 @@ public final class KtfmtFormattingOptions { private Boolean removeUnusedImports; @Nullable - private Boolean manageTrailingCommas; + private KtfmtTrailingCommaManagementStrategy trailingCommaManagementStrategy; public KtfmtFormattingOptions( - @Nullable Integer maxWidth, - @Nullable Integer blockIndent, - @Nullable Integer continuationIndent, - @Nullable Boolean removeUnusedImports, - @Nullable Boolean manageTrailingCommas) { + @Nullable Integer maxWidth, + @Nullable Integer blockIndent, + @Nullable Integer continuationIndent, + @Nullable Boolean removeUnusedImports, + @Nullable KtfmtTrailingCommaManagementStrategy trailingCommaManagementStrategy) { this.maxWidth = maxWidth; this.blockIndent = blockIndent; this.continuationIndent = continuationIndent; this.removeUnusedImports = removeUnusedImports; - this.manageTrailingCommas = manageTrailingCommas; + this.trailingCommaManagementStrategy = trailingCommaManagementStrategy; } @Nonnull @@ -71,8 +71,8 @@ public Optional getRemoveUnusedImports() { } @Nonnull - public Optional getManageTrailingCommas() { - return Optional.ofNullable(manageTrailingCommas); + public Optional getTrailingCommaManagementStrategy() { + return Optional.ofNullable(trailingCommaManagementStrategy); } public void setMaxWidth(int maxWidth) { @@ -100,7 +100,7 @@ public void setRemoveUnusedImports(boolean removeUnusedImports) { this.removeUnusedImports = removeUnusedImports; } - public void setManageTrailingCommas(boolean manageTrailingCommas) { - this.manageTrailingCommas = manageTrailingCommas; + public void setTrailingCommaManagementStrategy(@Nullable KtfmtTrailingCommaManagementStrategy trailingCommaManagementStrategy) { + this.trailingCommaManagementStrategy = trailingCommaManagementStrategy; } } diff --git a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtTrailingCommaManagementStrategy.java b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtTrailingCommaManagementStrategy.java new file mode 100644 index 0000000000..3c7b017ad9 --- /dev/null +++ b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtTrailingCommaManagementStrategy.java @@ -0,0 +1,17 @@ +package com.diffplug.spotless.glue.ktfmt; + +import com.facebook.ktfmt.format.TrailingCommaManagementStrategy; + +public enum KtfmtTrailingCommaManagementStrategy { + NONE, + ONLY_ADD, + COMPLETE; + + public TrailingCommaManagementStrategy toFormatterTrailingCommaManagementStrategy() { + return switch (this) { + case NONE -> TrailingCommaManagementStrategy.NONE; + case ONLY_ADD -> TrailingCommaManagementStrategy.ONLY_ADD; + case COMPLETE -> TrailingCommaManagementStrategy.COMPLETE; + }; + } +} 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 2120dc144a..5f0660f7b1 100644 --- a/lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java @@ -19,6 +19,8 @@ import static com.diffplug.spotless.kotlin.KtfmtStep.Style.DROPBOX; import static com.diffplug.spotless.kotlin.KtfmtStep.Style.META; +import static com.diffplug.spotless.kotlin.KtfmtStep.TrailingCommaManagementStrategy.ONLY_ADD; + import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -39,7 +41,7 @@ */ public class KtfmtStep implements Serializable { private static final long serialVersionUID = 1L; - private static final String DEFAULT_VERSION = "0.53"; + private static final String DEFAULT_VERSION = "0.58"; private static final String NAME = "ktfmt"; private static final String MAVEN_COORDINATE = "com.facebook:ktfmt:"; @@ -51,13 +53,15 @@ public class KtfmtStep implements Serializable { private final Style style; @Nullable private final KtfmtFormattingOptions options; - /** The jar that contains the formatter. */ + /** + * The jar that contains the formatter. + */ private final JarState.Promised jarState; private KtfmtStep(String version, - JarState.Promised jarState, - @Nullable Style style, - @Nullable KtfmtFormattingOptions options) { + JarState.Promised jarState, + @Nullable Style style, + @Nullable KtfmtFormattingOptions options) { this.version = Objects.requireNonNull(version, "version"); this.style = style; this.options = options; @@ -103,13 +107,43 @@ String getSince() { return since; } - /** Last version (inclusive) that supports this style */ + /** + * Last version (inclusive) that supports this style + */ @Nullable String getUntil() { return until; } } + public enum TrailingCommaManagementStrategy { + /** + * Do not manage trailing commas at all, only format what is already present. + */ + NONE, + /** + *

+ * Only add trailing commas when necessary, but do not remove them. + *

+ *

+ * Lists that cannot fit on one line will have trailing commas inserted. + * Trailing commas can to be used to "hint" ktfmt that the list should be broken to multiple lines + *

+ */ + ONLY_ADD, + /** + *

+ * Fully manage trailing commas, adding and removing them where necessary. + *

+ *

+ * Lists that cannot fit on one line will have trailing commas inserted. + * Lists that span multiple lines will have them removed. Manually inserted trailing commas + * cannot be used as a hint to force breaking lists to multiple lines. + *

+ */ + COMPLETE, + } + public static class KtfmtFormattingOptions implements Serializable { private static final long serialVersionUID = 1L; @@ -127,21 +161,21 @@ public static class KtfmtFormattingOptions implements Serializable { private Boolean removeUnusedImports = null; @Nullable - private Boolean manageTrailingCommas = null; + private TrailingCommaManagementStrategy trailingCommaManagementStrategy; - public KtfmtFormattingOptions() {} + public KtfmtFormattingOptions() { + } public KtfmtFormattingOptions( - @Nullable Integer maxWidth, - @Nullable Integer blockIndent, - @Nullable Integer continuationIndent, - @Nullable Boolean removeUnusedImports, - @Nullable Boolean manageTrailingCommas) { + @Nullable Integer maxWidth, + @Nullable Integer blockIndent, + @Nullable Integer continuationIndent, + @Nullable Boolean removeUnusedImports, + @Nullable Boolean manageTrailingCommas) { this.maxWidth = maxWidth; this.blockIndent = blockIndent; this.continuationIndent = continuationIndent; this.removeUnusedImports = removeUnusedImports; - this.manageTrailingCommas = manageTrailingCommas; } public void setMaxWidth(int maxWidth) { @@ -160,29 +194,35 @@ public void setRemoveUnusedImports(boolean removeUnusedImports) { this.removeUnusedImports = removeUnusedImports; } - public void setManageTrailingCommas(boolean manageTrailingCommas) { - this.manageTrailingCommas = manageTrailingCommas; + public void setTrailingCommaManagementStrategy(TrailingCommaManagementStrategy trailingCommaManagementStrategy) { + this.trailingCommaManagementStrategy = trailingCommaManagementStrategy; } } - /** Creates a step which formats everything - code, import order, and unused imports. */ + /** + * Creates a step which formats everything - code, import order, and unused imports. + */ public static FormatterStep create(Provisioner provisioner) { return create(defaultVersion(), provisioner); } - /** Creates a step which formats everything - code, import order, and unused imports. */ + /** + * Creates a step which formats everything - code, import order, and unused imports. + */ public static FormatterStep create(String version, Provisioner provisioner) { return create(version, provisioner, null, null); } - /** Creates a step which formats everything - code, import order, and unused imports. */ + /** + * Creates a step which formats everything - code, import order, and unused imports. + */ public static FormatterStep create(String version, Provisioner provisioner, @Nullable Style style, @Nullable KtfmtFormattingOptions options) { Objects.requireNonNull(version, "version"); Objects.requireNonNull(provisioner, "provisioner"); return FormatterStep.create(NAME, - new KtfmtStep(version, JarState.promise(() -> JarState.from(MAVEN_COORDINATE + version, provisioner)), style, options), - KtfmtStep::equalityState, - State::createFormat); + new KtfmtStep(version, JarState.promise(() -> JarState.from(MAVEN_COORDINATE + version, provisioner)), style, options), + KtfmtStep::equalityState, + State::createFormat); } public static String defaultVersion() { @@ -203,9 +243,9 @@ private static final class State implements Serializable { private final JarState jarState; State(String version, - JarState jarState, - @Nullable Style style, - @Nullable KtfmtFormattingOptions options) { + JarState jarState, + @Nullable Style style, + @Nullable KtfmtFormattingOptions options) { this.version = version; this.options = options; this.style = style; @@ -224,6 +264,7 @@ FormatterFunc createFormat() throws Exception { final Class formatterFuncClass = classLoader.loadClass("com.diffplug.spotless.glue.ktfmt.KtfmtFormatterFunc"); final Class ktfmtStyleClass = classLoader.loadClass("com.diffplug.spotless.glue.ktfmt.KtfmtStyle"); final Class ktfmtFormattingOptionsClass = classLoader.loadClass("com.diffplug.spotless.glue.ktfmt.KtfmtFormattingOptions"); + final Class ktfmtTrailingCommaManagmentStrategyClass = classLoader.loadClass("com.diffplug.spotless.glue.ktfmt.KtfmtTrailingCommaManagementStrategy"); if (style == null && options == null) { final Constructor constructor = formatterFuncClass.getConstructor(); @@ -237,9 +278,11 @@ FormatterFunc createFormat() throws Exception { } final Constructor optionsConstructor = ktfmtFormattingOptionsClass.getConstructor( - Integer.class, Integer.class, Integer.class, Boolean.class, Boolean.class); + Integer.class, Integer.class, Integer.class, Boolean.class, ktfmtTrailingCommaManagmentStrategyClass); + + // TODO: use Enum.valueOf like for ktfmt style for trailing comma management strategy value final Object ktfmtFormattingOptions = optionsConstructor.newInstance( - options.maxWidth, options.blockIndent, options.continuationIndent, options.removeUnusedImports, options.manageTrailingCommas); + options.maxWidth, options.blockIndent, options.continuationIndent, options.removeUnusedImports, options.trailingCommaManagementStrategy); if (style == null) { final Constructor constructor = formatterFuncClass.getConstructor(ktfmtFormattingOptionsClass); return (FormatterFunc) constructor.newInstance(ktfmtFormattingOptions); @@ -262,6 +305,12 @@ private void validateOptions() { throw new IllegalStateException("Ktfmt formatting option `removeUnusedImports` supported for version 0.17 and later"); } } + + if (BadSemver.version(version) < BadSemver.version(0, 57)) { + if (options != null && options.trailingCommaManagementStrategy == ONLY_ADD) { + throw new IllegalStateException("Value ONLY_ADD for Ktfmt formatting option `trailingCommaManagementStrategy` supported for version 0.57 and later"); + } + } } private void validateStyle() { @@ -346,35 +395,45 @@ private Object getCustomFormattingOptions(Class formatterClass) throws Except if (options != null) { if (BadSemver.version(version) < BadSemver.version(0, 17)) { formattingOptions = formattingOptions.getClass().getConstructor(int.class, int.class, int.class).newInstance( - /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), - /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), - /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions))); + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions))); } else if (BadSemver.version(version) < BadSemver.version(0, 19)) { formattingOptions = formattingOptions.getClass().getConstructor(int.class, int.class, int.class, boolean.class, boolean.class).newInstance( - /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), - /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), - /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), - /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), - /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions)); + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), + /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), + /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions)); } else if (BadSemver.version(version) < BadSemver.version(0, 47)) { Class styleClass = classLoader.loadClass(formattingOptionsClass.getName() + "$Style"); formattingOptions = formattingOptions.getClass().getConstructor(styleClass, int.class, int.class, int.class, boolean.class, boolean.class).newInstance( - /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), - /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), - /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), - /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), - /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), - /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions)); - } else { + /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), + /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), + /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions)); + } else if (BadSemver.version(version) < BadSemver.version(0, 57)) { Class styleClass = classLoader.loadClass(formattingOptionsClass.getName() + "$Style"); formattingOptions = formattingOptions.getClass().getConstructor(styleClass, int.class, int.class, int.class, boolean.class, boolean.class, boolean.class).newInstance( - /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), - /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), - /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), - /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), - /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), - /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions), - /* manageTrailingCommas */ Optional.ofNullable(options.manageTrailingCommas).orElse((Boolean) formattingOptionsClass.getMethod("getManageTrailingCommas").invoke(formattingOptions))); + /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), + /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), + /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions), + /* manageTrailingCommas = */ Optional.ofNullable(getManageTrailingCommasFrom(options.trailingCommaManagementStrategy)).orElse((Boolean) formattingOptionsClass.getMethod("getManageTrailingCommas").invoke(formattingOptions))); + } else { + Class styleClass = classLoader.loadClass(formattingOptionsClass.getName() + "$Style"); + formattingOptions = formattingOptions.getClass().getConstructor(styleClass, int.class, int.class, int.class, boolean.class, boolean.class, TrailingCommaManagementStrategy.class).newInstance( + /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), + /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), + /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions), + /* trailingCommaManagementStrategy */ Optional.ofNullable(options.trailingCommaManagementStrategy).orElse((TrailingCommaManagementStrategy) formattingOptionsClass.getMethod("getTrailingCommaManagementStrategy").invoke(formattingOptions))); } } @@ -422,5 +481,18 @@ private Class getFormattingOptionsClazz() throws Exception { } return formattingOptionsClazz; } + + private @Nullable Boolean getManageTrailingCommasFrom( + @Nullable TrailingCommaManagementStrategy trailingCommaManagementStrategy + ) { + if (trailingCommaManagementStrategy == null) { + return null; + } + + return switch (trailingCommaManagementStrategy) { + case NONE, ONLY_ADD -> false; + case COMPLETE -> true; + }; + } } } diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 31947a036d..903dbbdf47 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -515,7 +515,7 @@ spotless { it.setBlockIndent(4) it.setContinuationIndent(4) it.setRemoveUnusedImports(false) - it.setManageTrailingCommas(false) + it.setTrailingCommaManagementStrategy(TrailingCommaManagementStrategy.NONE) } } } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/KotlinExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/KotlinExtensionTest.java index 2132ac11e4..f986d83717 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/KotlinExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/KotlinExtensionTest.java @@ -47,6 +47,7 @@ void integrationDiktat() throws IOException { @Test void integrationKtfmtDropboxStyleWithPublicApi() throws IOException { setFile("build.gradle.kts").toLines( + "import com.diffplug.spotless.kotlin.KtfmtStep.TrailingCommaManagementStrategy", "plugins {", " id(\"org.jetbrains.kotlin.jvm\") version \"1.6.21\"", " id(\"com.diffplug.spotless\")", @@ -59,7 +60,7 @@ void integrationKtfmtDropboxStyleWithPublicApi() throws IOException { " it.setBlockIndent(4)", " it.setContinuationIndent(4)", " it.setRemoveUnusedImports(false)", - " it.setManageTrailingCommas(false)", + " it.setTrailingCommaManagementStrategy(TrailingCommaManagementStrategy.NONE)", " }", " }", "}"); diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java index 68d99c8186..2b7134690a 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java @@ -37,6 +37,7 @@ void testKtfmt() throws Exception { } @Test + // TODO void testContinuation() throws Exception { writePomWithKotlinSteps(""); @@ -73,6 +74,7 @@ void testKtfmtStyleWithMaxWidthOption() throws Exception { } @Test + // TODO void testKtfmtWithManageTrailingCommasOption() throws Exception { writePomWithKotlinSteps("0.49true"); diff --git a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java index 56687d0578..917c9b90b8 100644 --- a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java @@ -65,11 +65,15 @@ void dropboxStyle_0_50() throws Exception { @Test void behaviorWithTrailingCommas() throws Exception { KtfmtStep.KtfmtFormattingOptions options = new KtfmtStep.KtfmtFormattingOptions(); - options.setManageTrailingCommas(true); + options.setTrailingCommaManagementStrategy(KtfmtStep.TrailingCommaManagementStrategy.COMPLETE); FormatterStep step = KtfmtStep.create("0.49", TestProvisioner.mavenCentral(), KtfmtStep.Style.DROPBOX, options); StepHarness.forStep(step).testResource("kotlin/ktfmt/trailing-commas.dirty", "kotlin/ktfmt/trailing-commas.clean"); } + // TODO: test trailing comma only add + + // TODO: test before 0.57 + @Test void equality() throws Exception { new SerializableEqualityTester() { From 8cba0cc51b58a257e6f62601ff88cacfe0a3f07b Mon Sep 17 00:00:00 2001 From: Peter Laggner Date: Sun, 7 Sep 2025 00:33:21 +0200 Subject: [PATCH 02/10] chore: document PR changes in CHANGES.md files --- CHANGES.md | 2 ++ plugin-gradle/CHANGES.md | 3 +++ plugin-maven/CHANGES.md | 2 ++ 3 files changed, 7 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index dfc37968fc..a3366ca354 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Bump default `google-java-format` version to latest `1.24.0` -> `1.28.0`. ([#2345](https://github.com/diffplug/spotless/pull/2345)) * Bump default `ktlint` version to latest `1.5.0` -> `1.7.1`. ([#2555](https://github.com/diffplug/spotless/pull/2555)) * Bump default `jackson` version to latest `2.19.2` -> `2.20.0`. ([#2606](https://github.com/diffplug/spotless/pull/2606)) +* **BREAKING** Bump default `ktfmt` version to latest `0.53` -> `0.58` ([#2613](https://github.com/diffplug/spotless/pull/2613)) + * use `TrailingCommaManagementStrategy` enum instead of `manageTrailingCommas` boolean configuration option ## [3.3.1] - 2025-07-21 ### Fixed diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 98a465f59d..cb8f690dc0 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -10,6 +10,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Bump default `google-java-format` version to latest `1.24.0` -> `1.28.0`. ([#2345](https://github.com/diffplug/spotless/pull/2345)) * Bump default `ktlint` version to latest `1.5.0` -> `1.7.1`. ([#2555](https://github.com/diffplug/spotless/pull/2555)) * Bump default `jackson` version to latest `2.19.2` -> `2.20.0`. ([#2606](https://github.com/diffplug/spotless/pull/2606)) +* **BREAKING** Bump default `ktfmt` version to latest `0.53` -> `0.58` ([#2613](https://github.com/diffplug/spotless/pull/2613)) + * use `TrailingCommaManagementStrategy` enum instead of `manageTrailingCommas` boolean configuration option + ### Fixed * Respect system gitconfig when performing git operations ([#2404](https://github.com/diffplug/spotless/issues/2404)) diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index c58e31e0c2..25d1896a2c 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -10,6 +10,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Bump default `google-java-format` version to latest `1.24.0` -> `1.28.0`. ([#2345](https://github.com/diffplug/spotless/pull/2345)) * Bump default `ktlint` version to latest `1.5.0` -> `1.7.1`. ([#2555](https://github.com/diffplug/spotless/pull/2555)) * Bump default `jackson` version to latest `2.19.2` -> `2.20.0`. ([#2606](https://github.com/diffplug/spotless/pull/2606)) +* **BREAKING** Bump default `ktfmt` version to latest `0.53` -> `0.58` ([#2613](https://github.com/diffplug/spotless/pull/2613)) + * use `TrailingCommaManagementStrategy` enum instead of `manageTrailingCommas` boolean configuration option ## [2.46.1] - 2025-07-21 ### Fixed From 87158156eab4fdebc15487dc3f654d8fdc739f02 Mon Sep 17 00:00:00 2001 From: Peter Laggner Date: Sun, 7 Sep 2025 00:39:34 +0200 Subject: [PATCH 03/10] fix: add trailingCommaManagementStrategy support for maven plugin --- .../diffplug/spotless/kotlin/KtfmtStep.java | 26 +++++++++++-------- plugin-maven/README.md | 2 +- .../diffplug/spotless/maven/kotlin/Ktfmt.java | 5 ++-- .../spotless/maven/kotlin/KtfmtTest.java | 3 +-- .../resources/kotlin/ktfmt/continuation.clean | 4 ++- 5 files changed, 23 insertions(+), 17 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 5f0660f7b1..615fa5e93c 100644 --- a/lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java @@ -171,11 +171,12 @@ public KtfmtFormattingOptions( @Nullable Integer blockIndent, @Nullable Integer continuationIndent, @Nullable Boolean removeUnusedImports, - @Nullable Boolean manageTrailingCommas) { + @Nullable TrailingCommaManagementStrategy trailingCommaManagementStrategy) { this.maxWidth = maxWidth; this.blockIndent = blockIndent; this.continuationIndent = continuationIndent; this.removeUnusedImports = removeUnusedImports; + this.trailingCommaManagementStrategy = trailingCommaManagementStrategy; } public void setMaxWidth(int maxWidth) { @@ -280,9 +281,12 @@ FormatterFunc createFormat() throws Exception { final Constructor optionsConstructor = ktfmtFormattingOptionsClass.getConstructor( Integer.class, Integer.class, Integer.class, Boolean.class, ktfmtTrailingCommaManagmentStrategyClass); - // TODO: use Enum.valueOf like for ktfmt style for trailing comma management strategy value + final Object ktfmtTrailingCommaManagementStrategy = + options.trailingCommaManagementStrategy == null + ? null + : Enum.valueOf((Class) ktfmtTrailingCommaManagmentStrategyClass, options.trailingCommaManagementStrategy.name()); final Object ktfmtFormattingOptions = optionsConstructor.newInstance( - options.maxWidth, options.blockIndent, options.continuationIndent, options.removeUnusedImports, options.trailingCommaManagementStrategy); + options.maxWidth, options.blockIndent, options.continuationIndent, options.removeUnusedImports, ktfmtTrailingCommaManagementStrategy); if (style == null) { final Constructor constructor = formatterFuncClass.getConstructor(ktfmtFormattingOptionsClass); return (FormatterFunc) constructor.newInstance(ktfmtFormattingOptions); @@ -332,14 +336,14 @@ private void validateStyle() { */ private String getKtfmtStyleOption(Style style) { switch (style) { - case META: - return "META"; - case GOOGLE: - return "GOOGLE"; - case KOTLINLANG: - return "KOTLIN_LANG"; - default: - throw new IllegalStateException("Unsupported style: " + style); + case META: + return "META"; + case GOOGLE: + return "GOOGLE"; + case KOTLINLANG: + return "KOTLIN_LANG"; + default: + throw new IllegalStateException("Unsupported style: " + style); } } } diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 05903b7540..7efd7c3157 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -473,7 +473,7 @@ Groovy-Eclipse formatting errors/warnings lead per default to a build failure. T 4 8 false - true + COMPLETE ``` diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java index 4c5c4628d3..449859a9e2 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java @@ -21,6 +21,7 @@ import com.diffplug.spotless.kotlin.KtfmtStep; import com.diffplug.spotless.kotlin.KtfmtStep.KtfmtFormattingOptions; import com.diffplug.spotless.kotlin.KtfmtStep.Style; +import com.diffplug.spotless.kotlin.KtfmtStep.TrailingCommaManagementStrategy; import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; @@ -45,13 +46,13 @@ public class Ktfmt implements FormatterStepFactory { private Boolean removeUnusedImports; @Parameter - private Boolean manageTrailingCommas; + private TrailingCommaManagementStrategy trailingCommaManagementStrategy; @Override public FormatterStep newFormatterStep(FormatterStepConfig config) { String version = this.version != null ? this.version : KtfmtStep.defaultVersion(); Style style = this.style != null ? Style.valueOf(this.style) : null; - KtfmtFormattingOptions options = new KtfmtFormattingOptions(maxWidth, blockIndent, continuationIndent, removeUnusedImports, manageTrailingCommas); + KtfmtFormattingOptions options = new KtfmtFormattingOptions(maxWidth, blockIndent, continuationIndent, removeUnusedImports, trailingCommaManagementStrategy); return KtfmtStep.create(version, config.getProvisioner(), style, options); } } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java index 2b7134690a..1d1d4bd718 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java @@ -74,9 +74,8 @@ void testKtfmtStyleWithMaxWidthOption() throws Exception { } @Test - // TODO void testKtfmtWithManageTrailingCommasOption() throws Exception { - writePomWithKotlinSteps("0.49true"); + writePomWithKotlinSteps("0.49COMPLETE"); setFile("src/main/kotlin/main.kt").toResource("kotlin/ktfmt/trailing-commas.dirty"); mavenRunner().withArguments("spotless:apply").runNoError(); diff --git a/testlib/src/main/resources/kotlin/ktfmt/continuation.clean b/testlib/src/main/resources/kotlin/ktfmt/continuation.clean index 11677928fc..9bbb9a5d7b 100644 --- a/testlib/src/main/resources/kotlin/ktfmt/continuation.clean +++ b/testlib/src/main/resources/kotlin/ktfmt/continuation.clean @@ -1,6 +1,8 @@ fun myFunction() { val location = restTemplate.postForLocation( - "/v1/my-api", mapOf("name" to "some-name", "url" to "https://www.google.com")) + "/v1/my-api", + mapOf("name" to "some-name", "url" to "https://www.google.com"), + ) return location } From 464a584211d94972669c8395711046593f221776 Mon Sep 17 00:00:00 2001 From: Peter Laggner Date: Sun, 7 Sep 2025 00:56:08 +0200 Subject: [PATCH 04/10] test: trailing comma management strategy only add --- .../kotlin/ktfmt/trailing-commas-only-add.clean | 13 +++++++++++++ .../kotlin/ktfmt/trailing-commas-only-add.dirty | 8 ++++++++ .../com/diffplug/spotless/kotlin/KtfmtStepTest.java | 11 ++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 testlib/src/main/resources/kotlin/ktfmt/trailing-commas-only-add.clean create mode 100644 testlib/src/main/resources/kotlin/ktfmt/trailing-commas-only-add.dirty diff --git a/testlib/src/main/resources/kotlin/ktfmt/trailing-commas-only-add.clean b/testlib/src/main/resources/kotlin/ktfmt/trailing-commas-only-add.clean new file mode 100644 index 0000000000..7f10d0537c --- /dev/null +++ b/testlib/src/main/resources/kotlin/ktfmt/trailing-commas-only-add.clean @@ -0,0 +1,13 @@ +import a.* + +fun foo( + paramA: String, + paramB: Int, + anotherParamIsHere: Float, + myLongParamNameIsHere: CustomType, + lastParam: Boolean, +) = Unit + +fun bar( + myLongParamNameIsHereButDoesNotWrap: Int, +) = Unit diff --git a/testlib/src/main/resources/kotlin/ktfmt/trailing-commas-only-add.dirty b/testlib/src/main/resources/kotlin/ktfmt/trailing-commas-only-add.dirty new file mode 100644 index 0000000000..4767c419e8 --- /dev/null +++ b/testlib/src/main/resources/kotlin/ktfmt/trailing-commas-only-add.dirty @@ -0,0 +1,8 @@ +import a.* + +fun foo(paramA: String,paramB : Int , anotherParamIsHere: Float ,myLongParamNameIsHere: CustomType +,lastParam: Boolean ) = Unit + +fun bar( + myLongParamNameIsHereButDoesNotWrap: Int, +) = Unit diff --git a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java index 917c9b90b8..613b7bad7c 100644 --- a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java @@ -70,7 +70,16 @@ void behaviorWithTrailingCommas() throws Exception { StepHarness.forStep(step).testResource("kotlin/ktfmt/trailing-commas.dirty", "kotlin/ktfmt/trailing-commas.clean"); } - // TODO: test trailing comma only add + @Test + void behaviorWithTrailingCommaManagementStrategyOnlyAdd() { + KtfmtStep.KtfmtFormattingOptions options = new KtfmtStep.KtfmtFormattingOptions(); + options.setTrailingCommaManagementStrategy(KtfmtStep.TrailingCommaManagementStrategy.ONLY_ADD); + FormatterStep step = KtfmtStep.create("0.58", TestProvisioner.mavenCentral(), KtfmtStep.Style.KOTLINLANG, options); + StepHarness.forStep(step).testResource( + "kotlin/ktfmt/trailing-commas-only-add.dirty", + "kotlin/ktfmt/trailing-commas-only-add.clean" + ); + } // TODO: test before 0.57 From 22e4d0e80288877c7afabf747e3f49a001215603 Mon Sep 17 00:00:00 2001 From: Peter Laggner Date: Sun, 7 Sep 2025 01:01:00 +0200 Subject: [PATCH 05/10] chore: remove TODO --- .../test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java index 1d1d4bd718..2e69285363 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java @@ -37,7 +37,6 @@ void testKtfmt() throws Exception { } @Test - // TODO void testContinuation() throws Exception { writePomWithKotlinSteps(""); From 50809bec27af9719f1d86156bd36c1cc268e8a5e Mon Sep 17 00:00:00 2001 From: Peter Laggner Date: Sun, 7 Sep 2025 01:05:46 +0200 Subject: [PATCH 06/10] fix: format --- .../glue/ktfmt/KtfmtFormatterFunc.java | 5 +- .../glue/ktfmt/KtfmtFormattingOptions.java | 27 ++-- .../KtfmtTrailingCommaManagementStrategy.java | 19 ++- .../diffplug/spotless/kotlin/KtfmtStep.java | 143 ++++++++---------- .../diffplug/spotless/maven/kotlin/Ktfmt.java | 2 +- .../spotless/maven/kotlin/KtfmtTest.java | 2 +- 6 files changed, 96 insertions(+), 102 deletions(-) diff --git a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormatterFunc.java b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormatterFunc.java index c911c759b0..4b8308e47c 100644 --- a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormatterFunc.java +++ b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormatterFunc.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 DiffPlug + * Copyright 2022-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,8 +28,7 @@ public final class KtfmtFormatterFunc implements FormatterFunc { @Nonnull private final KtfmtStyle style; - @Nullable - private final KtfmtFormattingOptions ktfmtFormattingOptions; + @Nullable private final KtfmtFormattingOptions ktfmtFormattingOptions; public KtfmtFormatterFunc() { this(KtfmtStyle.META, null); diff --git a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormattingOptions.java b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormattingOptions.java index c25e74fcb7..b110f2bbde 100644 --- a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormattingOptions.java +++ b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtFormattingOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 DiffPlug + * Copyright 2022-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,27 +22,22 @@ public final class KtfmtFormattingOptions { - @Nullable - private Integer maxWidth; + @Nullable private Integer maxWidth; - @Nullable - private Integer blockIndent; + @Nullable private Integer blockIndent; - @Nullable - private Integer continuationIndent; + @Nullable private Integer continuationIndent; - @Nullable - private Boolean removeUnusedImports; + @Nullable private Boolean removeUnusedImports; - @Nullable - private KtfmtTrailingCommaManagementStrategy trailingCommaManagementStrategy; + @Nullable private KtfmtTrailingCommaManagementStrategy trailingCommaManagementStrategy; public KtfmtFormattingOptions( - @Nullable Integer maxWidth, - @Nullable Integer blockIndent, - @Nullable Integer continuationIndent, - @Nullable Boolean removeUnusedImports, - @Nullable KtfmtTrailingCommaManagementStrategy trailingCommaManagementStrategy) { + @Nullable Integer maxWidth, + @Nullable Integer blockIndent, + @Nullable Integer continuationIndent, + @Nullable Boolean removeUnusedImports, + @Nullable KtfmtTrailingCommaManagementStrategy trailingCommaManagementStrategy) { this.maxWidth = maxWidth; this.blockIndent = blockIndent; this.continuationIndent = continuationIndent; diff --git a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtTrailingCommaManagementStrategy.java b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtTrailingCommaManagementStrategy.java index 3c7b017ad9..f9ca437eee 100644 --- a/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtTrailingCommaManagementStrategy.java +++ b/lib/src/ktfmt/java/com/diffplug/spotless/glue/ktfmt/KtfmtTrailingCommaManagementStrategy.java @@ -1,11 +1,24 @@ +/* + * Copyright 2025 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.glue.ktfmt; import com.facebook.ktfmt.format.TrailingCommaManagementStrategy; public enum KtfmtTrailingCommaManagementStrategy { - NONE, - ONLY_ADD, - COMPLETE; + NONE, ONLY_ADD, COMPLETE; public TrailingCommaManagementStrategy toFormatterTrailingCommaManagementStrategy() { return switch (this) { 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 615fa5e93c..b30044ff2c 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-2024 DiffPlug + * Copyright 2016-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ import static com.diffplug.spotless.kotlin.KtfmtStep.Style.DEFAULT; import static com.diffplug.spotless.kotlin.KtfmtStep.Style.DROPBOX; import static com.diffplug.spotless.kotlin.KtfmtStep.Style.META; - import static com.diffplug.spotless.kotlin.KtfmtStep.TrailingCommaManagementStrategy.ONLY_ADD; import java.io.Serializable; @@ -49,19 +48,17 @@ public class KtfmtStep implements Serializable { /** * 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; + @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) { + JarState.Promised jarState, + @Nullable Style style, + @Nullable KtfmtFormattingOptions options) { this.version = Objects.requireNonNull(version, "version"); this.style = style; this.options = options; @@ -110,8 +107,7 @@ String getSince() { /** * Last version (inclusive) that supports this style */ - @Nullable - String getUntil() { + @Nullable String getUntil() { return until; } } @@ -148,30 +144,24 @@ public static class KtfmtFormattingOptions implements Serializable { private static final long serialVersionUID = 1L; - @Nullable - private Integer maxWidth = null; + @Nullable private Integer maxWidth = null; - @Nullable - private Integer blockIndent = null; + @Nullable private Integer blockIndent = null; - @Nullable - private Integer continuationIndent = null; + @Nullable private Integer continuationIndent = null; - @Nullable - private Boolean removeUnusedImports = null; + @Nullable private Boolean removeUnusedImports = null; - @Nullable - private TrailingCommaManagementStrategy trailingCommaManagementStrategy; + @Nullable private TrailingCommaManagementStrategy trailingCommaManagementStrategy; - public KtfmtFormattingOptions() { - } + public KtfmtFormattingOptions() {} public KtfmtFormattingOptions( - @Nullable Integer maxWidth, - @Nullable Integer blockIndent, - @Nullable Integer continuationIndent, - @Nullable Boolean removeUnusedImports, - @Nullable TrailingCommaManagementStrategy trailingCommaManagementStrategy) { + @Nullable Integer maxWidth, + @Nullable Integer blockIndent, + @Nullable Integer continuationIndent, + @Nullable Boolean removeUnusedImports, + @Nullable TrailingCommaManagementStrategy trailingCommaManagementStrategy) { this.maxWidth = maxWidth; this.blockIndent = blockIndent; this.continuationIndent = continuationIndent; @@ -221,9 +211,9 @@ public static FormatterStep create(String version, Provisioner provisioner, @Nul Objects.requireNonNull(version, "version"); Objects.requireNonNull(provisioner, "provisioner"); return FormatterStep.create(NAME, - new KtfmtStep(version, JarState.promise(() -> JarState.from(MAVEN_COORDINATE + version, provisioner)), style, options), - KtfmtStep::equalityState, - State::createFormat); + new KtfmtStep(version, JarState.promise(() -> JarState.from(MAVEN_COORDINATE + version, provisioner)), style, options), + KtfmtStep::equalityState, + State::createFormat); } public static String defaultVersion() { @@ -237,16 +227,14 @@ private State equalityState() { private static final class State implements Serializable { private static final long serialVersionUID = 1L; private final String version; - @Nullable - private final Style style; - @Nullable - private final KtfmtFormattingOptions options; + @Nullable private final Style style; + @Nullable private final KtfmtFormattingOptions options; private final JarState jarState; State(String version, - JarState jarState, - @Nullable Style style, - @Nullable KtfmtFormattingOptions options) { + JarState jarState, + @Nullable Style style, + @Nullable KtfmtFormattingOptions options) { this.version = version; this.options = options; this.style = style; @@ -279,14 +267,13 @@ FormatterFunc createFormat() throws Exception { } final Constructor optionsConstructor = ktfmtFormattingOptionsClass.getConstructor( - Integer.class, Integer.class, Integer.class, Boolean.class, ktfmtTrailingCommaManagmentStrategyClass); + Integer.class, Integer.class, Integer.class, Boolean.class, ktfmtTrailingCommaManagmentStrategyClass); - final Object ktfmtTrailingCommaManagementStrategy = - options.trailingCommaManagementStrategy == null + final Object ktfmtTrailingCommaManagementStrategy = options.trailingCommaManagementStrategy == null ? null : Enum.valueOf((Class) ktfmtTrailingCommaManagmentStrategyClass, options.trailingCommaManagementStrategy.name()); final Object ktfmtFormattingOptions = optionsConstructor.newInstance( - options.maxWidth, options.blockIndent, options.continuationIndent, options.removeUnusedImports, ktfmtTrailingCommaManagementStrategy); + options.maxWidth, options.blockIndent, options.continuationIndent, options.removeUnusedImports, ktfmtTrailingCommaManagementStrategy); if (style == null) { final Constructor constructor = formatterFuncClass.getConstructor(ktfmtFormattingOptionsClass); return (FormatterFunc) constructor.newInstance(ktfmtFormattingOptions); @@ -336,14 +323,14 @@ private void validateStyle() { */ private String getKtfmtStyleOption(Style style) { switch (style) { - case META: - return "META"; - case GOOGLE: - return "GOOGLE"; - case KOTLINLANG: - return "KOTLIN_LANG"; - default: - throw new IllegalStateException("Unsupported style: " + style); + case META: + return "META"; + case GOOGLE: + return "GOOGLE"; + case KOTLINLANG: + return "KOTLIN_LANG"; + default: + throw new IllegalStateException("Unsupported style: " + style); } } } @@ -399,45 +386,45 @@ private Object getCustomFormattingOptions(Class formatterClass) throws Except if (options != null) { if (BadSemver.version(version) < BadSemver.version(0, 17)) { formattingOptions = formattingOptions.getClass().getConstructor(int.class, int.class, int.class).newInstance( - /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), - /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), - /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions))); + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions))); } else if (BadSemver.version(version) < BadSemver.version(0, 19)) { formattingOptions = formattingOptions.getClass().getConstructor(int.class, int.class, int.class, boolean.class, boolean.class).newInstance( - /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), - /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), - /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), - /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), - /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions)); + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), + /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), + /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions)); } else if (BadSemver.version(version) < BadSemver.version(0, 47)) { Class styleClass = classLoader.loadClass(formattingOptionsClass.getName() + "$Style"); formattingOptions = formattingOptions.getClass().getConstructor(styleClass, int.class, int.class, int.class, boolean.class, boolean.class).newInstance( - /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), - /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), - /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), - /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), - /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), - /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions)); + /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), + /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), + /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions)); } else if (BadSemver.version(version) < BadSemver.version(0, 57)) { Class styleClass = classLoader.loadClass(formattingOptionsClass.getName() + "$Style"); formattingOptions = formattingOptions.getClass().getConstructor(styleClass, int.class, int.class, int.class, boolean.class, boolean.class, boolean.class).newInstance( - /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), - /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), - /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), - /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), - /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), - /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions), - /* manageTrailingCommas = */ Optional.ofNullable(getManageTrailingCommasFrom(options.trailingCommaManagementStrategy)).orElse((Boolean) formattingOptionsClass.getMethod("getManageTrailingCommas").invoke(formattingOptions))); + /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), + /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), + /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions), + /* manageTrailingCommas = */ Optional.ofNullable(getManageTrailingCommasFrom(options.trailingCommaManagementStrategy)).orElse((Boolean) formattingOptionsClass.getMethod("getManageTrailingCommas").invoke(formattingOptions))); } else { Class styleClass = classLoader.loadClass(formattingOptionsClass.getName() + "$Style"); formattingOptions = formattingOptions.getClass().getConstructor(styleClass, int.class, int.class, int.class, boolean.class, boolean.class, TrailingCommaManagementStrategy.class).newInstance( - /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), - /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), - /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), - /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), - /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), - /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions), - /* trailingCommaManagementStrategy */ Optional.ofNullable(options.trailingCommaManagementStrategy).orElse((TrailingCommaManagementStrategy) formattingOptionsClass.getMethod("getTrailingCommaManagementStrategy").invoke(formattingOptions))); + /* style = */ formattingOptionsClass.getMethod("getStyle").invoke(formattingOptions), + /* maxWidth = */ Optional.ofNullable(options.maxWidth).orElse((Integer) formattingOptionsClass.getMethod("getMaxWidth").invoke(formattingOptions)), + /* blockIndent = */ Optional.ofNullable(options.blockIndent).orElse((Integer) formattingOptionsClass.getMethod("getBlockIndent").invoke(formattingOptions)), + /* continuationIndent = */ Optional.ofNullable(options.continuationIndent).orElse((Integer) formattingOptionsClass.getMethod("getContinuationIndent").invoke(formattingOptions)), + /* removeUnusedImports = */ Optional.ofNullable(options.removeUnusedImports).orElse((Boolean) formattingOptionsClass.getMethod("getRemoveUnusedImports").invoke(formattingOptions)), + /* debuggingPrintOpsAfterFormatting = */ (Boolean) formattingOptionsClass.getMethod("getDebuggingPrintOpsAfterFormatting").invoke(formattingOptions), + /* trailingCommaManagementStrategy */ Optional.ofNullable(options.trailingCommaManagementStrategy).orElse((TrailingCommaManagementStrategy) formattingOptionsClass.getMethod("getTrailingCommaManagementStrategy").invoke(formattingOptions))); } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java index 449859a9e2..12fd4090c9 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 DiffPlug + * Copyright 2016-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java index 2e69285363..82aee91906 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 DiffPlug + * Copyright 2016-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 1e7fa4ad376786eea75f6d9420e3050cc676a422 Mon Sep 17 00:00:00 2001 From: Peter Laggner Date: Mon, 15 Sep 2025 14:16:35 +0200 Subject: [PATCH 07/10] fix: format in testlib --- .../java/com/diffplug/spotless/kotlin/KtfmtStepTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java index 613b7bad7c..55c7adef0a 100644 --- a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 DiffPlug + * Copyright 2016-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,9 +76,8 @@ void behaviorWithTrailingCommaManagementStrategyOnlyAdd() { options.setTrailingCommaManagementStrategy(KtfmtStep.TrailingCommaManagementStrategy.ONLY_ADD); FormatterStep step = KtfmtStep.create("0.58", TestProvisioner.mavenCentral(), KtfmtStep.Style.KOTLINLANG, options); StepHarness.forStep(step).testResource( - "kotlin/ktfmt/trailing-commas-only-add.dirty", - "kotlin/ktfmt/trailing-commas-only-add.clean" - ); + "kotlin/ktfmt/trailing-commas-only-add.dirty", + "kotlin/ktfmt/trailing-commas-only-add.clean"); } // TODO: test before 0.57 From 04ccdbfc11b64b0ea90cd914ddfed567a2be6f67 Mon Sep 17 00:00:00 2001 From: Peter Laggner Date: Wed, 17 Sep 2025 17:56:17 +0200 Subject: [PATCH 08/10] test: ONLY_ADD comma management strategy is only applicable from 0.57 --- .../com/diffplug/spotless/kotlin/KtfmtStepTest.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java index 55c7adef0a..73fcb8bd4f 100644 --- a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java @@ -15,6 +15,8 @@ */ package com.diffplug.spotless.kotlin; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import org.junit.jupiter.api.Test; import com.diffplug.spotless.*; @@ -80,7 +82,16 @@ void behaviorWithTrailingCommaManagementStrategyOnlyAdd() { "kotlin/ktfmt/trailing-commas-only-add.clean"); } - // TODO: test before 0.57 + @Test + void trailingCommaManagementStrategyOnlyAddUnsupportedBefore_0_57() { + KtfmtStep.KtfmtFormattingOptions options = new KtfmtStep.KtfmtFormattingOptions(); + options.setTrailingCommaManagementStrategy(KtfmtStep.TrailingCommaManagementStrategy.ONLY_ADD); + var step = KtfmtStep.create("0.56", TestProvisioner.mavenCentral(), KtfmtStep.Style.KOTLINLANG, options); + + assertThatThrownBy(() -> StepHarness.forStep(step)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("ONLY_ADD"); + } @Test void equality() throws Exception { From 47017acd48563151370adc91e37ba035504cc699 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 22 Sep 2025 23:01:02 -0700 Subject: [PATCH 09/10] spotlessApply --- .../test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java index 73fcb8bd4f..49f9a5e884 100644 --- a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtfmtStepTest.java @@ -89,8 +89,8 @@ void trailingCommaManagementStrategyOnlyAddUnsupportedBefore_0_57() { var step = KtfmtStep.create("0.56", TestProvisioner.mavenCentral(), KtfmtStep.Style.KOTLINLANG, options); assertThatThrownBy(() -> StepHarness.forStep(step)) - .isInstanceOf(IllegalStateException.class) - .hasMessageContaining("ONLY_ADD"); + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("ONLY_ADD"); } @Test From a50c90c9f53fe7ae0078f178add08f0fded58a62 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 22 Sep 2025 23:05:31 -0700 Subject: [PATCH 10/10] Fix KtfmtTest, no reason for it to be so old. --- .../test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java index 82aee91906..5869422995 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtfmtTest.java @@ -65,7 +65,7 @@ void testKtfmtWithMaxWidthOption() throws Exception { @Test void testKtfmtStyleWithMaxWidthOption() throws Exception { - writePomWithKotlinSteps("0.17120"); + writePomWithKotlinSteps("0.50120"); setFile("src/main/kotlin/main.kt").toResource("kotlin/ktfmt/max-width.dirty"); mavenRunner().withArguments("spotless:apply").runNoError();