Skip to content

Commit aa9bb11

Browse files
authored
Update ktlint to 0.46.1 and remove support for older versions (#1250)
2 parents d951b89 + 4befeaf commit aa9bb11

File tree

14 files changed

+66
-346
lines changed

14 files changed

+66
-346
lines changed

CHANGES.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
1212
## [Unreleased]
1313
### Added
1414
* Support for `MAC_CLASSIC` (`\r`) line ending ([#1243](https://github.com/diffplug/spotless/pull/1243) fixes [#1196](https://github.com/diffplug/spotless/issues/1196))
15-
### Changed
16-
* Minimum required `diktat` version bumped to `1.2.0` ([#1246](https://github.com/diffplug/spotless/pull/1246))
17-
* Default bumped from `1.1.0` -> `1.2.0`
15+
### Changes
16+
* Bump default `ktlint` version to latest `0.45.2` -> `0.46.1` ([#1239](https://github.com/diffplug/spotless/issues/1239))
17+
* Minimum supported version also bumped to `0.46.0` (we have abandoned strong backward compatibility for `ktlint`, from here on out Spotless will only support the most-recent breaking change).
18+
* Bump default `diktat` version to latest `1.1.0` -> `1.2.0` ([#1246](https://github.com/diffplug/spotless/pull/1246))
19+
* Minimum supported version also bumped to `1.2.0` (diktat is based on ktlint and has the same backward compatibility issues).
1820

1921
## [2.26.2] - 2022-06-11
2022
### Fixed

lib/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ dependencies {
4545
}
4646
}
4747

48-
String VER_KTLINT='0.45.2'
48+
String VER_KTLINT='0.46.1'
4949
ktlintCompileOnly "com.pinterest:ktlint:$VER_KTLINT"
5050
ktlintCompileOnly "com.pinterest.ktlint:ktlint-core:$VER_KTLINT"
5151
ktlintCompileOnly "com.pinterest.ktlint:ktlint-ruleset-experimental:$VER_KTLINT"

lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import java.util.stream.Collectors;
2525
import java.util.stream.Stream;
2626

27+
import org.jetbrains.annotations.NotNull;
28+
2729
import com.pinterest.ktlint.core.KtLint;
2830
import com.pinterest.ktlint.core.KtLint.ExperimentalParams;
2931
import com.pinterest.ktlint.core.LintError;
@@ -46,6 +48,7 @@ public class KtlintFormatterFunc implements FormatterFunc.NeedsFile {
4648
private final Map<String, String> userData;
4749
private final Function2<? super LintError, ? super Boolean, Unit> formatterCallback;
4850
private final boolean isScript;
51+
@NotNull
4952
private final EditorConfigOverride editorConfigOverride;
5053

5154
/**
@@ -64,7 +67,7 @@ public KtlintFormatterFunc(boolean isScript, boolean useExperimental, Map<String
6467
this.isScript = isScript;
6568

6669
if (editorConfigOverrideMap.isEmpty()) {
67-
this.editorConfigOverride = null;
70+
this.editorConfigOverride = EditorConfigOverride.Companion.getEmptyEditorConfigOverride();
6871
} else {
6972
this.editorConfigOverride = createEditorConfigOverride(editorConfigOverrideMap);
7073
}
@@ -83,7 +86,7 @@ private EditorConfigOverride createEditorConfigOverride(Map<String, Object> edit
8386

8487
// Create a mapping of properties to their names based on rule properties and default properties
8588
Map<String, UsesEditorConfigProperties.EditorConfigProperty<?>> supportedProperties = Stream
86-
.concat(ruleProperties, DefaultEditorConfigProperties.INSTANCE.getDefaultEditorConfigProperties().stream())
89+
.concat(ruleProperties, DefaultEditorConfigProperties.INSTANCE.getEditorConfigProperties().stream())
8790
.distinct()
8891
.collect(Collectors.toMap(property -> property.getType().getName(), property -> property));
8992

@@ -116,31 +119,16 @@ public Unit invoke(LintError lint, Boolean corrected) {
116119

117120
@Override
118121
public String applyWithFile(String unix, File file) throws Exception {
119-
120-
if (editorConfigOverride != null) {
121-
// Use ExperimentalParams with EditorConfigOverride which requires KtLint 0.45.2
122-
return KtLint.INSTANCE.format(new ExperimentalParams(
123-
file.getName(),
124-
unix,
125-
rulesets,
126-
userData,
127-
formatterCallback,
128-
isScript,
129-
null,
130-
false,
131-
editorConfigOverride,
132-
false));
133-
} else {
134-
// Use Params for backward compatibility
135-
return KtLint.INSTANCE.format(new KtLint.Params(
136-
file.getName(),
137-
unix,
138-
rulesets,
139-
userData,
140-
formatterCallback,
141-
isScript,
142-
null,
143-
false));
144-
}
122+
return KtLint.INSTANCE.format(new ExperimentalParams(
123+
file.getName(),
124+
unix,
125+
rulesets,
126+
userData,
127+
formatterCallback,
128+
isScript,
129+
null,
130+
false,
131+
editorConfigOverride,
132+
false));
145133
}
146134
}

lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java

Lines changed: 7 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@
1818
import java.io.IOException;
1919
import java.io.Serializable;
2020
import java.lang.reflect.Constructor;
21-
import java.lang.reflect.InvocationTargetException;
22-
import java.lang.reflect.Method;
23-
import java.lang.reflect.Proxy;
24-
import java.util.ArrayList;
2521
import java.util.Collections;
2622
import java.util.Map;
2723
import java.util.Objects;
@@ -31,18 +27,15 @@
3127
import com.diffplug.spotless.FormatterStep;
3228
import com.diffplug.spotless.JarState;
3329
import com.diffplug.spotless.Provisioner;
34-
import com.diffplug.spotless.ThrowingEx;
3530

3631
/** Wraps up <a href="https://github.com/pinterest/ktlint">ktlint</a> as a FormatterStep. */
3732
public class KtLintStep {
3833
// prevent direct instantiation
3934
private KtLintStep() {}
4035

41-
private static final String DEFAULT_VERSION = "0.45.2";
36+
private static final String DEFAULT_VERSION = "0.46.1";
4237
static final String NAME = "ktlint";
43-
static final String PACKAGE_PRE_0_32 = "com.github.shyiko";
4438
static final String PACKAGE = "com.pinterest";
45-
static final String MAVEN_COORDINATE_PRE_0_32 = PACKAGE_PRE_0_32 + ":ktlint:";
4639
static final String MAVEN_COORDINATE = PACKAGE + ":ktlint:";
4740

4841
public static FormatterStep create(Provisioner provisioner) {
@@ -85,95 +78,30 @@ static final class State implements Serializable {
8578

8679
/** Are the files being linted Kotlin script files. */
8780
private final boolean isScript;
88-
private final String pkg;
8981
/** The jar that contains the formatter. */
9082
final JarState jarState;
9183
private final boolean useExperimental;
9284
private final TreeMap<String, String> userData;
9385
private final TreeMap<String, Object> editorConfigOverride;
94-
private final boolean useParams;
9586

9687
State(String version, Provisioner provisioner, boolean isScript, boolean useExperimental,
9788
Map<String, String> userData, Map<String, Object> editorConfigOverride) throws IOException {
9889

99-
if (!editorConfigOverride.isEmpty() &&
100-
BadSemver.version(version) < BadSemver.version(0, 45, 2)) {
101-
throw new IllegalStateException("KtLint editorConfigOverride supported for version 0.45.2 and later");
90+
if (BadSemver.version(version) < BadSemver.version(0, 46, 0)) {
91+
throw new IllegalStateException("KtLint versions < 0.46.0 not supported!");
10292
}
10393

10494
this.useExperimental = useExperimental;
10595
this.userData = new TreeMap<>(userData);
10696
this.editorConfigOverride = new TreeMap<>(editorConfigOverride);
107-
String coordinate;
108-
if (BadSemver.version(version) < BadSemver.version(0, 32)) {
109-
coordinate = MAVEN_COORDINATE_PRE_0_32;
110-
this.pkg = PACKAGE_PRE_0_32;
111-
} else {
112-
coordinate = MAVEN_COORDINATE;
113-
this.pkg = PACKAGE;
114-
}
115-
this.useParams = BadSemver.version(version) >= BadSemver.version(0, 34);
116-
this.jarState = JarState.from(coordinate + version, provisioner);
97+
this.jarState = JarState.from(MAVEN_COORDINATE + version, provisioner);
11798
this.isScript = isScript;
11899
}
119100

120101
FormatterFunc createFormat() throws Exception {
121-
if (useParams) {
122-
Class<?> formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.ktlint.KtlintFormatterFunc");
123-
Constructor<?> constructor = formatterFunc.getConstructor(boolean.class, boolean.class, Map.class, Map.class);
124-
return (FormatterFunc.NeedsFile) constructor.newInstance(isScript, useExperimental, userData, editorConfigOverride);
125-
}
126-
127-
ClassLoader classLoader = jarState.getClassLoader();
128-
// String KtLint::format(String input, Iterable<RuleSet> rules, Function2 errorCallback)
129-
130-
ArrayList<Object> ruleSets = new ArrayList<>();
131-
132-
// first, we get the standard rules
133-
Class<?> standardRuleSetProviderClass = classLoader.loadClass(pkg + ".ktlint.ruleset.standard.StandardRuleSetProvider");
134-
Object standardRuleSet = standardRuleSetProviderClass.getMethod("get").invoke(standardRuleSetProviderClass.newInstance());
135-
ruleSets.add(standardRuleSet);
136-
137-
// second, we get the experimental rules if desired
138-
if (useExperimental) {
139-
Class<?> experimentalRuleSetProviderClass = classLoader.loadClass(pkg + ".ktlint.ruleset.experimental.ExperimentalRuleSetProvider");
140-
Object experimentalRuleSet = experimentalRuleSetProviderClass.getMethod("get").invoke(experimentalRuleSetProviderClass.newInstance());
141-
ruleSets.add(experimentalRuleSet);
142-
}
143-
144-
// next, we create an error callback which throws an assertion error when the format is bad
145-
Class<?> function2Interface = classLoader.loadClass("kotlin.jvm.functions.Function2");
146-
Class<?> lintErrorClass = classLoader.loadClass(pkg + ".ktlint.core.LintError");
147-
Method detailGetter = lintErrorClass.getMethod("getDetail");
148-
Method lineGetter = lintErrorClass.getMethod("getLine");
149-
Method colGetter = lintErrorClass.getMethod("getCol");
150-
Object formatterCallback = Proxy.newProxyInstance(classLoader, new Class[]{function2Interface},
151-
(proxy, method, args) -> {
152-
Object lintError = args[0]; //ktlint.core.LintError
153-
boolean corrected = (Boolean) args[1];
154-
if (!corrected) {
155-
String detail = (String) detailGetter.invoke(lintError);
156-
int line = (Integer) lineGetter.invoke(lintError);
157-
int col = (Integer) colGetter.invoke(lintError);
158-
throw new AssertionError("Error on line: " + line + ", column: " + col + "\n" + detail);
159-
}
160-
return null;
161-
});
162-
163-
// grab the KtLint singleton
164-
Class<?> ktlintClass = classLoader.loadClass(pkg + ".ktlint.core.KtLint");
165-
Object ktlint = ktlintClass.getDeclaredField("INSTANCE").get(null);
166-
167-
// and its format method
168-
String formatterMethodName = isScript ? "formatScript" : "format";
169-
Method formatterMethod = ktlintClass.getMethod(formatterMethodName, String.class, Iterable.class, Map.class, function2Interface);
170-
return input -> {
171-
try {
172-
return (String) formatterMethod.invoke(ktlint, input, ruleSets, userData, formatterCallback);
173-
} catch (InvocationTargetException e) {
174-
throw ThrowingEx.unwrapCause(e);
175-
}
176-
};
102+
Class<?> formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.ktlint.KtlintFormatterFunc");
103+
Constructor<?> constructor = formatterFunc.getConstructor(boolean.class, boolean.class, Map.class, Map.class);
104+
return (FormatterFunc.NeedsFile) constructor.newInstance(isScript, useExperimental, userData, editorConfigOverride);
177105
}
178106
}
179107
}

plugin-gradle/CHANGES.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
55
## [Unreleased]
66
### Added
77
* Support for `MAC_CLASSIC` (`\r`) line ending ([#1243](https://github.com/diffplug/spotless/pull/1243) fixes [#1196](https://github.com/diffplug/spotless/issues/1196))
8-
### Changed
9-
* Minimum required `diktat` version bumped to `1.2.0` ([#1246](https://github.com/diffplug/spotless/pull/1246))
10-
* Default bumped from `1.1.0` -> `1.2.0`
8+
### Changes
9+
* Bump default `ktlint` version to latest `0.45.2` -> `0.46.1` ([#1239](https://github.com/diffplug/spotless/issues/1239))
10+
* Minimum supported version also bumped to `0.46.0` (we have abandoned strong backward compatibility for `ktlint`, from here on out Spotless will only support the most-recent breaking change).
11+
* Bump default `diktat` version to latest `1.1.0` -> `1.2.0` ([#1246](https://github.com/diffplug/spotless/pull/1246))
12+
* Minimum supported version also bumped to `1.2.0` (diktat is based on ktlint and has the same backward compatibility issues).
1113

1214
## [6.7.2] - 2022-06-11
1315
### Fixed

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/KotlinExtensionTest.java

Lines changed: 10 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,10 @@
1515
*/
1616
package com.diffplug.gradle.spotless;
1717

18-
import static org.assertj.core.api.Assertions.assertThat;
19-
import static org.junit.jupiter.api.Assertions.assertThrows;
2018
import static org.junit.jupiter.api.condition.JRE.JAVA_11;
2119

2220
import java.io.IOException;
2321

24-
import org.gradle.testkit.runner.BuildResult;
2522
import org.junit.jupiter.api.Test;
2623
import org.junit.jupiter.api.condition.EnabledForJreRange;
2724

@@ -42,9 +39,9 @@ void integration() throws IOException {
4239
" ktlint()",
4340
" }",
4441
"}");
45-
setFile("src/main/kotlin/basic.kt").toResource("kotlin/ktlint/basic.dirty");
42+
setFile("src/main/kotlin/Main.kt").toResource("kotlin/ktlint/basic.dirty");
4643
gradleRunner().withArguments("spotlessApply").build();
47-
assertFile("src/main/kotlin/basic.kt").sameAsResource("kotlin/ktlint/basic.clean");
44+
assertFile("src/main/kotlin/Main.kt").sameAsResource("kotlin/ktlint/basic.clean");
4845
}
4946

5047
@Test
@@ -132,12 +129,12 @@ void testWithIndentation() throws IOException {
132129
"repositories { mavenCentral() }",
133130
"spotless {",
134131
" kotlin {",
135-
" ktlint('0.32.0').userData(['indent_size': '6'])",
132+
" ktlint().editorConfigOverride(['indent_size': '6'])",
136133
" }",
137134
"}");
138-
setFile("src/main/kotlin/basic.kt").toResource("kotlin/ktlint/basic.dirty");
139-
BuildResult result = gradleRunner().withArguments("spotlessApply").buildAndFail();
140-
assertThat(result.getOutput()).contains("Unexpected indentation (4) (it should be 6)");
135+
setFile("src/main/kotlin/Main.kt").toResource("kotlin/ktlint/basic.dirty");
136+
gradleRunner().withArguments("spotlessApply").build();
137+
assertFile("src/main/kotlin/Main.kt").sameAsResource("kotlin/ktlint/basic.clean-indent6");
141138
}
142139

143140
@Test
@@ -153,27 +150,9 @@ void withExperimental() throws IOException {
153150
" ktlint().setUseExperimental(true)",
154151
" }",
155152
"}");
156-
setFile("src/main/kotlin/experimental.kt").toResource("kotlin/ktlint/experimental.dirty");
153+
setFile("src/main/kotlin/Main.kt").toResource("kotlin/ktlint/experimental.dirty");
157154
gradleRunner().withArguments("spotlessApply").build();
158-
assertFile("src/main/kotlin/experimental.kt").sameAsResource("kotlin/ktlint/experimental.clean");
159-
}
160-
161-
@Test
162-
void withExperimental_0_32() throws IOException {
163-
setFile("build.gradle").toLines(
164-
"plugins {",
165-
" id 'org.jetbrains.kotlin.jvm' version '1.5.31'",
166-
" id 'com.diffplug.spotless'",
167-
"}",
168-
"repositories { mavenCentral() }",
169-
"spotless {",
170-
" kotlin {",
171-
" ktlint('0.32.0').setUseExperimental(true)",
172-
" }",
173-
"}");
174-
setFile("src/main/kotlin/basic.kt").toResource("kotlin/ktlint/basic.dirty");
175-
gradleRunner().withArguments("spotlessApply").build();
176-
assertFile("src/main/kotlin/basic.kt").sameAsResource("kotlin/ktlint/basic.clean");
155+
assertFile("src/main/kotlin/Main.kt").sameAsResource("kotlin/ktlint/experimental.clean");
177156
}
178157

179158
@Test
@@ -193,56 +172,9 @@ void withExperimentalEditorConfigOverride() throws IOException {
193172
" ])",
194173
" }",
195174
"}");
196-
setFile("src/main/kotlin/experimental.kt").toResource("kotlin/ktlint/experimentalEditorConfigOverride.dirty");
197-
gradleRunner().withArguments("spotlessApply").build();
198-
assertFile("src/main/kotlin/experimental.kt").sameAsResource("kotlin/ktlint/experimentalEditorConfigOverride.clean");
199-
}
200-
201-
@Test
202-
void withEditorConfigOverride_0_45_1() throws IOException {
203-
setFile("build.gradle").toLines(
204-
"plugins {",
205-
" id 'org.jetbrains.kotlin.jvm' version '1.5.31'",
206-
" id 'com.diffplug.spotless'",
207-
"}",
208-
"repositories { mavenCentral() }",
209-
"spotless {",
210-
" kotlin {",
211-
" ktlint('0.45.1')",
212-
" .editorConfigOverride([",
213-
" indent_size: 5",
214-
" ])",
215-
" }",
216-
"}");
217-
setFile("src/main/kotlin/basic.kt").toResource("kotlin/ktlint/basic.dirty");
218-
Throwable error = assertThrows(Throwable.class,
219-
() -> gradleRunner().withArguments("spotlessApply").build());
220-
assertThat(error).hasMessageContaining("KtLint editorConfigOverride supported for version 0.45.2 and later");
221-
}
222-
223-
/**
224-
* Check that the sample used to verify the experimental ruleset is untouched by the default ruleset, to verify
225-
* that enabling the experimental ruleset is actually doing something.
226-
*
227-
* If this test fails, it's likely that the experimental rule being used as a test graduated into the standard
228-
* ruleset, and therefore a new experimental rule should be used to verify functionality.
229-
*/
230-
@Test
231-
void experimentalSampleUnchangedWithDefaultRuleset() throws IOException {
232-
setFile("build.gradle").toLines(
233-
"plugins {",
234-
" id 'org.jetbrains.kotlin.jvm' version '1.5.31'",
235-
" id 'com.diffplug.spotless'",
236-
"}",
237-
"repositories { mavenCentral() }",
238-
"spotless {",
239-
" kotlin {",
240-
" ktlint()",
241-
" }",
242-
"}");
243-
setFile("src/main/kotlin/experimental.kt").toResource("kotlin/ktlint/experimental.dirty");
175+
setFile("src/main/kotlin/Main.kt").toResource("kotlin/ktlint/experimentalEditorConfigOverride.dirty");
244176
gradleRunner().withArguments("spotlessApply").build();
245-
assertFile("src/main/kotlin/experimental.kt").sameAsResource("kotlin/ktlint/experimental.dirty");
177+
assertFile("src/main/kotlin/Main.kt").sameAsResource("kotlin/ktlint/experimentalEditorConfigOverride.clean");
246178
}
247179

248180
@Test

0 commit comments

Comments
 (0)