From 98f9fd55ef557d4e7d6ea1a47ed40854e84574e5 Mon Sep 17 00:00:00 2001 From: Paul Dingemans Date: Sun, 20 Dec 2020 15:33:20 +0100 Subject: [PATCH 1/3] Fix string-template for dot-expression of which the redundant toString is removed (#996) The no-unused-imports rule fails on the existence of the dot-expression node but for which the actual call to the toString method was removed. --- .../ruleset/standard/StringTemplateRule.kt | 20 ++++++++++++++++--- .../standard/StringTemplateRuleTest.kt | 20 +++++++++++++++++++ .../string-template/format-expected.kt.spec | 1 + .../spec/string-template/format.kt.spec | 1 + .../spec/string-template/lint.kt.spec | 12 ++++++----- 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt index 27b779f99a..06ad017816 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt @@ -6,7 +6,11 @@ import com.pinterest.ktlint.core.ast.ElementType.DOT import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.LITERAL_STRING_TEMPLATE_ENTRY import com.pinterest.ktlint.core.ast.ElementType.LONG_STRING_TEMPLATE_ENTRY +import com.pinterest.ktlint.core.ast.ElementType.LONG_TEMPLATE_ENTRY_END +import com.pinterest.ktlint.core.ast.ElementType.LONG_TEMPLATE_ENTRY_START +import com.pinterest.ktlint.core.ast.ElementType.REGULAR_STRING_PART import com.pinterest.ktlint.core.ast.ElementType.SUPER_EXPRESSION +import com.pinterest.ktlint.core.ast.children import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.psi.KtBlockStringTemplateEntry @@ -65,9 +69,19 @@ class StringTemplateRule : Rule("string-template") { ) { emit(node.treePrev.startOffset + 2, "Redundant curly braces", true) if (autoCorrect) { - // fixme: a proper way would be to downcast to SHORT_STRING_TEMPLATE_ENTRY - (node.firstChildNode as LeafPsiElement).rawReplaceWithText("$") // entry start - (node.lastChildNode as LeafPsiElement).rawReplaceWithText("") // entry end + val leftCurlyBraceNode = node.findChildByType(LONG_TEMPLATE_ENTRY_START) + val rightCurlyBraceNode = node.findChildByType(LONG_TEMPLATE_ENTRY_END) + if (node.children().count() == 3 && leftCurlyBraceNode != null && rightCurlyBraceNode != null) { + node.removeChild(leftCurlyBraceNode) + node.removeChild(rightCurlyBraceNode) + val remainingNode = node.firstChildNode + val newNode = if (remainingNode.elementType == DOT_QUALIFIED_EXPRESSION) { + LeafPsiElement(REGULAR_STRING_PART, "\$${remainingNode.text}") + } else { + LeafPsiElement(remainingNode.elementType, "\$${remainingNode.text}") + } + node.replaceChild(node.firstChildNode, newNode) + } } } } diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRuleTest.kt index dee53082c8..2849be6a9c 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRuleTest.kt @@ -2,6 +2,7 @@ package com.pinterest.ktlint.ruleset.standard import com.pinterest.ktlint.test.diffFileFormat import com.pinterest.ktlint.test.diffFileLint +import com.pinterest.ktlint.test.format import org.assertj.core.api.Assertions.assertThat import org.junit.Test @@ -21,4 +22,23 @@ class StringTemplateRuleTest { ) ).isEmpty() } + + @Test + fun testFormatIssue996() { + assertThat( + StringTemplateRule().format( + """ + fun getDrafts(val draftsIds: List) { + println("draftIds=[${'$'}{draftsIds.toString()}]") + } + """.trimIndent() + ) + ).isEqualTo( + """ + fun getDrafts(val draftsIds: List) { + println("draftIds=[${'$'}draftsIds]") + } + """.trimIndent() + ) + } } diff --git a/ktlint-ruleset-standard/src/test/resources/spec/string-template/format-expected.kt.spec b/ktlint-ruleset-standard/src/test/resources/spec/string-template/format-expected.kt.spec index 9a706d1b8f..bb9884d30d 100644 --- a/ktlint-ruleset-standard/src/test/resources/spec/string-template/format-expected.kt.spec +++ b/ktlint-ruleset-standard/src/test/resources/spec/string-template/format-expected.kt.spec @@ -2,6 +2,7 @@ fun main() { val x = "${String::class}" println("$x.hello") println("$x.hello") + println("$x") println("${x}hello") println("${x.length}.hello") println("$x.hello") diff --git a/ktlint-ruleset-standard/src/test/resources/spec/string-template/format.kt.spec b/ktlint-ruleset-standard/src/test/resources/spec/string-template/format.kt.spec index 867175c316..02f75d55a7 100644 --- a/ktlint-ruleset-standard/src/test/resources/spec/string-template/format.kt.spec +++ b/ktlint-ruleset-standard/src/test/resources/spec/string-template/format.kt.spec @@ -2,6 +2,7 @@ fun main() { val x = "${String::class.toString()}" println("${x}.hello") println("${x.toString()}.hello") + println("${x.toString()}") println("${x}hello") println("${x.length}.hello") println("$x.hello") diff --git a/ktlint-ruleset-standard/src/test/resources/spec/string-template/lint.kt.spec b/ktlint-ruleset-standard/src/test/resources/spec/string-template/lint.kt.spec index 7e6cb5e352..a38f9780af 100644 --- a/ktlint-ruleset-standard/src/test/resources/spec/string-template/lint.kt.spec +++ b/ktlint-ruleset-standard/src/test/resources/spec/string-template/lint.kt.spec @@ -1,5 +1,6 @@ fun main() { println("${String::class.toString()}") + println("${hello.toString()}") println("""${Int::class.toString()}""") println("$s0") println("""$s1""") @@ -62,9 +63,10 @@ class F { // expect // 2:29:Redundant "toString()" call in string template -// 3:28:Redundant "toString()" call in string template -// 6:15:Redundant curly braces +// 3:21:Redundant "toString()" call in string template +// 4:28:Redundant "toString()" call in string template // 7:15:Redundant curly braces -// 28:79:Redundant "toString()" call in string template -// 45:20:Redundant curly braces -// 55:19:Redundant curly braces +// 8:15:Redundant curly braces +// 29:79:Redundant "toString()" call in string template +// 46:20:Redundant curly braces +// 56:19:Redundant curly braces From 3234eaeeb83a0a144c51502ce75484ec2f2914dc Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Mon, 21 Dec 2020 22:45:02 +0100 Subject: [PATCH 2/3] Update changelog --- CHANGELOG.md | 1 + .../com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7338cd0117..86173c6c50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Fix '.editorconfig' generation for "import-ordering" rule ([#1011](https://github.com/pinterest/ktlint/issues/1004)) - Fix "filename" rule will not work when '.editorconfig' file is not found ([#997](https://github.com/pinterest/ktlint/issues/1004)) - EditorConfig generation for `import-ordering` ([#1011](https://github.com/pinterest/ktlint/pull/1011)) +- Internal error (`no-unused-imports`) ([#996](https://github.com/pinterest/ktlint/issues/996)) ### Changed - Update Gradle shadow plugin to `6.1.0` version diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt index 06ad017816..e3fb200ef7 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt @@ -71,7 +71,7 @@ class StringTemplateRule : Rule("string-template") { if (autoCorrect) { val leftCurlyBraceNode = node.findChildByType(LONG_TEMPLATE_ENTRY_START) val rightCurlyBraceNode = node.findChildByType(LONG_TEMPLATE_ENTRY_END) - if (node.children().count() == 3 && leftCurlyBraceNode != null && rightCurlyBraceNode != null) { + if (leftCurlyBraceNode != null && rightCurlyBraceNode != null) { node.removeChild(leftCurlyBraceNode) node.removeChild(rightCurlyBraceNode) val remainingNode = node.firstChildNode From ed8d878c23f3191729ee15a29e9c91f401ca2f1c Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Mon, 21 Dec 2020 22:56:18 +0100 Subject: [PATCH 3/3] Fix code style violation --- .../com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt index e3fb200ef7..7577763f74 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRule.kt @@ -10,7 +10,6 @@ import com.pinterest.ktlint.core.ast.ElementType.LONG_TEMPLATE_ENTRY_END import com.pinterest.ktlint.core.ast.ElementType.LONG_TEMPLATE_ENTRY_START import com.pinterest.ktlint.core.ast.ElementType.REGULAR_STRING_PART import com.pinterest.ktlint.core.ast.ElementType.SUPER_EXPRESSION -import com.pinterest.ktlint.core.ast.children import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.psi.KtBlockStringTemplateEntry