Skip to content

Commit 0570045

Browse files
authored
Support custom rule sets for Ktlint (#1896)
2 parents d5ddbcf + 6d4a679 commit 0570045

File tree

11 files changed

+104
-14
lines changed

11 files changed

+104
-14
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ This document is intended for Spotless developers.
1010
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
1111

1212
## [Unreleased]
13+
### Added
14+
* Support custom rule sets for Ktlint. ([#1896](https://github.com/diffplug/spotless/pull/1896)
1315
### Fixed
1416
* Fix Eclipse JDT on some settings files. ([#1864](https://github.com/diffplug/spotless/pull/1864) fixes [#1638](https://github.com/diffplug/spotless/issues/1638))
1517
### Changes

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

+14-7
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
import java.io.Serializable;
2020
import java.lang.reflect.Constructor;
2121
import java.util.Collections;
22+
import java.util.HashSet;
23+
import java.util.List;
2224
import java.util.Map;
2325
import java.util.Objects;
26+
import java.util.Set;
2427
import java.util.TreeMap;
2528

2629
import javax.annotation.Nullable;
@@ -46,25 +49,26 @@ public static FormatterStep create(Provisioner provisioner) {
4649
}
4750

4851
public static FormatterStep create(String version, Provisioner provisioner) {
49-
return create(version, provisioner, null, Collections.emptyMap());
52+
return create(version, provisioner, null, Collections.emptyMap(), Collections.emptyList());
5053
}
5154

5255
public static FormatterStep create(String version,
5356
Provisioner provisioner,
5457
@Nullable FileSignature editorConfig,
55-
Map<String, Object> editorConfigOverride) {
58+
Map<String, Object> editorConfigOverride,
59+
List<String> customRuleSets) {
5660
Objects.requireNonNull(version, "version");
5761
Objects.requireNonNull(provisioner, "provisioner");
5862
return FormatterStep.createLazy(NAME,
59-
() -> new State(version, provisioner, editorConfig, editorConfigOverride),
63+
() -> new State(version, provisioner, editorConfig, editorConfigOverride, customRuleSets),
6064
State::createFormat);
6165
}
6266

6367
public static String defaultVersion() {
6468
return DEFAULT_VERSION;
6569
}
6670

67-
static final class State implements Serializable {
71+
private static final class State implements Serializable {
6872
private static final long serialVersionUID = 1L;
6973
/** The jar that contains the formatter. */
7074
private final JarState jarState;
@@ -76,11 +80,14 @@ static final class State implements Serializable {
7680
State(String version,
7781
Provisioner provisioner,
7882
@Nullable FileSignature editorConfigPath,
79-
Map<String, Object> editorConfigOverride) throws IOException {
83+
Map<String, Object> editorConfigOverride,
84+
List<String> customRuleSets) throws IOException {
8085
this.version = version;
8186
this.editorConfigOverride = new TreeMap<>(editorConfigOverride);
82-
this.jarState = JarState.from((version.startsWith("0.") ? MAVEN_COORDINATE_0_DOT : MAVEN_COORDINATE_1_DOT) + version,
83-
provisioner);
87+
String ktlintCoordinate = (version.startsWith("0.") ? MAVEN_COORDINATE_0_DOT : MAVEN_COORDINATE_1_DOT) + version;
88+
Set<String> mavenCoordinates = new HashSet<>(customRuleSets);
89+
mavenCoordinates.add(ktlintCoordinate);
90+
this.jarState = JarState.from(mavenCoordinates, provisioner);
8491
this.editorConfigPath = editorConfigPath;
8592
}
8693

plugin-gradle/CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).
44

55
## [Unreleased]
6+
### Added
7+
* Support custom rule sets for Ktlint. ([#1896](https://github.com/diffplug/spotless/pull/1896)
68
### Fixed
79
* Fix Eclipse JDT on some settings files. ([#1864](https://github.com/diffplug/spotless/pull/1864) fixes [#1638](https://github.com/diffplug/spotless/issues/1638))
810
* Check if EditorConfig file exist for Ktlint in KotlinGradleExtension. ([#1889](https://github.com/diffplug/spotless/pull/1889))

plugin-gradle/README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,19 @@ Additionally, `editorConfigOverride` options will override what's supplied in `.
399399
```kotlin
400400
spotless {
401401
kotlin {
402-
// version, editorConfigPath and editorConfigOverride are all optional
402+
// version, editorConfigPath, editorConfigOverride and customRuleSets are all optional
403403
ktlint("1.0.0")
404404
.setEditorConfigPath("$projectDir/config/.editorconfig") // sample unusual placement
405405
.editorConfigOverride(
406406
mapOf(
407407
"indent_size" to 2,
408408
)
409409
)
410+
.customRuleSets(
411+
listOf(
412+
"io.nlopez.compose.rules:ktlint:0.3.3"
413+
)
414+
)
410415
}
411416
}
412417
```

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/BaseKotlinExtension.java

+15-3
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
import java.io.File;
1919
import java.io.IOException;
2020
import java.util.Collections;
21+
import java.util.List;
2122
import java.util.Map;
2223
import java.util.Objects;
2324
import java.util.function.Consumer;
2425

2526
import javax.annotation.Nullable;
2627

28+
import com.diffplug.common.collect.ImmutableList;
2729
import com.diffplug.common.collect.ImmutableSortedMap;
2830
import com.diffplug.spotless.FileSignature;
2931
import com.diffplug.spotless.FormatterStep;
@@ -51,7 +53,7 @@ public KtlintConfig ktlint() throws IOException {
5153

5254
/** Adds the specified version of <a href="https://github.com/pinterest/ktlint">ktlint</a>. */
5355
public KtlintConfig ktlint(String version) throws IOException {
54-
return new KtlintConfig(version, Collections.emptyMap());
56+
return new KtlintConfig(version, Collections.emptyMap(), Collections.emptyList());
5557
}
5658

5759
/** Uses the <a href="https://github.com/facebookincubator/ktfmt">ktfmt</a> jar to format source code. */
@@ -147,16 +149,19 @@ public class KtlintConfig {
147149
private final String version;
148150
private FileSignature editorConfigPath;
149151
private Map<String, Object> editorConfigOverride;
152+
private List<String> customRuleSets;
150153

151154
private KtlintConfig(
152155
String version,
153-
Map<String, Object> editorConfigOverride) throws IOException {
156+
Map<String, Object> editorConfigOverride,
157+
List<String> customRuleSets) throws IOException {
154158
Objects.requireNonNull(version);
155159
File defaultEditorConfig = getProject().getRootProject().file(".editorconfig");
156160
FileSignature editorConfigPath = defaultEditorConfig.exists() ? FileSignature.signAsList(defaultEditorConfig) : null;
157161
this.version = version;
158162
this.editorConfigPath = editorConfigPath;
159163
this.editorConfigOverride = editorConfigOverride;
164+
this.customRuleSets = customRuleSets;
160165
addStep(createStep());
161166
}
162167

@@ -182,12 +187,19 @@ public KtlintConfig editorConfigOverride(Map<String, Object> editorConfigOverrid
182187
return this;
183188
}
184189

190+
public KtlintConfig customRuleSets(List<String> customRuleSets) {
191+
this.customRuleSets = ImmutableList.copyOf(customRuleSets);
192+
replaceStep(createStep());
193+
return this;
194+
}
195+
185196
private FormatterStep createStep() {
186197
return KtLintStep.create(
187198
version,
188199
provisioner(),
189200
editorConfigPath,
190-
editorConfigOverride);
201+
editorConfigOverride,
202+
customRuleSets);
191203
}
192204
}
193205
}

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

+24
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,30 @@ void testSetEditorConfigCanOverrideEditorConfigFile() throws IOException {
141141
checkKtlintOfficialStyle();
142142
}
143143

144+
@Test
145+
void withCustomRuleSetApply() throws IOException {
146+
setFile("build.gradle").toLines(
147+
"plugins {",
148+
" id 'org.jetbrains.kotlin.jvm' version '1.5.31'",
149+
" id 'com.diffplug.spotless'",
150+
"}",
151+
"repositories { mavenCentral() }",
152+
"spotless {",
153+
" kotlin {",
154+
" ktlint(\"1.0.1\")",
155+
" .customRuleSets([",
156+
" \"io.nlopez.compose.rules:ktlint:0.3.3\"",
157+
" ])",
158+
" .editorConfigOverride([",
159+
" ktlint_function_naming_ignore_when_annotated_with: \"Composable\",",
160+
" ])",
161+
" }",
162+
"}");
163+
setFile("src/main/kotlin/Main.kt").toResource("kotlin/ktlint/listScreen.dirty");
164+
String buildOutput = gradleRunner().withArguments("spotlessCheck").buildAndFail().getOutput();
165+
assertThat(buildOutput).contains("Composable functions that return Unit should start with an uppercase letter.");
166+
}
167+
144168
@Test
145169
void testWithHeader() throws IOException {
146170
setFile("build.gradle").toLines(

plugin-maven/CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
55
## [Unreleased]
66
### Added
77
* CompileSourceRoots and TestCompileSourceRoots are now respected as default includes. These properties are commonly set when adding extra source directories. ([#1846](https://github.com/diffplug/spotless/issues/1846))
8+
* Support custom rule sets for Ktlint. ([#1896](https://github.com/diffplug/spotless/pull/1896)
89
### Fixed
910
* Fix crash when build dir is a softlink to another directory. ([#1859](https://github.com/diffplug/spotless/pull/1859))
1011
* Fix Eclipse JDT on some settings files. ([#1864](https://github.com/diffplug/spotless/pull/1864) fixes [#1638](https://github.com/diffplug/spotless/issues/1638))

plugin-maven/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ Additionally, `editorConfigOverride` options will override what's supplied in `.
416416
<ij_kotlin_allow_trailing_comma>true</ij_kotlin_allow_trailing_comma>
417417
<ij_kotlin_allow_trailing_comma_on_call_site>true</ij_kotlin_allow_trailing_comma_on_call_site>
418418
</editorConfigOverride>
419+
<customRuleSets> <!-- optional -->
420+
<value>io.nlopez.compose.rules:ktlint:0.3.3</value>
421+
</customRuleSets>
419422
</ktlint>
420423
```
421424

plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktlint.java

+13-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
*/
1616
package com.diffplug.spotless.maven.kotlin;
1717

18+
import java.util.Collections;
1819
import java.util.HashMap;
20+
import java.util.List;
1921
import java.util.Map;
2022

2123
import org.apache.maven.plugins.annotations.Parameter;
@@ -28,13 +30,14 @@
2830
import com.diffplug.spotless.maven.FormatterStepFactory;
2931

3032
public class Ktlint implements FormatterStepFactory {
31-
3233
@Parameter
3334
private String version;
3435
@Parameter
3536
private String editorConfigPath;
3637
@Parameter
3738
private Map<String, Object> editorConfigOverride;
39+
@Parameter
40+
private List<String> customRuleSets;
3841

3942
@Override
4043
public FormatterStep newFormatterStep(final FormatterStepConfig stepConfig) {
@@ -46,7 +49,14 @@ public FormatterStep newFormatterStep(final FormatterStepConfig stepConfig) {
4649
if (editorConfigOverride == null) {
4750
editorConfigOverride = new HashMap<>();
4851
}
49-
50-
return KtLintStep.create(ktlintVersion, stepConfig.getProvisioner(), configPath, editorConfigOverride);
52+
if (customRuleSets == null) {
53+
customRuleSets = Collections.emptyList();
54+
}
55+
return KtLintStep.create(
56+
ktlintVersion,
57+
stepConfig.getProvisioner(),
58+
configPath,
59+
editorConfigOverride,
60+
customRuleSets);
5161
}
5262
}

plugin-maven/src/test/java/com/diffplug/spotless/maven/kotlin/KtlintTest.java

+18
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
*/
1616
package com.diffplug.spotless.maven.kotlin;
1717

18+
import static org.junit.jupiter.api.Assertions.assertTrue;
19+
1820
import org.junit.jupiter.api.Test;
1921

22+
import com.diffplug.spotless.ProcessRunner;
2023
import com.diffplug.spotless.maven.MavenIntegrationHarness;
2124

2225
class KtlintTest extends MavenIntegrationHarness {
@@ -63,6 +66,21 @@ void testSetEditorConfigCanOverrideEditorConfigFile() throws Exception {
6366
checkKtlintOfficialStyle();
6467
}
6568

69+
@Test
70+
void testWithCustomRuleSetApply() throws Exception {
71+
writePomWithKotlinSteps("<ktlint>\n" +
72+
" <customRuleSets>\n" +
73+
" <value>io.nlopez.compose.rules:ktlint:0.3.3</value>\n" +
74+
" </customRuleSets>\n" +
75+
" <editorConfigOverride>\n" +
76+
" <ktlint_function_naming_ignore_when_annotated_with>Composable</ktlint_function_naming_ignore_when_annotated_with>\n" +
77+
" </editorConfigOverride>\n" +
78+
"</ktlint>");
79+
setFile("src/main/kotlin/Main.kt").toResource("kotlin/ktlint/listScreen.dirty");
80+
ProcessRunner.Result result = mavenRunner().withArguments("spotless:check").runHasError();
81+
assertTrue(result.toString().contains("Composable functions that return Unit should start with an uppercase letter."));
82+
}
83+
6684
private void checkKtlintOfficialStyle() throws Exception {
6785
String path = "src/main/kotlin/Main.kt";
6886
setFile(path).toResource("kotlin/ktlint/experimentalEditorConfigOverride.dirty");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import androidx.compose.runtime.Composable
2+
3+
@Composable
4+
fun listScreen() {
5+
val list: List<String> = mutableListOf<String>()
6+
}

0 commit comments

Comments
 (0)