Skip to content

Commit

Permalink
Support custom rule sets for Ktlint (#1896)
Browse files Browse the repository at this point in the history
  • Loading branch information
nedtwigg authored Nov 21, 2023
2 parents d5ddbcf + 6d4a679 commit 0570045
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This document is intended for Spotless developers.
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
* Support custom rule sets for Ktlint. ([#1896](https://github.com/diffplug/spotless/pull/1896)
### Fixed
* Fix Eclipse JDT on some settings files. ([#1864](https://github.com/diffplug/spotless/pull/1864) fixes [#1638](https://github.com/diffplug/spotless/issues/1638))
### Changes
Expand Down
21 changes: 14 additions & 7 deletions lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;

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

public static FormatterStep create(String version, Provisioner provisioner) {
return create(version, provisioner, null, Collections.emptyMap());
return create(version, provisioner, null, Collections.emptyMap(), Collections.emptyList());
}

public static FormatterStep create(String version,
Provisioner provisioner,
@Nullable FileSignature editorConfig,
Map<String, Object> editorConfigOverride) {
Map<String, Object> editorConfigOverride,
List<String> customRuleSets) {
Objects.requireNonNull(version, "version");
Objects.requireNonNull(provisioner, "provisioner");
return FormatterStep.createLazy(NAME,
() -> new State(version, provisioner, editorConfig, editorConfigOverride),
() -> new State(version, provisioner, editorConfig, editorConfigOverride, customRuleSets),
State::createFormat);
}

public static String defaultVersion() {
return DEFAULT_VERSION;
}

static final class State implements Serializable {
private static final class State implements Serializable {
private static final long serialVersionUID = 1L;
/** The jar that contains the formatter. */
private final JarState jarState;
Expand All @@ -76,11 +80,14 @@ static final class State implements Serializable {
State(String version,
Provisioner provisioner,
@Nullable FileSignature editorConfigPath,
Map<String, Object> editorConfigOverride) throws IOException {
Map<String, Object> editorConfigOverride,
List<String> customRuleSets) throws IOException {
this.version = version;
this.editorConfigOverride = new TreeMap<>(editorConfigOverride);
this.jarState = JarState.from((version.startsWith("0.") ? MAVEN_COORDINATE_0_DOT : MAVEN_COORDINATE_1_DOT) + version,
provisioner);
String ktlintCoordinate = (version.startsWith("0.") ? MAVEN_COORDINATE_0_DOT : MAVEN_COORDINATE_1_DOT) + version;
Set<String> mavenCoordinates = new HashSet<>(customRuleSets);
mavenCoordinates.add(ktlintCoordinate);
this.jarState = JarState.from(mavenCoordinates, provisioner);
this.editorConfigPath = editorConfigPath;
}

Expand Down
2 changes: 2 additions & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).

## [Unreleased]
### Added
* Support custom rule sets for Ktlint. ([#1896](https://github.com/diffplug/spotless/pull/1896)
### Fixed
* Fix Eclipse JDT on some settings files. ([#1864](https://github.com/diffplug/spotless/pull/1864) fixes [#1638](https://github.com/diffplug/spotless/issues/1638))
* Check if EditorConfig file exist for Ktlint in KotlinGradleExtension. ([#1889](https://github.com/diffplug/spotless/pull/1889))
Expand Down
7 changes: 6 additions & 1 deletion plugin-gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,14 +399,19 @@ Additionally, `editorConfigOverride` options will override what's supplied in `.
```kotlin
spotless {
kotlin {
// version, editorConfigPath and editorConfigOverride are all optional
// version, editorConfigPath, editorConfigOverride and customRuleSets are all optional
ktlint("1.0.0")
.setEditorConfigPath("$projectDir/config/.editorconfig") // sample unusual placement
.editorConfigOverride(
mapOf(
"indent_size" to 2,
)
)
.customRuleSets(
listOf(
"io.nlopez.compose.rules:ktlint:0.3.3"
)
)
}
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;

import javax.annotation.Nullable;

import com.diffplug.common.collect.ImmutableList;
import com.diffplug.common.collect.ImmutableSortedMap;
import com.diffplug.spotless.FileSignature;
import com.diffplug.spotless.FormatterStep;
Expand Down Expand Up @@ -51,7 +53,7 @@ public KtlintConfig ktlint() throws IOException {

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

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

private KtlintConfig(
String version,
Map<String, Object> editorConfigOverride) throws IOException {
Map<String, Object> editorConfigOverride,
List<String> customRuleSets) throws IOException {
Objects.requireNonNull(version);
File defaultEditorConfig = getProject().getRootProject().file(".editorconfig");
FileSignature editorConfigPath = defaultEditorConfig.exists() ? FileSignature.signAsList(defaultEditorConfig) : null;
this.version = version;
this.editorConfigPath = editorConfigPath;
this.editorConfigOverride = editorConfigOverride;
this.customRuleSets = customRuleSets;
addStep(createStep());
}

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

public KtlintConfig customRuleSets(List<String> customRuleSets) {
this.customRuleSets = ImmutableList.copyOf(customRuleSets);
replaceStep(createStep());
return this;
}

private FormatterStep createStep() {
return KtLintStep.create(
version,
provisioner(),
editorConfigPath,
editorConfigOverride);
editorConfigOverride,
customRuleSets);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,30 @@ void testSetEditorConfigCanOverrideEditorConfigFile() throws IOException {
checkKtlintOfficialStyle();
}

@Test
void withCustomRuleSetApply() throws IOException {
setFile("build.gradle").toLines(
"plugins {",
" id 'org.jetbrains.kotlin.jvm' version '1.5.31'",
" id 'com.diffplug.spotless'",
"}",
"repositories { mavenCentral() }",
"spotless {",
" kotlin {",
" ktlint(\"1.0.1\")",
" .customRuleSets([",
" \"io.nlopez.compose.rules:ktlint:0.3.3\"",
" ])",
" .editorConfigOverride([",
" ktlint_function_naming_ignore_when_annotated_with: \"Composable\",",
" ])",
" }",
"}");
setFile("src/main/kotlin/Main.kt").toResource("kotlin/ktlint/listScreen.dirty");
String buildOutput = gradleRunner().withArguments("spotlessCheck").buildAndFail().getOutput();
assertThat(buildOutput).contains("Composable functions that return Unit should start with an uppercase letter.");
}

@Test
void testWithHeader() throws IOException {
setFile("build.gradle").toLines(
Expand Down
1 change: 1 addition & 0 deletions plugin-maven/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
## [Unreleased]
### Added
* 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))
* Support custom rule sets for Ktlint. ([#1896](https://github.com/diffplug/spotless/pull/1896)
### Fixed
* Fix crash when build dir is a softlink to another directory. ([#1859](https://github.com/diffplug/spotless/pull/1859))
* Fix Eclipse JDT on some settings files. ([#1864](https://github.com/diffplug/spotless/pull/1864) fixes [#1638](https://github.com/diffplug/spotless/issues/1638))
Expand Down
3 changes: 3 additions & 0 deletions plugin-maven/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,9 @@ Additionally, `editorConfigOverride` options will override what's supplied in `.
<ij_kotlin_allow_trailing_comma>true</ij_kotlin_allow_trailing_comma>
<ij_kotlin_allow_trailing_comma_on_call_site>true</ij_kotlin_allow_trailing_comma_on_call_site>
</editorConfigOverride>
<customRuleSets> <!-- optional -->
<value>io.nlopez.compose.rules:ktlint:0.3.3</value>
</customRuleSets>
</ktlint>
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
*/
package com.diffplug.spotless.maven.kotlin;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

public class Ktlint implements FormatterStepFactory {

@Parameter
private String version;
@Parameter
private String editorConfigPath;
@Parameter
private Map<String, Object> editorConfigOverride;
@Parameter
private List<String> customRuleSets;

@Override
public FormatterStep newFormatterStep(final FormatterStepConfig stepConfig) {
Expand All @@ -46,7 +49,14 @@ public FormatterStep newFormatterStep(final FormatterStepConfig stepConfig) {
if (editorConfigOverride == null) {
editorConfigOverride = new HashMap<>();
}

return KtLintStep.create(ktlintVersion, stepConfig.getProvisioner(), configPath, editorConfigOverride);
if (customRuleSets == null) {
customRuleSets = Collections.emptyList();
}
return KtLintStep.create(
ktlintVersion,
stepConfig.getProvisioner(),
configPath,
editorConfigOverride,
customRuleSets);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
*/
package com.diffplug.spotless.maven.kotlin;

import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

import com.diffplug.spotless.ProcessRunner;
import com.diffplug.spotless.maven.MavenIntegrationHarness;

class KtlintTest extends MavenIntegrationHarness {
Expand Down Expand Up @@ -63,6 +66,21 @@ void testSetEditorConfigCanOverrideEditorConfigFile() throws Exception {
checkKtlintOfficialStyle();
}

@Test
void testWithCustomRuleSetApply() throws Exception {
writePomWithKotlinSteps("<ktlint>\n" +
" <customRuleSets>\n" +
" <value>io.nlopez.compose.rules:ktlint:0.3.3</value>\n" +
" </customRuleSets>\n" +
" <editorConfigOverride>\n" +
" <ktlint_function_naming_ignore_when_annotated_with>Composable</ktlint_function_naming_ignore_when_annotated_with>\n" +
" </editorConfigOverride>\n" +
"</ktlint>");
setFile("src/main/kotlin/Main.kt").toResource("kotlin/ktlint/listScreen.dirty");
ProcessRunner.Result result = mavenRunner().withArguments("spotless:check").runHasError();
assertTrue(result.toString().contains("Composable functions that return Unit should start with an uppercase letter."));
}

private void checkKtlintOfficialStyle() throws Exception {
String path = "src/main/kotlin/Main.kt";
setFile(path).toResource("kotlin/ktlint/experimentalEditorConfigOverride.dirty");
Expand Down
6 changes: 6 additions & 0 deletions testlib/src/main/resources/kotlin/ktlint/listScreen.dirty
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import androidx.compose.runtime.Composable

@Composable
fun listScreen() {
val list: List<String> = mutableListOf<String>()
}

0 comments on commit 0570045

Please sign in to comment.