diff --git a/CHANGES.md b/CHANGES.md index ab72dc3ab0..a0a6b309ee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,9 @@ 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 +* Bump default `ktlint` version to latest `0.49.1` -> `0.50.0`.([#1741](https://github.com/diffplug/spotless/issues/1741)) + * Dropped support for `ktlint 0.47.x` following our policy of supporting two breaking changes at a time. ### Changes * Bump default `cleanthat` version to latest `2.13` -> `2.16`. ([#1725](https://github.com/diffplug/spotless/pull/1725)) ### Fixed diff --git a/lib/build.gradle b/lib/build.gradle index a9d5181569..36921698f0 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -44,9 +44,9 @@ versionCompatibility { // we will support no more than 2 breaking changes at a time = 3 incompatible versions // we will try to drop down to only one version if a stable API can be maintained for a full year versions = [ - '0.47.0', '0.48.0', '0.49.0', + '0.50.0', ] targetSourceSetName = 'ktlint' } @@ -95,16 +95,18 @@ dependencies { strictly '1.7' // for JDK 8 compatibility } } - // ktlint - 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' + // ktlint oldest supported version 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' + // ktlint previous supported version compatKtLint0Dot49Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-rule-engine:0.49.0' compatKtLint0Dot49Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.49.0' compatKtLint0Dot49Dot0CompileAndTestOnly 'org.slf4j:slf4j-api:2.0.0' + // ktlint latest supported version + compatKtLint0Dot50Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-rule-engine:0.50.0' + compatKtLint0Dot50Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.50.0' + compatKtLint0Dot50Dot0CompileAndTestOnly 'org.slf4j:slf4j-api:2.0.0' // palantirJavaFormat palantirJavaFormatCompileOnly 'com.palantir.javaformat:palantir-java-format:1.1.0' // this version needs to stay compilable against Java 8 for CI Job testNpm // scalafmt diff --git a/lib/src/compatKtLint0Dot47Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot47Dot0Adapter.java b/lib/src/compatKtLint0Dot47Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot47Dot0Adapter.java deleted file mode 100644 index 0a38730b6a..0000000000 --- a/lib/src/compatKtLint0Dot47Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot47Dot0Adapter.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2022-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 java.util.Collections.emptySet; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.pinterest.ktlint.core.KtLint; -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.ruleset.experimental.ExperimentalRuleSetProvider; -import com.pinterest.ktlint.ruleset.standard.StandardRuleSetProvider; - -import kotlin.Pair; -import kotlin.Unit; -import kotlin.jvm.functions.Function2; - -public class KtLintCompat0Dot47Dot0Adapter implements KtLintCompatAdapter { - - 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; - } - } - - @Override - public String format(final String text, Path path, final boolean isScript, - final boolean useExperimental, - Path editorConfigPath, final Map userData, - final Map editorConfigOverrideMap) { - final FormatterCallback formatterCallback = new FormatterCallback(); - - Set allRuleProviders = new LinkedHashSet<>( - new StandardRuleSetProvider().getRuleProviders()); - if (useExperimental) { - allRuleProviders.addAll(new ExperimentalRuleSetProvider().getRuleProviders()); - } - - EditorConfigOverride editorConfigOverride; - if (editorConfigOverrideMap.isEmpty()) { - editorConfigOverride = new EditorConfigOverride(); - } else { - editorConfigOverride = createEditorConfigOverride(allRuleProviders.stream().map( - RuleProvider::createNewRuleInstance).collect( - Collectors.toList()), - editorConfigOverrideMap); - } - - EditorConfigDefaults editorConfig; - if (editorConfigPath == null || !Files.exists(editorConfigPath)) { - editorConfig = EditorConfigDefaults.Companion.getEmptyEditorConfigDefaults(); - } else { - editorConfig = EditorConfigDefaults.Companion.load(editorConfigPath); - } - - return KtLint.INSTANCE.format(new KtLint.ExperimentalParams( - path.toFile().getAbsolutePath(), - text, - emptySet(), - allRuleProviders, - userData, - formatterCallback, - isScript, - null, - false, - editorConfig, - editorConfigOverride, - false)); - } - - /** - * Create EditorConfigOverride from user provided parameters. - * Calling this method requires KtLint 0.45.2. - */ - private static EditorConfigOverride createEditorConfigOverride(final List rules, Map editorConfigOverrideMap) { - // Get properties from rules in the rule sets - Stream> ruleProperties = rules.stream() - .filter(rule -> rule instanceof UsesEditorConfigProperties) - .flatMap(rule -> ((UsesEditorConfigProperties) rule).getEditorConfigProperties().stream()); - - // get complete list of supported properties in DefaultEditorConfigProperties.INSTANCE - List> editorConfigProperties = new ArrayList<>(DefaultEditorConfigProperties.INSTANCE.getEditorConfigProperties()); - editorConfigProperties.add(DefaultEditorConfigProperties.INSTANCE.getKtlintDisabledRulesProperty()); - - // Create a mapping of properties to their names based on rule properties and default properties - Map> supportedProperties = Stream - .concat(ruleProperties, editorConfigProperties.stream()) - .distinct() - .collect(Collectors.toMap(property -> property.getType().getName(), property -> property)); - - // Create config properties based on provided property names and values - @SuppressWarnings("unchecked") - Pair, ?>[] properties = editorConfigOverrideMap.entrySet().stream() - .map(entry -> { - UsesEditorConfigProperties.EditorConfigProperty property = supportedProperties.get(entry.getKey()); - if (property != null) { - return new Pair<>(property, entry.getValue()); - } else { - return null; - } - }) - .filter(Objects::nonNull) - .toArray(Pair[]::new); - - return EditorConfigOverride.Companion.from(properties); - } -} diff --git a/lib/src/compatKtLint0Dot50Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot50Dot0Adapter.java b/lib/src/compatKtLint0Dot50Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot50Dot0Adapter.java new file mode 100644 index 0000000000..642e15adc2 --- /dev/null +++ b/lib/src/compatKtLint0Dot50Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot50Dot0Adapter.java @@ -0,0 +1,173 @@ +/* + * 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 java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.pinterest.ktlint.rule.engine.api.Code; +import com.pinterest.ktlint.rule.engine.api.EditorConfigDefaults; +import com.pinterest.ktlint.rule.engine.api.EditorConfigOverride; +import com.pinterest.ktlint.rule.engine.api.KtLintRuleEngine; +import com.pinterest.ktlint.rule.engine.api.LintError; +import com.pinterest.ktlint.rule.engine.core.api.Rule; +import com.pinterest.ktlint.rule.engine.core.api.RuleId; +import com.pinterest.ktlint.rule.engine.core.api.RuleProvider; +import com.pinterest.ktlint.rule.engine.core.api.RuleSetId; +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.CodeStyleEditorConfigPropertyKt; +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.EditorConfigProperty; +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.EndOfLinePropertyKt; +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.IndentSizeEditorConfigPropertyKt; +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.IndentStyleEditorConfigPropertyKt; +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.InsertFinalNewLineEditorConfigPropertyKt; +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.MaxLineLengthEditorConfigPropertyKt; +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.RuleExecution; +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.RuleExecutionEditorConfigPropertyKt; +import com.pinterest.ktlint.ruleset.standard.StandardRuleSetProvider; + +import kotlin.Pair; +import kotlin.Unit; +import kotlin.jvm.functions.Function2; + +public class KtLintCompat0Dot50Dot0Adapter implements KtLintCompatAdapter { + + private static final Logger logger = LoggerFactory.getLogger(KtLintCompat0Dot50Dot0Adapter.class); + + private static final List> DEFAULT_EDITOR_CONFIG_PROPERTIES; + + static { + List> list = new ArrayList<>(); + list.add(CodeStyleEditorConfigPropertyKt.getCODE_STYLE_PROPERTY()); + list.add(EndOfLinePropertyKt.getEND_OF_LINE_PROPERTY()); + list.add(IndentSizeEditorConfigPropertyKt.getINDENT_SIZE_PROPERTY()); + list.add(IndentStyleEditorConfigPropertyKt.getINDENT_STYLE_PROPERTY()); + list.add(InsertFinalNewLineEditorConfigPropertyKt.getINSERT_FINAL_NEWLINE_PROPERTY()); + list.add(MaxLineLengthEditorConfigPropertyKt.getMAX_LINE_LENGTH_PROPERTY()); + list.add(RuleExecutionEditorConfigPropertyKt.getEXPERIMENTAL_RULES_EXECUTION_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().getValue(), lint.getDetail()); + } + return Unit.INSTANCE; + } + } + + @Override + public String format(final String text, Path path, final boolean isScript, + final boolean useExperimental, + Path editorConfigPath, final Map userData, + final Map editorConfigOverrideMap) { + final FormatterCallback formatterCallback = new FormatterCallback(); + + Set allRuleProviders = new LinkedHashSet<>( + new StandardRuleSetProvider().getRuleProviders()); + + // TODO: Should we keep `useExperimental` now that ktlint uses an EditorConfig property for this purpose? + if (useExperimental) { + String experimentalRulesPropertyName = RuleExecutionEditorConfigPropertyKt.getEXPERIMENTAL_RULES_EXECUTION_PROPERTY().getName(); + Object experimentalOverride = editorConfigOverrideMap.get(experimentalRulesPropertyName); + if (experimentalOverride != null) { + logger.warn("`useExperimental` parameter is `true` and `ktlint_experimental` property is set, `useExperimental` will take priority!"); + editorConfigOverrideMap.put(experimentalRulesPropertyName, "enabled"); + } + } + + EditorConfigOverride editorConfigOverride; + if (editorConfigOverrideMap.isEmpty()) { + editorConfigOverride = EditorConfigOverride.Companion.getEMPTY_EDITOR_CONFIG_OVERRIDE(); + } else { + editorConfigOverride = createEditorConfigOverride(allRuleProviders.stream().map( + RuleProvider::createNewRuleInstance).collect(Collectors.toList()), + editorConfigOverrideMap); + } + EditorConfigDefaults editorConfig; + if (editorConfigPath == null || !Files.exists(editorConfigPath)) { + editorConfig = EditorConfigDefaults.Companion.getEMPTY_EDITOR_CONFIG_DEFAULTS(); + } else { + editorConfig = EditorConfigDefaults.Companion.load(editorConfigPath, Collections.emptySet()); + } + + return new KtLintRuleEngine( + allRuleProviders, + editorConfig, + editorConfigOverride, + true, + false, + path.getFileSystem()) + .format(Code.Companion.fromPath(path), formatterCallback); + } + + /** + * Create EditorConfigOverride from user provided parameters. + */ + private static EditorConfigOverride createEditorConfigOverride(final List rules, Map editorConfigOverrideMap) { + // Get properties from rules in the rule sets + Stream> ruleProperties = rules.stream() + .flatMap(rule -> rule.getUsesEditorConfigProperties().stream()); + + // Create a mapping of properties to their names based on rule properties and default properties + Map> supportedProperties = Stream + .concat(ruleProperties, DEFAULT_EDITOR_CONFIG_PROPERTIES.stream()) + .distinct() + .collect(Collectors.toMap(EditorConfigProperty::getName, property -> property)); + + // Create config properties based on provided property names and values + @SuppressWarnings("unchecked") + Pair, ?>[] properties = editorConfigOverrideMap.entrySet().stream() + .map(entry -> { + 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 RuleSetId + RuleSetId id = new RuleSetId(parts[0]); + property = RuleExecutionEditorConfigPropertyKt.createRuleSetExecutionEditorConfigProperty(id, RuleExecution.disabled); + } else { + // convert ktlint_{ruleset}_{rulename} to RuleId + RuleId id = new RuleId(parts[0] + ":" + parts[1]); + property = RuleExecutionEditorConfigPropertyKt.createRuleExecutionEditorConfigProperty(id, RuleExecution.disabled); + } + return new Pair<>(property, entry.getValue()); + } else { + return null; + } + }) + .filter(Objects::nonNull) + .toArray(Pair[]::new); + + return EditorConfigOverride.Companion.from(properties); + } +} 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 fba855bb9a..9f773d4016 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 @@ -35,17 +35,19 @@ public class KtlintFormatterFunc implements FormatterFunc.NeedsFile { public KtlintFormatterFunc(String version, boolean isScript, boolean useExperimental, FileSignature editorConfigPath, Map userData, Map editorConfigOverrideMap) { int minorVersion = Integer.parseInt(version.split("\\.")[1]); - if (minorVersion >= 49) { + if (minorVersion >= 50) { + // Fixed `RuleId` and `RuleSetId` issues + // New argument to `EditorConfigDefaults.Companion.load(...)` for custom property type parsing + // New argument to `new KtLintRuleEngine(...)` to fail on usage of `treeCopyHandler` extension point + this.adapter = new KtLintCompat0Dot50Dot0Adapter(); + } else if (minorVersion == 49) { // Packages and modules moved around (`ktlint-core` -> `ktlint-rule-engine`) // Experimental ruleset was replaced by implementing `Rule.Experimental` and checking the `ktlint_experimental` `.editorconfig` property // `RuleId` and `RuleSetId` became inline classes (mangled to be unrepresentable in Java source code, so reflection is needed), tracked here: https://github.com/pinterest/ktlint/issues/2041 this.adapter = new KtLintCompat0Dot49Dot0Adapter(); - } else if (minorVersion == 48) { + } else { // ExperimentalParams lost two constructor arguments, EditorConfigProperty moved to its own class this.adapter = new KtLintCompat0Dot48Dot0Adapter(); - } else { - // rename RuleSet to RuleProvider - this.adapter = new KtLintCompat0Dot47Dot0Adapter(); } this.editorConfigPath = editorConfigPath; this.useExperimental = useExperimental; 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 6e82538b04..a844a93bff 100644 --- a/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java +++ b/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java @@ -36,7 +36,7 @@ public class KtLintStep { // prevent direct instantiation private KtLintStep() {} - private static final String DEFAULT_VERSION = "0.49.1"; + private static final String DEFAULT_VERSION = "0.50.0"; static final String NAME = "ktlint"; static final String PACKAGE = "com.pinterest"; static final String MAVEN_COORDINATE = PACKAGE + ":ktlint:"; diff --git a/lib/src/testCompatKtLint0Dot50Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot50Dot0AdapterTest.java b/lib/src/testCompatKtLint0Dot50Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot50Dot0AdapterTest.java new file mode 100644 index 0000000000..575515a66e --- /dev/null +++ b/lib/src/testCompatKtLint0Dot50Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot50Dot0AdapterTest.java @@ -0,0 +1,70 @@ +/* + * 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.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class KtLintCompat0Dot50Dot0AdapterTest { + @Test + public void testDefaults(@TempDir Path path) throws IOException { + KtLintCompat0Dot50Dot0Adapter KtLintCompat0Dot50Dot0Adapter = new KtLintCompat0Dot50Dot0Adapter(); + String text = loadAndWriteText(path, "EmptyClassBody.kt"); + final Path filePath = Paths.get(path.toString(), "EmptyClassBody.kt"); + + Map userData = new HashMap<>(); + + Map editorConfigOverrideMap = new HashMap<>(); + + String formatted = KtLintCompat0Dot50Dot0Adapter.format(text, filePath, false, false, null, userData, editorConfigOverrideMap); + assertEquals("class EmptyClassBody\n", formatted); + } + + @Test + public void testEditorConfigCanDisable(@TempDir Path path) throws IOException { + KtLintCompat0Dot50Dot0Adapter KtLintCompat0Dot50Dot0Adapter = new KtLintCompat0Dot50Dot0Adapter(); + String text = loadAndWriteText(path, "FailsNoSemicolons.kt"); + final Path filePath = Paths.get(path.toString(), "FailsNoSemicolons.kt"); + + Map userData = new HashMap<>(); + + Map editorConfigOverrideMap = new HashMap<>(); + editorConfigOverrideMap.put("indent_style", "tab"); + editorConfigOverrideMap.put("ktlint_standard_no-semi", "disabled"); + + String formatted = KtLintCompat0Dot50Dot0Adapter.format(text, filePath, false, false, null, userData, editorConfigOverrideMap); + assertEquals("class FailsNoSemicolons {\n\tval i = 0;\n}\n", formatted); + } + + private static String loadAndWriteText(Path path, String name) throws IOException { + try (InputStream is = KtLintCompat0Dot50Dot0AdapterTest.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/testCompatKtLint0Dot50Dot0/resources/EmptyClassBody.kt b/lib/src/testCompatKtLint0Dot50Dot0/resources/EmptyClassBody.kt new file mode 100644 index 0000000000..7da53fb78d --- /dev/null +++ b/lib/src/testCompatKtLint0Dot50Dot0/resources/EmptyClassBody.kt @@ -0,0 +1,3 @@ +class EmptyClassBody { + +} diff --git a/lib/src/testCompatKtLint0Dot50Dot0/resources/FailsNoSemicolons.kt b/lib/src/testCompatKtLint0Dot50Dot0/resources/FailsNoSemicolons.kt new file mode 100644 index 0000000000..4cf05ceacf --- /dev/null +++ b/lib/src/testCompatKtLint0Dot50Dot0/resources/FailsNoSemicolons.kt @@ -0,0 +1,3 @@ +class FailsNoSemicolons { + val i = 0; +} diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 744c6efce7..af7d966755 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -3,7 +3,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`). ## [Unreleased] - +### Added +* Bump default `ktlint` version to latest `0.49.1` -> `0.50.0`.([#1741](https://github.com/diffplug/spotless/issues/1741)) + * Dropped support for `ktlint 0.47.x` following our policy of supporting two breaking changes at a time. ### Fixed * Correctly support the syntax ``` diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index c19cc804af..db7fff9851 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -5,6 +5,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * Support pass skip (`-Dspotless.skip=true`) from command-line. ([#1729](https://github.com/diffplug/spotless/pull/1729)) +* Bump default `ktlint` version to latest `0.49.1` -> `0.50.0`.([#1741](https://github.com/diffplug/spotless/issues/1741)) + * Dropped support for `ktlint 0.47.x` following our policy of supporting two breaking changes at a time. ### Fixed * Update documented default `semanticSort` to `false`. ([#1728](https://github.com/diffplug/spotless/pull/1728)) diff --git a/testlib/src/main/resources/kotlin/ktlint/basic-old.clean b/testlib/src/main/resources/kotlin/ktlint/basic-old.clean new file mode 100644 index 0000000000..fd5371bed2 --- /dev/null +++ b/testlib/src/main/resources/kotlin/ktlint/basic-old.clean @@ -0,0 +1,5 @@ +fun main() { + fun name() { a(); return b } + println(";") + println() +} diff --git a/testlib/src/main/resources/kotlin/ktlint/basic.clean b/testlib/src/main/resources/kotlin/ktlint/basic.clean index fd5371bed2..b727a7d016 100644 --- a/testlib/src/main/resources/kotlin/ktlint/basic.clean +++ b/testlib/src/main/resources/kotlin/ktlint/basic.clean @@ -1,5 +1,8 @@ fun main() { - fun name() { a(); return b } + fun name() { + a() + return b + } println(";") println() } 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 9af6685906..5b62eeed48 100644 --- a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java @@ -25,59 +25,48 @@ class KtLintStepTest extends ResourceHarness { @Test - void behavior() { - FormatterStep step = KtLintStep.create(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: standard:no-wildcard-imports\n" + - "Wildcard import"); - } - - @Test - void works0_47_0() { - FormatterStep step = KtLintStep.create("0.47.0", TestProvisioner.mavenCentral()); + void works0_48_0() { + FormatterStep step = KtLintStep.create("0.48.0", TestProvisioner.mavenCentral()); StepHarnessWithFile.forStep(this, step) - .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic.clean") + .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic-old.clean") .testResourceExceptionMsg("kotlin/ktlint/unsolvable.dirty").isEqualTo("Error on line: 1, column: 1\n" + "rule: no-wildcard-imports\n" + "Wildcard import"); } @Test - void works0_47_1() { - FormatterStep step = KtLintStep.create("0.47.1", TestProvisioner.mavenCentral()); + 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") + .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic-old.clean") .testResourceExceptionMsg("kotlin/ktlint/unsolvable.dirty").isEqualTo("Error on line: 1, column: 1\n" + "rule: no-wildcard-imports\n" + "Wildcard import"); } @Test - void works0_48_0() { - FormatterStep step = KtLintStep.create("0.48.0", TestProvisioner.mavenCentral()); + void works0_49_0() { + FormatterStep step = KtLintStep.create("0.49.0", TestProvisioner.mavenCentral()); StepHarnessWithFile.forStep(this, step) - .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic.clean") + .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic-old.clean") .testResourceExceptionMsg("kotlin/ktlint/unsolvable.dirty").isEqualTo("Error on line: 1, column: 1\n" + - "rule: no-wildcard-imports\n" + + "rule: standard:no-wildcard-imports\n" + "Wildcard import"); } @Test - void works0_48_1() { - FormatterStep step = KtLintStep.create("0.48.1", TestProvisioner.mavenCentral()); + void works0_49_1() { + FormatterStep step = KtLintStep.create("0.49.1", TestProvisioner.mavenCentral()); StepHarnessWithFile.forStep(this, step) - .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic.clean") + .testResource("kotlin/ktlint/basic.dirty", "kotlin/ktlint/basic-old.clean") .testResourceExceptionMsg("kotlin/ktlint/unsolvable.dirty").isEqualTo("Error on line: 1, column: 1\n" + - "rule: no-wildcard-imports\n" + + "rule: standard:no-wildcard-imports\n" + "Wildcard import"); } @Test - void works0_49_0() { - FormatterStep step = KtLintStep.create("0.49.0", TestProvisioner.mavenCentral()); + void works0_50_0() { + FormatterStep step = KtLintStep.create("0.50.0", 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" + @@ -86,8 +75,8 @@ void works0_49_0() { } @Test - void works0_49_1() { - FormatterStep step = KtLintStep.create("0.49.1", TestProvisioner.mavenCentral()); + void behavior() { + FormatterStep step = KtLintStep.create(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" +