From 5cf7a7e5a6f57795a20d9da012a89135c173f07e Mon Sep 17 00:00:00 2001 From: Mitchell Skaggs Date: Thu, 18 May 2023 12:16:52 -0500 Subject: [PATCH 1/4] Support KtLint 0.49.0, drop KtLint 0.46.0 Currently, we work around name-mangling issues with special Kotlin classes. The root issue is tracked here: https://github.com/pinterest/ktlint/issues/2041 Also fixes the IntelliJ .editorconfig import order property to better match Eclipse formatting --- .editorconfig | 2 +- lib/build.gradle | 10 +- .../compat/KtLintCompat0Dot46Dot0Adapter.java | 119 ---------- .../compat/KtLintCompat0Dot49Dot0Adapter.java | 210 ++++++++++++++++++ .../glue/ktlint/KtlintFormatterFunc.java | 12 +- .../diffplug/spotless/kotlin/KtLintStep.java | 2 +- .../KtLintCompat0Dot49Dot0AdapterTest.java | 70 ++++++ .../resources/EmptyClassBody.kt | 3 + .../resources/FailsNoSemicolons.kt | 3 + .../spotless/kotlin/KtLintStepTest.java | 32 ++- 10 files changed, 321 insertions(+), 142 deletions(-) delete mode 100644 lib/src/compatKtLint0Dot46Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot46Dot0Adapter.java create mode 100644 lib/src/compatKtLint0Dot49Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot49Dot0Adapter.java create mode 100644 lib/src/testCompatKtLint0Dot49Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot49Dot0AdapterTest.java create mode 100644 lib/src/testCompatKtLint0Dot49Dot0/resources/EmptyClassBody.kt create mode 100644 lib/src/testCompatKtLint0Dot49Dot0/resources/FailsNoSemicolons.kt diff --git a/.editorconfig b/.editorconfig index 4042d549fd..5d0704bd2b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,7 +14,7 @@ indent_size = 2 [*.java] # Doc: https://youtrack.jetbrains.com/issue/IDEA-170643#focus=streamItem-27-3708697.0-0 -ij_java_imports_layout = java.**,|,javax.**,|,org.**,|,com.**,|,com.diffplug.**,|,* +ij_java_imports_layout = $*,|,java.**,|,javax.**,|,org.**,|,com.**,|,com.diffplug.**,|,* ij_java_use_single_class_imports = true ij_java_class_count_to_use_import_on_demand = 999 ij_java_names_count_to_use_import_on_demand = 999 diff --git a/lib/build.gradle b/lib/build.gradle index 8db911e33e..c0564e5c12 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.46.0', '0.47.0', '0.48.0', + '0.49.0', ] targetSourceSetName = 'ktlint' } @@ -96,20 +96,20 @@ dependencies { } } // ktlint - String VER_KTLINT='0.46.1' + String VER_KTLINT='0.47.1' ktlintCompileOnly "com.pinterest:ktlint:$VER_KTLINT" ktlintCompileOnly "com.pinterest.ktlint:ktlint-core:$VER_KTLINT" ktlintCompileOnly "com.pinterest.ktlint:ktlint-ruleset-experimental:$VER_KTLINT" ktlintCompileOnly "com.pinterest.ktlint:ktlint-ruleset-standard:$VER_KTLINT" - compatKtLint0Dot46Dot0CompileOnly 'com.pinterest.ktlint:ktlint-core:0.46.0' - compatKtLint0Dot46Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.46.0' - compatKtLint0Dot46Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.46.0' 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' 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' + 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' // 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/compatKtLint0Dot46Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot46Dot0Adapter.java b/lib/src/compatKtLint0Dot46Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot46Dot0Adapter.java deleted file mode 100644 index afaf2ad19f..0000000000 --- a/lib/src/compatKtLint0Dot46Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot46Dot0Adapter.java +++ /dev/null @@ -1,119 +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 java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; -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.RuleSet; -import com.pinterest.ktlint.core.api.DefaultEditorConfigProperties; -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 KtLintCompat0Dot46Dot0Adapter 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(); - - final List rulesets = new ArrayList<>(); - rulesets.add(new StandardRuleSetProvider().get()); - - if (useExperimental) { - rulesets.add(new ExperimentalRuleSetProvider().get()); - } - - EditorConfigOverride editorConfigOverride; - if (editorConfigOverrideMap.isEmpty()) { - editorConfigOverride = EditorConfigOverride.Companion.getEmptyEditorConfigOverride(); - } else { - editorConfigOverride = createEditorConfigOverride(rulesets, editorConfigOverrideMap); - } - - return KtLint.INSTANCE.format(new KtLint.ExperimentalParams( - path.toFile().getAbsolutePath(), - text, - rulesets, - userData, - formatterCallback, - isScript, - editorConfigPath == null ? null : editorConfigPath.toFile().getAbsolutePath(), - false, - editorConfigOverride, - false)); - } - - /** - * Create EditorConfigOverride from user provided parameters. - * Calling this method requires KtLint 0.45.2. - */ - private static EditorConfigOverride createEditorConfigOverride(final List rulesets, Map editorConfigOverrideMap) { - // Get properties from rules in the rule sets - Stream> ruleProperties = rulesets.stream() - .flatMap(ruleSet -> Arrays.stream(ruleSet.getRules())) - .filter(rule -> rule instanceof UsesEditorConfigProperties) - .flatMap(rule -> ((UsesEditorConfigProperties) rule).getEditorConfigProperties().stream()); - - // Create a mapping of properties to their names based on rule properties and default properties - Map> supportedProperties = Stream - .concat(ruleProperties, DefaultEditorConfigProperties.INSTANCE.getEditorConfigProperties().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/compatKtLint0Dot49Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot49Dot0Adapter.java b/lib/src/compatKtLint0Dot49Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot49Dot0Adapter.java new file mode 100644 index 0000000000..86ca69c352 --- /dev/null +++ b/lib/src/compatKtLint0Dot49Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot49Dot0Adapter.java @@ -0,0 +1,210 @@ +/* + * 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.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +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.RuleProvider; +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 KtLintCompat0Dot49Dot0Adapter implements KtLintCompatAdapter { + + private static final Logger logger = LoggerFactory.getLogger(KtLintCompat0Dot49Dot0Adapter.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); + } + + private static final Method RULEID_METHOD; + private static final Method CREATE_RULESET_EXECUTION_METHOD; + private static final Method CREATE_RULE_EXECUTION_METHOD; + + static { + try { + RULEID_METHOD = LintError.class.getMethod("getRuleId-6XN97os"); + CREATE_RULESET_EXECUTION_METHOD = RuleExecutionEditorConfigPropertyKt.class.getMethod("createRuleSetExecutionEditorConfigProperty-fqiwTpU", String.class, RuleExecution.class); + CREATE_RULE_EXECUTION_METHOD = RuleExecutionEditorConfigPropertyKt.class.getMethod("createRuleExecutionEditorConfigProperty-U7AdEiY", String.class, RuleExecution.class); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + private static String getRuleId(LintError lint) { + try { + return (String) RULEID_METHOD.invoke(lint); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private static EditorConfigProperty createRuleSetExecution(String id, RuleExecution execution) { + try { + return (EditorConfigProperty) CREATE_RULESET_EXECUTION_METHOD.invoke(null, id, execution); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private static EditorConfigProperty createRuleExecution(String id, RuleExecution execution) { + try { + return (EditorConfigProperty) CREATE_RULE_EXECUTION_METHOD.invoke(null, id, execution); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + static class FormatterCallback implements Function2 { + + @Override + public Unit invoke(LintError lint, Boolean corrected) { + if (!corrected) { + KtLintCompatReporting.report(lint.getLine(), lint.getCol(), getRuleId(lint), 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); + } + + return new KtLintRuleEngine( + allRuleProviders, + editorConfig, + editorConfigOverride, + 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 {ruleset} + String qualifiedRuleId = parts[0] + ":"; + property = createRuleSetExecution(qualifiedRuleId, RuleExecution.disabled); + } else { + // convert ktlint_{ruleset}_{rulename} to {ruleset}:{rulename} + String qualifiedRuleId = parts[0] + ":" + parts[1]; + property = createRuleExecution(qualifiedRuleId, 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 02ff5355e3..f6f4203fef 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 @@ -38,15 +38,17 @@ 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 >= 48) { + 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) { // ExperimentalParams lost two constructor arguments, EditorConfigProperty moved to its own class this.adapter = new KtLintCompat0Dot48Dot0Adapter(); - } else if (minorVersion == 47) { + } else { // rename RuleSet to RuleProvider this.adapter = new KtLintCompat0Dot47Dot0Adapter(); - } else { - // DefaultEditorConfigProperties.INSTANCE.getDefaultEditorConfigProperties() renamed to .getEditorConfigProperties() - this.adapter = new KtLintCompat0Dot46Dot0Adapter(); } 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 0d75460902..6e82538b04 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.48.2"; + private static final String DEFAULT_VERSION = "0.49.1"; static final String NAME = "ktlint"; static final String PACKAGE = "com.pinterest"; static final String MAVEN_COORDINATE = PACKAGE + ":ktlint:"; diff --git a/lib/src/testCompatKtLint0Dot49Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot49Dot0AdapterTest.java b/lib/src/testCompatKtLint0Dot49Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot49Dot0AdapterTest.java new file mode 100644 index 0000000000..ede67e0174 --- /dev/null +++ b/lib/src/testCompatKtLint0Dot49Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot49Dot0AdapterTest.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 KtLintCompat0Dot49Dot0AdapterTest { + @Test + public void testDefaults(@TempDir Path path) throws IOException { + KtLintCompat0Dot49Dot0Adapter ktLintCompat0Dot49Dot0Adapter = new KtLintCompat0Dot49Dot0Adapter(); + 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 = ktLintCompat0Dot49Dot0Adapter.format(text, filePath, false, false, null, userData, editorConfigOverrideMap); + assertEquals("class EmptyClassBody\n", formatted); + } + + @Test + public void testEditorConfigCanDisable(@TempDir Path path) throws IOException { + KtLintCompat0Dot49Dot0Adapter ktLintCompat0Dot49Dot0Adapter = new KtLintCompat0Dot49Dot0Adapter(); + 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 = ktLintCompat0Dot49Dot0Adapter.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 = KtLintCompat0Dot49Dot0AdapterTest.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/testCompatKtLint0Dot49Dot0/resources/EmptyClassBody.kt b/lib/src/testCompatKtLint0Dot49Dot0/resources/EmptyClassBody.kt new file mode 100644 index 0000000000..7da53fb78d --- /dev/null +++ b/lib/src/testCompatKtLint0Dot49Dot0/resources/EmptyClassBody.kt @@ -0,0 +1,3 @@ +class EmptyClassBody { + +} diff --git a/lib/src/testCompatKtLint0Dot49Dot0/resources/FailsNoSemicolons.kt b/lib/src/testCompatKtLint0Dot49Dot0/resources/FailsNoSemicolons.kt new file mode 100644 index 0000000000..4cf05ceacf --- /dev/null +++ b/lib/src/testCompatKtLint0Dot49Dot0/resources/FailsNoSemicolons.kt @@ -0,0 +1,3 @@ +class FailsNoSemicolons { + val i = 0; +} 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 6700be168d..9af6685906 100644 --- a/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/kotlin/KtLintStepTest.java @@ -31,20 +31,10 @@ void behavior() { .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" + + "rule: standard:no-wildcard-imports\n" + "Wildcard import"); } - @Test - void works0_46_0() { - FormatterStep step = KtLintStep.create("0.46.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" + - "rule: no-wildcard-imports\n" + - "Wildcard import"); - } - @Test void works0_47_0() { FormatterStep step = KtLintStep.create("0.47.0", TestProvisioner.mavenCentral()); @@ -85,6 +75,26 @@ void works0_48_1() { "Wildcard import"); } + @Test + 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") + .testResourceExceptionMsg("kotlin/ktlint/unsolvable.dirty").isEqualTo("Error on line: 1, column: 1\n" + + "rule: standard:no-wildcard-imports\n" + + "Wildcard import"); + } + + @Test + 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") + .testResourceExceptionMsg("kotlin/ktlint/unsolvable.dirty").isEqualTo("Error on line: 1, column: 1\n" + + "rule: standard:no-wildcard-imports\n" + + "Wildcard import"); + } + @Test void equality() { new SerializableEqualityTester() { From a66ef3db9cc9b7b41e481394a84f2e7f8e32a39a Mon Sep 17 00:00:00 2001 From: Mitchell Skaggs Date: Thu, 18 May 2023 12:35:50 -0500 Subject: [PATCH 2/4] Add ktlint 0.49.1 update to changelog --- CHANGES.md | 1 + plugin-gradle/CHANGES.md | 1 + plugin-maven/CHANGES.md | 1 + 3 files changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 9d65dfd9b5..3ab7fc3745 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Fixed a regression which changed the import sorting order in `googleJavaFormat` introduced in `2.38.0`. ([#1680](https://github.com/diffplug/spotless/pull/1680)) ### Changes * Bump default sortpom version to latest `3.0.0` -> `3.2.1`. ([#1675](https://github.com/diffplug/spotless/pull/1675)) +* Bump default `ktlint` version to latest `0.48.2` -> `0.49.1`.([#1696](https://github.com/diffplug/spotless/issues/1696)) ## [2.38.0] - 2023-04-06 ### Added diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index d064173af6..a5f9d8c6c6 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -11,6 +11,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Fixed a regression which changed the import sorting order in `googleJavaFormat` introduced in `6.18.0`. ([#1680](https://github.com/diffplug/spotless/pull/1680)) ### Changes * Bump default sortpom version to latest `3.0.0` -> `3.2.1`. ([#1675](https://github.com/diffplug/spotless/pull/1675)) +* Bump default `ktlint` version to latest `0.48.2` -> `0.49.1`.([#1696](https://github.com/diffplug/spotless/issues/1696)) ## [6.18.0] - 2023-04-06 ### Added diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 5777493c41..e006f3462d 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -11,6 +11,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * Fixed a regression which changed the import sorting order in `googleJavaFormat` introduced in `2.36.0`. ([#1680](https://github.com/diffplug/spotless/pull/1680)) ### Changes * Bump default sortpom version to latest `3.0.0` -> `3.2.1`. ([#1675](https://github.com/diffplug/spotless/pull/1675)) +* Bump default `ktlint` version to latest `0.48.2` -> `0.49.1`.([#1696](https://github.com/diffplug/spotless/issues/1696)) ## [2.36.0] - 2023-04-06 ### Added From 88845df2179c3ea457e67eff39f7b3541908363c Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Fri, 19 May 2023 09:35:04 -0700 Subject: [PATCH 3/4] Tweak changelogs. --- CHANGES.md | 1 + plugin-gradle/CHANGES.md | 1 + plugin-maven/CHANGES.md | 1 + 3 files changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 3ab7fc3745..094f5b43f0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ### Changes * Bump default sortpom version to latest `3.0.0` -> `3.2.1`. ([#1675](https://github.com/diffplug/spotless/pull/1675)) * Bump default `ktlint` version to latest `0.48.2` -> `0.49.1`.([#1696](https://github.com/diffplug/spotless/issues/1696)) + * Dropped support for `ktlint 0.46.x` following our policy of supporting two breaking changes at a time. ## [2.38.0] - 2023-04-06 ### Added diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index a5f9d8c6c6..f140151867 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -12,6 +12,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ### Changes * Bump default sortpom version to latest `3.0.0` -> `3.2.1`. ([#1675](https://github.com/diffplug/spotless/pull/1675)) * Bump default `ktlint` version to latest `0.48.2` -> `0.49.1`.([#1696](https://github.com/diffplug/spotless/issues/1696)) + * Dropped support for `ktlint 0.46.x` following our policy of supporting two breaking changes at a time. ## [6.18.0] - 2023-04-06 ### Added diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index e006f3462d..154b2becaa 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -12,6 +12,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ### Changes * Bump default sortpom version to latest `3.0.0` -> `3.2.1`. ([#1675](https://github.com/diffplug/spotless/pull/1675)) * Bump default `ktlint` version to latest `0.48.2` -> `0.49.1`.([#1696](https://github.com/diffplug/spotless/issues/1696)) + * Dropped support for `ktlint 0.46.x` following our policy of supporting two breaking changes at a time. ## [2.36.0] - 2023-04-06 ### Added From 87efad89426314c4969807fcc3b5725dddd8c642 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Sat, 20 May 2023 16:07:56 -0700 Subject: [PATCH 4/4] Simplify ktlint build. --- lib/build.gradle | 5 ----- .../diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java | 3 --- 2 files changed, 8 deletions(-) diff --git a/lib/build.gradle b/lib/build.gradle index c0564e5c12..058e5f4132 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -96,11 +96,6 @@ dependencies { } } // ktlint - String VER_KTLINT='0.47.1' - ktlintCompileOnly "com.pinterest:ktlint:$VER_KTLINT" - ktlintCompileOnly "com.pinterest.ktlint:ktlint-core:$VER_KTLINT" - ktlintCompileOnly "com.pinterest.ktlint:ktlint-ruleset-experimental:$VER_KTLINT" - ktlintCompileOnly "com.pinterest.ktlint:ktlint-ruleset-standard:$VER_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' 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 f6f4203fef..fba855bb9a 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 @@ -19,8 +19,6 @@ import java.nio.file.Path; import java.util.Map; -import org.jetbrains.annotations.NotNull; - import com.diffplug.spotless.FileSignature; import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.glue.ktlint.compat.*; @@ -29,7 +27,6 @@ public class KtlintFormatterFunc implements FormatterFunc.NeedsFile { private final Map userData; private final boolean isScript; - @NotNull private final KtLintCompatAdapter adapter; private final boolean useExperimental; private final FileSignature editorConfigPath;