diff --git a/CHANGES.md b/CHANGES.md index a7e3516607..50e4d83141 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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] +### Fixed +* Support `ktlint` 0.48+ new rule disabling syntax ([#1456](https://github.com/diffplug/spotless/pull/1456)) fixes ([#1444](https://github.com/diffplug/spotless/issues/1444)) ### Changes * Bump the dev version of Gradle from `7.5.1` to `7.6` ([#1409](https://github.com/diffplug/spotless/pull/1409)) * We also removed the no-longer-required dependency `org.codehaus.groovy:groovy-xml` @@ -18,6 +20,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * `StepHarness` now operates on `Formatter` rather than a `FormatterStep` * `StepHarnessWithFile` now takes a `ResourceHarness` in its constructor to handle the file manipulation parts * Standardized that we test exception *messages*, not types, which will ease the transition to linting later on + * Bump default `ktlint` version to latest `0.47.1` -> `0.48.1` ([#1456](https://github.com/diffplug/spotless/pull/1456)) ## [2.31.1] - 2023-01-02 ### Fixed diff --git a/lib/build.gradle b/lib/build.gradle index 0cc258afca..115d27195f 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -45,9 +45,9 @@ dependencies { compileOnly 'org.slf4j:slf4j-api:2.0.0' // zero runtime reqs is a hard requirements for spotless-lib // if you need a dep, put it in lib-extra - testImplementation "org.junit.jupiter:junit-jupiter:$VER_JUNIT" - testImplementation "org.assertj:assertj-core:$VER_ASSERTJ" - testImplementation "com.diffplug.durian:durian-testlib:$VER_DURIAN" + testCommonImplementation "org.junit.jupiter:junit-jupiter:$VER_JUNIT" + testCommonImplementation "org.assertj:assertj-core:$VER_ASSERTJ" + testCommonImplementation "com.diffplug.durian:durian-testlib:$VER_DURIAN" // used for pom sorting sortPomCompileOnly 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0' @@ -91,9 +91,9 @@ dependencies { compatKtLint0Dot47Dot0CompileOnly 'com.pinterest.ktlint:ktlint-core:0.47.0' compatKtLint0Dot47Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.47.0' compatKtLint0Dot47Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.47.0' - compatKtLint0Dot48Dot0CompileOnly 'com.pinterest.ktlint:ktlint-core:0.48.0' - compatKtLint0Dot48Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.48.0' - compatKtLint0Dot48Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.48.0' + compatKtLint0Dot48Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-core:0.48.0' + compatKtLint0Dot48Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.48.0' + compatKtLint0Dot48Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.48.0' String VER_SCALAFMT="3.6.1" scalafmtCompileOnly "org.scalameta:scalafmt-core_2.13:$VER_SCALAFMT" @@ -108,7 +108,9 @@ dependencies { // we'll hold the core lib to a high standard spotbugs { reportLevel = 'low' } // low|medium|high (low = sensitive to even minor mistakes) -test { useJUnitPlatform() } +tasks.withType(Test).configureEach { + useJUnitPlatform() +} jar { for (glue in NEEDS_GLUE) { diff --git a/lib/src/compatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0Adapter.java b/lib/src/compatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0Adapter.java index 8235c535a5..f910576971 100644 --- a/lib/src/compatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0Adapter.java +++ b/lib/src/compatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0Adapter.java @@ -15,6 +15,8 @@ */ package com.diffplug.spotless.glue.ktlint.compat; +import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -27,11 +29,17 @@ import com.pinterest.ktlint.core.LintError; import com.pinterest.ktlint.core.Rule; import com.pinterest.ktlint.core.RuleProvider; -import com.pinterest.ktlint.core.api.DefaultEditorConfigProperties; import com.pinterest.ktlint.core.api.EditorConfigDefaults; import com.pinterest.ktlint.core.api.EditorConfigOverride; import com.pinterest.ktlint.core.api.UsesEditorConfigProperties; +import com.pinterest.ktlint.core.api.editorconfig.CodeStyleEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.DisabledRulesEditorConfigPropertyKt; import com.pinterest.ktlint.core.api.editorconfig.EditorConfigProperty; +import com.pinterest.ktlint.core.api.editorconfig.IndentSizeEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.IndentStyleEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.InsertFinalNewLineEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.MaxLineLengthEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.RuleExecutionEditorConfigPropertyKt; import com.pinterest.ktlint.ruleset.experimental.ExperimentalRuleSetProvider; import com.pinterest.ktlint.ruleset.standard.StandardRuleSetProvider; @@ -41,13 +49,29 @@ public class KtLintCompat0Dot48Dot0Adapter implements KtLintCompatAdapter { + private static final List> DEFAULT_EDITOR_CONFIG_PROPERTIES; + + static { + List> list = new ArrayList<>(); + list.add(CodeStyleEditorConfigPropertyKt.getCODE_STYLE_PROPERTY()); + //noinspection deprecation + list.add(DisabledRulesEditorConfigPropertyKt.getDISABLED_RULES_PROPERTY()); + //noinspection KotlinInternalInJava,deprecation + list.add(DisabledRulesEditorConfigPropertyKt.getKTLINT_DISABLED_RULES_PROPERTY()); + list.add(IndentStyleEditorConfigPropertyKt.getINDENT_STYLE_PROPERTY()); + list.add(IndentSizeEditorConfigPropertyKt.getINDENT_SIZE_PROPERTY()); + list.add(InsertFinalNewLineEditorConfigPropertyKt.getINSERT_FINAL_NEWLINE_PROPERTY()); + list.add(MaxLineLengthEditorConfigPropertyKt.getMAX_LINE_LENGTH_PROPERTY()); + DEFAULT_EDITOR_CONFIG_PROPERTIES = Collections.unmodifiableList(list); + } + static class FormatterCallback implements Function2 { @Override public Unit invoke(LintError lint, Boolean corrected) { if (!corrected) { KtLintCompatReporting.report(lint.getLine(), lint.getCol(), lint.getRuleId(), lint.getDetail()); } - return null; + return Unit.INSTANCE; } } @@ -66,7 +90,7 @@ public String format(final String text, final String name, final boolean isScrip EditorConfigOverride editorConfigOverride; if (editorConfigOverrideMap.isEmpty()) { - editorConfigOverride = EditorConfigOverride.Companion.getEmptyEditorConfigOverride(); + editorConfigOverride = EditorConfigOverride.Companion.getEMPTY_EDITOR_CONFIG_OVERRIDE(); } else { editorConfigOverride = createEditorConfigOverride(allRuleProviders.stream().map( RuleProvider::createNewRuleInstance).collect( @@ -82,7 +106,7 @@ public String format(final String text, final String name, final boolean isScrip formatterCallback, isScript, false, - EditorConfigDefaults.Companion.getEmptyEditorConfigDefaults(), + EditorConfigDefaults.Companion.getEMPTY_EDITOR_CONFIG_DEFAULTS(), editorConfigOverride, false)); } @@ -98,7 +122,7 @@ private static EditorConfigOverride createEditorConfigOverride(final List // Create a mapping of properties to their names based on rule properties and default properties Map> supportedProperties = Stream - .concat(ruleProperties, DefaultEditorConfigProperties.INSTANCE.getEditorConfigProperties().stream()) + .concat(ruleProperties, DEFAULT_EDITOR_CONFIG_PROPERTIES.stream()) .distinct() .collect(Collectors.toMap(EditorConfigProperty::getName, property -> property)); @@ -109,6 +133,18 @@ private static EditorConfigOverride createEditorConfigOverride(final List EditorConfigProperty property = supportedProperties.get(entry.getKey()); if (property != null) { return new Pair<>(property, entry.getValue()); + } else if (entry.getKey().startsWith("ktlint_")) { + String[] parts = entry.getKey().substring(7).split("_", 2); + if (parts.length == 1) { + // convert ktlint_{ruleset} to {ruleset} + String qualifiedRuleId = parts[0]; + property = RuleExecutionEditorConfigPropertyKt.createRuleSetExecutionEditorConfigProperty(qualifiedRuleId); + } else { + // convert ktlint_{ruleset}_{rulename} to {ruleset}:{rulename} + String qualifiedRuleId = parts[0] + ":" + parts[1]; + property = RuleExecutionEditorConfigPropertyKt.createRuleExecutionEditorConfigProperty(qualifiedRuleId); + } + return new Pair<>(property, entry.getValue()); } else { return null; } 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 b444f0f1a7..7efbb911e3 100644 --- a/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java +++ b/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java @@ -33,7 +33,7 @@ public class KtLintStep { // prevent direct instantiation private KtLintStep() {} - private static final String DEFAULT_VERSION = "0.48.0"; + private static final String DEFAULT_VERSION = "0.48.1"; static final String NAME = "ktlint"; static final String PACKAGE_PRE_0_32 = "com.github.shyiko"; static final String PACKAGE = "com.pinterest"; diff --git a/lib/src/testCompatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0AdapterTest.java b/lib/src/testCompatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0AdapterTest.java new file mode 100644 index 0000000000..fe4463468a --- /dev/null +++ b/lib/src/testCompatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0AdapterTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2023 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.ktlint.compat; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class KtLintCompat0Dot48Dot0AdapterTest { + @Test + public void testDefaults(@TempDir Path path) throws IOException { + KtLintCompat0Dot48Dot0Adapter ktLintCompat0Dot48Dot0Adapter = new KtLintCompat0Dot48Dot0Adapter(); + String text = loadAndWriteText(path, "empty_class_body.kt"); + + Map userData = new HashMap<>(); + + Map editorConfigOverrideMap = new HashMap<>(); + + String formatted = ktLintCompat0Dot48Dot0Adapter.format(text, "empty_class_body.kt", false, false, userData, editorConfigOverrideMap); + assertEquals("class empty_class_body\n", formatted); + } + + @Test + public void testEditorConfigCanDisable(@TempDir Path path) throws IOException { + KtLintCompat0Dot48Dot0Adapter ktLintCompat0Dot48Dot0Adapter = new KtLintCompat0Dot48Dot0Adapter(); + String text = loadAndWriteText(path, "fails_no_semicolons.kt"); + + Map userData = new HashMap<>(); + + Map editorConfigOverrideMap = new HashMap<>(); + editorConfigOverrideMap.put("indent_style", "tab"); + editorConfigOverrideMap.put("ktlint_standard_no-semi", "disabled"); + + String formatted = ktLintCompat0Dot48Dot0Adapter.format(text, "fails_no_semicolons.kt", false, false, userData, editorConfigOverrideMap); + assertEquals("class fails_no_semicolons {\n\tval i = 0;\n}\n", formatted); + } + + private static String loadAndWriteText(Path path, String name) throws IOException { + try (InputStream is = KtLintCompat0Dot48Dot0AdapterTest.class.getResourceAsStream("/" + name)) { + Files.copy(is, path.resolve(name)); + } + return new String(Files.readAllBytes(path.resolve(name)), StandardCharsets.UTF_8); + } + +} diff --git a/lib/src/testCompatKtLint0Dot48Dot0/resources/empty_class_body.kt b/lib/src/testCompatKtLint0Dot48Dot0/resources/empty_class_body.kt new file mode 100644 index 0000000000..b84774d572 --- /dev/null +++ b/lib/src/testCompatKtLint0Dot48Dot0/resources/empty_class_body.kt @@ -0,0 +1,3 @@ +class empty_class_body { + +} diff --git a/lib/src/testCompatKtLint0Dot48Dot0/resources/fails_no_semicolons.kt b/lib/src/testCompatKtLint0Dot48Dot0/resources/fails_no_semicolons.kt new file mode 100644 index 0000000000..20ab460913 --- /dev/null +++ b/lib/src/testCompatKtLint0Dot48Dot0/resources/fails_no_semicolons.kt @@ -0,0 +1,3 @@ +class fails_no_semicolons { + val i = 0; +} diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index c5f464069f..56ed8d6c1e 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] ### Fixed * Prevent tool configurations from being resolved outside project ([#1447](https://github.com/diffplug/spotless/pull/1447) fixes [#1215](https://github.com/diffplug/spotless/issues/1215)) +* Support `ktlint` 0.48+ new rule disabling syntax ([#1456](https://github.com/diffplug/spotless/pull/1456)) fixes ([#1444](https://github.com/diffplug/spotless/issues/1444)) +### Changes +* Bump default `ktlint` version to latest `0.47.1` -> `0.48.1` ([#1456](https://github.com/diffplug/spotless/pull/1456)) ## [6.12.1] - 2023-01-02 ### Fixed diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 8a4307c2cd..40038418b7 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -4,6 +4,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Fixed +* Support `ktlint` 0.48+ new rule disabling syntax ([#1456](https://github.com/diffplug/spotless/pull/1456)) fixes ([#1444](https://github.com/diffplug/spotless/issues/1444)) +### Changes +* Bump default `ktlint` version to latest `0.47.1` -> `0.48.1` ([#1456](https://github.com/diffplug/spotless/pull/1456)) * Reduce spurious invalidations of the up-to-date index file ([#1461](https://github.com/diffplug/spotless/pull/1461)) ## [2.29.0] - 2023-01-02 diff --git a/settings.gradle b/settings.gradle index 786baa1eba..741e4b6ccc 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,7 +16,7 @@ pluginManagement { // https://github.com/radarsh/gradle-test-logger-plugin/blob/develop/CHANGELOG.md id 'com.adarshr.test-logger' version '3.2.0' // https://github.com/davidburstrom/version-compatibility-gradle-plugin/tags - id 'io.github.davidburstrom.version-compatibility' version '0.3.0' + id 'io.github.davidburstrom.version-compatibility' version '0.4.0' } } plugins { 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 94de314e0b..1be0c7b72f 100644 --- a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java @@ -139,6 +139,16 @@ void works0_48_0() { "Wildcard import"); } + @Test + void works0_48_1() { + FormatterStep step = KtLintStep.create("0.48.1", TestProvisioner.mavenCentral()); + StepHarnessWithFile.forStep(this, step) + .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic.clean") + .testResourceExceptionMsg("kotlin/ktlint/unsolvable.dirty").isEqualTo("Error on line: 1, column: 1\n" + + "rule: no-wildcard-imports\n" + + "Wildcard import"); + } + @Test void equality() { new SerializableEqualityTester() {