From 67978ab1cbe345e71e4cea30ea3aa04c0f0330af Mon Sep 17 00:00:00 2001 From: Mitchell Skaggs Date: Tue, 28 Jun 2022 21:44:32 -0500 Subject: [PATCH] Update KtLint min version to 0.46.0 and default version to 0.46.1 Closes #1239 --- CHANGES.md | 3 + lib/build.gradle | 2 +- .../glue/ktlint/KtlintFormatterFunc.java | 44 ++++------ .../diffplug/spotless/kotlin/KtLintStep.java | 86 ++----------------- plugin-gradle/CHANGES.md | 3 + plugin-maven/CHANGES.md | 3 + .../spotless/kotlin/KtLintStepTest.java | 39 +-------- 7 files changed, 37 insertions(+), 143 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8e0d2c74d5..830d57d1a4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * Support for `MAC_CLASSIC` (`\r`) line ending ([#1243](https://github.com/diffplug/spotless/pull/1243) fixes [#1196](https://github.com/diffplug/spotless/issues/1196)) +### Changes +* Bump default `ktlint` version to latest `0.45.2` -> `0.46.1` [#1239](https://github.com/diffplug/spotless/issues/1239) + * Note that we now require `ktlint >= 0.46.0` due to frequent compatibility breakages ## [2.26.2] - 2022-06-11 ### Fixed diff --git a/lib/build.gradle b/lib/build.gradle index 2eb0f3e0e5..34b25d94a7 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -45,7 +45,7 @@ dependencies { } } - String VER_KTLINT='0.45.2' + String VER_KTLINT='0.46.1' ktlintCompileOnly "com.pinterest:ktlint:$VER_KTLINT" ktlintCompileOnly "com.pinterest.ktlint:ktlint-core:$VER_KTLINT" ktlintCompileOnly "com.pinterest.ktlint:ktlint-ruleset-experimental:$VER_KTLINT" diff --git a/lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java b/lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java index 1cd79a6ba9..da3e3ae475 100644 --- a/lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java +++ b/lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java @@ -24,6 +24,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jetbrains.annotations.NotNull; + import com.pinterest.ktlint.core.KtLint; import com.pinterest.ktlint.core.KtLint.ExperimentalParams; import com.pinterest.ktlint.core.LintError; @@ -46,6 +48,7 @@ public class KtlintFormatterFunc implements FormatterFunc.NeedsFile { private final Map userData; private final Function2 formatterCallback; private final boolean isScript; + @NotNull private final EditorConfigOverride editorConfigOverride; /** @@ -64,7 +67,7 @@ public KtlintFormatterFunc(boolean isScript, boolean useExperimental, Map edit // Create a mapping of properties to their names based on rule properties and default properties Map> supportedProperties = Stream - .concat(ruleProperties, DefaultEditorConfigProperties.INSTANCE.getDefaultEditorConfigProperties().stream()) + .concat(ruleProperties, DefaultEditorConfigProperties.INSTANCE.getEditorConfigProperties().stream()) .distinct() .collect(Collectors.toMap(property -> property.getType().getName(), property -> property)); @@ -116,31 +119,16 @@ public Unit invoke(LintError lint, Boolean corrected) { @Override public String applyWithFile(String unix, File file) throws Exception { - - if (editorConfigOverride != null) { - // Use ExperimentalParams with EditorConfigOverride which requires KtLint 0.45.2 - return KtLint.INSTANCE.format(new ExperimentalParams( - file.getName(), - unix, - rulesets, - userData, - formatterCallback, - isScript, - null, - false, - editorConfigOverride, - false)); - } else { - // Use Params for backward compatibility - return KtLint.INSTANCE.format(new KtLint.Params( - file.getName(), - unix, - rulesets, - userData, - formatterCallback, - isScript, - null, - false)); - } + return KtLint.INSTANCE.format(new ExperimentalParams( + file.getName(), + unix, + rulesets, + userData, + formatterCallback, + isScript, + null, + false, + editorConfigOverride, + false)); } } 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 d58331ec1b..f57ef1e997 100644 --- a/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java +++ b/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java @@ -18,10 +18,6 @@ import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; import java.util.Collections; import java.util.Map; import java.util.Objects; @@ -31,18 +27,15 @@ import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; -import com.diffplug.spotless.ThrowingEx; /** Wraps up ktlint as a FormatterStep. */ public class KtLintStep { // prevent direct instantiation private KtLintStep() {} - private static final String DEFAULT_VERSION = "0.45.2"; + private static final String DEFAULT_VERSION = "0.46.1"; static final String NAME = "ktlint"; - static final String PACKAGE_PRE_0_32 = "com.github.shyiko"; static final String PACKAGE = "com.pinterest"; - static final String MAVEN_COORDINATE_PRE_0_32 = PACKAGE_PRE_0_32 + ":ktlint:"; static final String MAVEN_COORDINATE = PACKAGE + ":ktlint:"; public static FormatterStep create(Provisioner provisioner) { @@ -85,95 +78,30 @@ static final class State implements Serializable { /** Are the files being linted Kotlin script files. */ private final boolean isScript; - private final String pkg; /** The jar that contains the formatter. */ final JarState jarState; private final boolean useExperimental; private final TreeMap userData; private final TreeMap editorConfigOverride; - private final boolean useParams; State(String version, Provisioner provisioner, boolean isScript, boolean useExperimental, Map userData, Map editorConfigOverride) throws IOException { - if (!editorConfigOverride.isEmpty() && - BadSemver.version(version) < BadSemver.version(0, 45, 2)) { - throw new IllegalStateException("KtLint editorConfigOverride supported for version 0.45.2 and later"); + if (BadSemver.version(version) < BadSemver.version(0, 46, 0)) { + throw new IllegalStateException("KtLint versions < 0.46.0 not supported!"); } this.useExperimental = useExperimental; this.userData = new TreeMap<>(userData); this.editorConfigOverride = new TreeMap<>(editorConfigOverride); - String coordinate; - if (BadSemver.version(version) < BadSemver.version(0, 32)) { - coordinate = MAVEN_COORDINATE_PRE_0_32; - this.pkg = PACKAGE_PRE_0_32; - } else { - coordinate = MAVEN_COORDINATE; - this.pkg = PACKAGE; - } - this.useParams = BadSemver.version(version) >= BadSemver.version(0, 34); - this.jarState = JarState.from(coordinate + version, provisioner); + this.jarState = JarState.from(MAVEN_COORDINATE + version, provisioner); this.isScript = isScript; } FormatterFunc createFormat() throws Exception { - if (useParams) { - Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.ktlint.KtlintFormatterFunc"); - Constructor constructor = formatterFunc.getConstructor(boolean.class, boolean.class, Map.class, Map.class); - return (FormatterFunc.NeedsFile) constructor.newInstance(isScript, useExperimental, userData, editorConfigOverride); - } - - ClassLoader classLoader = jarState.getClassLoader(); - // String KtLint::format(String input, Iterable rules, Function2 errorCallback) - - ArrayList ruleSets = new ArrayList<>(); - - // first, we get the standard rules - Class standardRuleSetProviderClass = classLoader.loadClass(pkg + ".ktlint.ruleset.standard.StandardRuleSetProvider"); - Object standardRuleSet = standardRuleSetProviderClass.getMethod("get").invoke(standardRuleSetProviderClass.newInstance()); - ruleSets.add(standardRuleSet); - - // second, we get the experimental rules if desired - if (useExperimental) { - Class experimentalRuleSetProviderClass = classLoader.loadClass(pkg + ".ktlint.ruleset.experimental.ExperimentalRuleSetProvider"); - Object experimentalRuleSet = experimentalRuleSetProviderClass.getMethod("get").invoke(experimentalRuleSetProviderClass.newInstance()); - ruleSets.add(experimentalRuleSet); - } - - // next, we create an error callback which throws an assertion error when the format is bad - Class function2Interface = classLoader.loadClass("kotlin.jvm.functions.Function2"); - Class lintErrorClass = classLoader.loadClass(pkg + ".ktlint.core.LintError"); - Method detailGetter = lintErrorClass.getMethod("getDetail"); - Method lineGetter = lintErrorClass.getMethod("getLine"); - Method colGetter = lintErrorClass.getMethod("getCol"); - Object formatterCallback = Proxy.newProxyInstance(classLoader, new Class[]{function2Interface}, - (proxy, method, args) -> { - Object lintError = args[0]; //ktlint.core.LintError - boolean corrected = (Boolean) args[1]; - if (!corrected) { - String detail = (String) detailGetter.invoke(lintError); - int line = (Integer) lineGetter.invoke(lintError); - int col = (Integer) colGetter.invoke(lintError); - throw new AssertionError("Error on line: " + line + ", column: " + col + "\n" + detail); - } - return null; - }); - - // grab the KtLint singleton - Class ktlintClass = classLoader.loadClass(pkg + ".ktlint.core.KtLint"); - Object ktlint = ktlintClass.getDeclaredField("INSTANCE").get(null); - - // and its format method - String formatterMethodName = isScript ? "formatScript" : "format"; - Method formatterMethod = ktlintClass.getMethod(formatterMethodName, String.class, Iterable.class, Map.class, function2Interface); - return input -> { - try { - return (String) formatterMethod.invoke(ktlint, input, ruleSets, userData, formatterCallback); - } catch (InvocationTargetException e) { - throw ThrowingEx.unwrapCause(e); - } - }; + Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.ktlint.KtlintFormatterFunc"); + Constructor constructor = formatterFunc.getConstructor(boolean.class, boolean.class, Map.class, Map.class); + return (FormatterFunc.NeedsFile) constructor.newInstance(isScript, useExperimental, userData, editorConfigOverride); } } } diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 178b8ec39b..77d94486bb 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -5,6 +5,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * Support for `MAC_CLASSIC` (`\r`) line ending ([#1243](https://github.com/diffplug/spotless/pull/1243) fixes [#1196](https://github.com/diffplug/spotless/issues/1196)) +### Changes +* Bump default `ktlint` version to latest `0.45.2` -> `0.46.1` [#1239](https://github.com/diffplug/spotless/issues/1239) + * Note that we now require `ktlint >= 0.46.0` due to frequent compatibility breakages ## [6.7.2] - 2022-06-11 ### Fixed diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index f6c5bcc84e..adefaacb5e 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -5,6 +5,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * Support for `MAC_CLASSIC` (`\r`) line ending ([#1243](https://github.com/diffplug/spotless/pull/1243) fixes [#1196](https://github.com/diffplug/spotless/issues/1196)) +### Changes +* Bump default `ktlint` version to latest `0.45.2` -> `0.46.1` [#1239](https://github.com/diffplug/spotless/issues/1239) + * Note that we now require `ktlint >= 0.46.0` due to frequent compatibility breakages ## [2.22.8] - 2022-06-11 ### Fixed diff --git a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java index af61ac4cd0..388fa57e74 100644 --- a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java @@ -42,8 +42,8 @@ void behavior() throws Exception { } @Test - void worksShyiko() throws Exception { - FormatterStep step = KtLintStep.create("0.31.0", TestProvisioner.mavenCentral()); + void worksPre0_46_1() throws Exception { + FormatterStep step = KtLintStep.create("0.46.0", TestProvisioner.mavenCentral()); StepHarness.forStep(step) .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic.clean") .testResourceException("kotlin/ktlint/unsolvable.dirty", assertion -> { @@ -53,48 +53,17 @@ void worksShyiko() throws Exception { }); } - // Regression test to ensure it works on the version it switched to Pinterest (version 0.32.0) - // but before 0.34. - // https://github.com/diffplug/spotless/issues/419 - @Test - void worksPinterestAndPre034() throws Exception { - FormatterStep step = KtLintStep.create("0.32.0", TestProvisioner.mavenCentral()); - StepHarness.forStep(step) - .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic.clean") - .testResourceException("kotlin/ktlint/unsolvable.dirty", assertion -> { - assertion.isInstanceOf(AssertionError.class); - assertion.hasMessage("Error on line: 1, column: 1\n" + - "Wildcard import"); - }); - } - - // Regression test to handle alpha and 1.x version numbers - // https://github.com/diffplug/spotless/issues/668 - @Test - void worksAlpha1() throws Exception { - FormatterStep step = KtLintStep.create("0.38.0-alpha01", TestProvisioner.mavenCentral()); - StepHarness.forStep(step) - .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic.clean"); - } - - @Test - void worksPre0_45_2() throws Exception { - FormatterStep step = KtLintStep.create("0.45.1", TestProvisioner.mavenCentral()); - StepHarness.forStep(step) - .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic.clean"); - } - @Test void equality() throws Exception { new SerializableEqualityTester() { - String version = "0.32.0"; + String version = "0.46.0"; @Override protected void setupTest(API api) { // same version == same api.areDifferentThan(); // change the version, and it's different - version = "0.38.0-alpha01"; + version = "0.46.1"; api.areDifferentThan(); }