From d04d85ea9578d301413a6b6f6f552f9dd36edaff Mon Sep 17 00:00:00 2001 From: Artur Bosch Date: Sat, 24 Sep 2022 15:28:30 +0200 Subject: [PATCH] Differentiate between correctable and non-correctable KtLint rules (#5324) * Differentiate between correctable and non-correctable KtLint rules * Split testcases into separate test functions --- .../detekt/formatting/FormattingRule.kt | 11 ++- .../formatting/wrappers/EnumEntryNameCase.kt | 2 + .../detekt/formatting/wrappers/Filename.kt | 2 + .../formatting/wrappers/ImportOrdering.kt | 2 + .../detekt/formatting/wrappers/Indentation.kt | 2 + .../formatting/wrappers/MaximumLineLength.kt | 2 + .../formatting/wrappers/NoWildcardImports.kt | 2 + .../detekt/formatting/wrappers/PackageName.kt | 2 + .../RulesWhichCantBeCorrectedSpec.kt | 85 +++++++++++++++++++ 9 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/RulesWhichCantBeCorrectedSpec.kt diff --git a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/FormattingRule.kt b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/FormattingRule.kt index defc385ea1e..03dceaa7811 100644 --- a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/FormattingRule.kt +++ b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/FormattingRule.kt @@ -7,6 +7,7 @@ import com.pinterest.ktlint.core.api.DefaultEditorConfigProperties.codeStyleSetP import com.pinterest.ktlint.core.api.UsesEditorConfigProperties import io.github.detekt.psi.fileName import io.github.detekt.psi.toFilePath +import io.gitlab.arturbosch.detekt.api.CodeSmell import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.api.CorrectableCodeSmell import io.gitlab.arturbosch.detekt.api.Debt @@ -47,6 +48,9 @@ abstract class FormattingRule(config: Config) : Rule(config) { private var positionByOffset: (offset: Int) -> Pair by SingleAssign() private var root: KtFile by SingleAssign() + // KtLint has rules which prompts the user to manually correct issues e.g. Filename and PackageName. + protected open fun canBeCorrectedByKtLint(message: String): Boolean = true + protected fun issueFor(description: String) = Issue(javaClass.simpleName, Severity.Style, description, Debt.FIVE_MINS) @@ -102,7 +106,12 @@ abstract class FormattingRule(config: Config) : Rule(config) { ?.plus(".") .orEmpty() val entity = Entity("", "$packageName${root.fileName}:$line", location, root) - report(CorrectableCodeSmell(issue, entity, message, autoCorrectEnabled = autoCorrect)) + + if (canBeCorrectedByKtLint(message)) { + report(CorrectableCodeSmell(issue, entity, message, autoCorrectEnabled = autoCorrect)) + } else { + report(CodeSmell(issue, entity, message)) + } } } diff --git a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/EnumEntryNameCase.kt b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/EnumEntryNameCase.kt index 5a17c111741..4b9da825332 100644 --- a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/EnumEntryNameCase.kt +++ b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/EnumEntryNameCase.kt @@ -15,4 +15,6 @@ class EnumEntryNameCase(config: Config) : FormattingRule(config) { override val wrapping = EnumEntryNameCaseRule() override val issue = issueFor("Reports enum entries with names that don't meet standard conventions.") + + override fun canBeCorrectedByKtLint(message: String): Boolean = false } diff --git a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/Filename.kt b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/Filename.kt index aa8dede5439..116ca427e2f 100644 --- a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/Filename.kt +++ b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/Filename.kt @@ -16,4 +16,6 @@ class Filename(config: Config) : FormattingRule(config) { override val wrapping = FilenameRule() override val issue = issueFor("Checks if top level class matches the filename") + + override fun canBeCorrectedByKtLint(message: String): Boolean = false } diff --git a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/ImportOrdering.kt b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/ImportOrdering.kt index a44fa4ddc86..5ad39af2f83 100644 --- a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/ImportOrdering.kt +++ b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/ImportOrdering.kt @@ -24,6 +24,8 @@ class ImportOrdering(config: Config) : FormattingRule(config) { @Configuration("the import ordering layout") private val layout: String by configWithAndroidVariants(IDEA_PATTERN, ASCII_PATTERN) + override fun canBeCorrectedByKtLint(message: String): Boolean = "no autocorrection" !in message + override fun overrideEditorConfigProperties(): Map, String> = mapOf(ImportOrderingRule.ideaImportsLayoutProperty to layout) diff --git a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/Indentation.kt b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/Indentation.kt index f943995d347..09271411230 100644 --- a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/Indentation.kt +++ b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/Indentation.kt @@ -30,6 +30,8 @@ class Indentation(config: Config) : FormattingRule(config) { @Suppress("UnusedPrivateMember") private val continuationIndentSize by config(4) + override fun canBeCorrectedByKtLint(message: String): Boolean = "not contain both tab(s) and space(s)" !in message + override fun overrideEditorConfigProperties(): Map, String> = mapOf( DefaultEditorConfigProperties.indentSizeProperty to indentSize.toString(), diff --git a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/MaximumLineLength.kt b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/MaximumLineLength.kt index e0c1d67772e..db7e3d8ecf9 100644 --- a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/MaximumLineLength.kt +++ b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/MaximumLineLength.kt @@ -32,6 +32,8 @@ class MaximumLineLength(config: Config) : FormattingRule(config) { @Configuration("ignore back ticked identifier") private val ignoreBackTickedIdentifier by config(false) + override fun canBeCorrectedByKtLint(message: String): Boolean = false + override fun overrideEditorConfigProperties(): Map, String> = mapOf( MaxLineLengthRule.ignoreBackTickedIdentifierProperty to ignoreBackTickedIdentifier.toString(), diff --git a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/NoWildcardImports.kt b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/NoWildcardImports.kt index 3dc3a50deef..4c4b08ac4aa 100644 --- a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/NoWildcardImports.kt +++ b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/NoWildcardImports.kt @@ -20,6 +20,8 @@ class NoWildcardImports(config: Config) : FormattingRule(config) { @Configuration("Defines allowed wildcard imports") private val packagesToUseImportOnDemandProperty by config(ALLOWED_WILDCARD_IMPORTS) + override fun canBeCorrectedByKtLint(message: String): Boolean = false + override fun overrideEditorConfigProperties(): Map, String> = mapOf( NoWildcardImportsRule.packagesToUseImportOnDemandProperty to packagesToUseImportOnDemandProperty diff --git a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/PackageName.kt b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/PackageName.kt index a15d6d59418..436e0c84b22 100644 --- a/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/PackageName.kt +++ b/detekt-formatting/src/main/kotlin/io/gitlab/arturbosch/detekt/formatting/wrappers/PackageName.kt @@ -16,4 +16,6 @@ class PackageName(config: Config) : FormattingRule(config) { override val wrapping = PackageNameRule() override val issue = issueFor("Checks package name is formatted correctly") + + override fun canBeCorrectedByKtLint(message: String): Boolean = false } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/RulesWhichCantBeCorrectedSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/RulesWhichCantBeCorrectedSpec.kt new file mode 100644 index 00000000000..8dfb465d473 --- /dev/null +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/RulesWhichCantBeCorrectedSpec.kt @@ -0,0 +1,85 @@ +package io.gitlab.arturbosch.detekt.formatting + +import io.gitlab.arturbosch.detekt.api.CodeSmell +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.formatting.wrappers.EnumEntryNameCase +import io.gitlab.arturbosch.detekt.formatting.wrappers.Filename +import io.gitlab.arturbosch.detekt.formatting.wrappers.ImportOrdering +import io.gitlab.arturbosch.detekt.formatting.wrappers.Indentation +import io.gitlab.arturbosch.detekt.formatting.wrappers.MaximumLineLength +import io.gitlab.arturbosch.detekt.formatting.wrappers.NoWildcardImports +import io.gitlab.arturbosch.detekt.formatting.wrappers.PackageName +import io.gitlab.arturbosch.detekt.test.assertThat +import org.junit.jupiter.api.Test + +class RulesWhichCantBeCorrectedSpec { + + @Test + fun `Filename findings can't be corrected`() { + assertThat(Filename(Config.empty).lint("class NotTheFilename")) + .isNotEmpty + .hasExactlyElementsOfTypes(CodeSmell::class.java) + } + + @Test + fun `PackageName findings can't be corrected`() { + assertThat(PackageName(Config.empty).lint("package under_score")) + .isNotEmpty + .hasExactlyElementsOfTypes(CodeSmell::class.java) + } + + @Test + fun `ImportOrdering has a case with comments which is not correctable`() { + assertThat( + ImportOrdering(Config.empty).lint( + """ + import xyz.wrong_order + /*comment in between*/ + import java.io.* + """.trimIndent() + ) + ).isNotEmpty + .hasExactlyElementsOfTypes(CodeSmell::class.java) + } + + @Test + fun `NoWildcardImports can't be corrected`() { + assertThat(NoWildcardImports(Config.empty).lint("import java.io.*")) + .isNotEmpty + .hasExactlyElementsOfTypes(CodeSmell::class.java) + } + + @Test + fun `MaximumLineLength can't be corrected`() { + assertThat( + MaximumLineLength(Config.empty).lint( + """ + class MaximumLeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeth + """.trimIndent() + ) + ).isNotEmpty + .hasExactlyElementsOfTypes(CodeSmell::class.java) + } + + @Test + fun `EnumEntryNameCase can't be corrected`() { + assertThat(EnumEntryNameCase(Config.empty).lint("enum class Enum { violation_triggering_name }")) + .isNotEmpty + .hasExactlyElementsOfTypes(CodeSmell::class.java) + } + + @Test + fun `Indentation finding inside string templates can't be corrected`() { + val multilineQuote = "${'"'}${'"'}${'"'}" + val code = """ + val foo = $multilineQuote + line1 + ${'\t'}line2 + $multilineQuote.trimIndent() + """.trimIndent() + + assertThat(Indentation(Config.empty).lint(code)) + .isNotEmpty + .hasExactlyElementsOfTypes(CodeSmell::class.java) + } +}