From 443ba01abc87d2a82bb74931744e72d3de5ed442 Mon Sep 17 00:00:00 2001 From: JelloRanger Date: Thu, 25 Jan 2018 22:02:42 -0800 Subject: [PATCH 1/2] Add unit test to verify that custom componentN operator functions aren't marked as unused imports --- .../standard/NoUnusedImportsRuleTest.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRuleTest.kt index 2384ffa9f1..65d1b74467 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRuleTest.kt @@ -47,6 +47,35 @@ class NoUnusedImportsRuleTest { )).isEmpty() } + @Test + fun testDestructureOperatorLint() { + assertThat(NoUnusedImportsRule().lint( + """ + import p.component6 + + fun main() { + val (one, two, three, four, five, six) = someList + } + """.trimIndent() + )).isEmpty() + assertThat(NoUnusedImportsRule().lint( + """ + import p.component6 + import p.component2 + import p.component100 + import p.component + import p.component12woohoo + + fun main() { + val (one, two, three, four, five, six) = someList + } + """.trimIndent() + )).isEqualTo(listOf( + LintError(4, 1, "no-unused-imports", "Unused import"), + LintError(5, 1, "no-unused-imports", "Unused import") + )) + } + @Test fun testLintKDocLinkImport() { assertThat(NoUnusedImportsRule().lint( From 4d13e87749b91465f6f8e4ad4574cc63bc6d794b Mon Sep 17 00:00:00 2001 From: JelloRanger Date: Thu, 25 Jan 2018 22:23:49 -0800 Subject: [PATCH 2/2] Fix KtLint erroneously marking custom componentN operators as unused - Devs can write custom componentN operators in order to allow destructuring blocks of > 5 values, i.e. inline operator fun component6 = get(5) which allows the following (which is NOT possible without the above extension method): val (one, two, three, four, five, six) = someList ^--- component6() is imported to make this possible - In order to avoid marking these imports as unused we can ignore all imports that match componentX (where X is any number) --- .../shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt index f7e9ce7bd0..32255b48b4 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoUnusedImportsRule.kt @@ -12,6 +12,8 @@ import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes class NoUnusedImportsRule : Rule("no-unused-imports") { + private val destructureOperator = Regex("(?:component)[\\d]+\\b") + private val operatorSet = setOf( // unary "unaryPlus", "unaryMinus", "not", @@ -34,9 +36,7 @@ class NoUnusedImportsRule : Rule("no-unused-imports") { // iteration (https://github.com/shyiko/ktlint/issues/40) "iterator", // by (https://github.com/shyiko/ktlint/issues/54) - "getValue", "setValue", - // destructuring assignment - "component1", "component2", "component3", "component4", "component5" + "getValue", "setValue" ) private val ref = mutableSetOf() private var packageName = "" @@ -74,7 +74,7 @@ class NoUnusedImportsRule : Rule("no-unused-imports") { if (autoCorrect) { importDirective.delete() } - } else if (name != null && !ref.contains(name) && !operatorSet.contains(name)) { + } else if (name != null && !ref.contains(name) && !operatorSet.contains(name) && !destructureOperator.matches(name)) { emit(importDirective.startOffset, "Unused import", true) if (autoCorrect) { importDirective.delete()