From 0502a2bcabb78d9bbba6b9f73e9d41678e8eccf2 Mon Sep 17 00:00:00 2001 From: Phil Davies Date: Tue, 16 Apr 2024 10:55:07 +0100 Subject: [PATCH] Fix unwanted whitespace between super class constructor and its argument list (#2630) Co-authored-by: Paul Dingemans --- .../standard/rules/ClassSignatureRule.kt | 15 ++++++ .../standard/rules/SpacingAroundParensRule.kt | 4 +- .../standard/rules/ClassSignatureRuleTest.kt | 49 +++++++++++++++++++ .../rules/SpacingAroundParensRuleTest.kt | 34 +++++++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ClassSignatureRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ClassSignatureRule.kt index 30f06b9de0..9dc041f4b8 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ClassSignatureRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ClassSignatureRule.kt @@ -584,6 +584,21 @@ public class ClassSignatureRule : } } + // Disallow: + // class Foo : Bar ("foobar") + superTypes + .filter { it.elementType == SUPER_TYPE_CALL_ENTRY } + .forEach { superTypeCallEntry -> + superTypeCallEntry + .findChildByType(WHITE_SPACE) + ?.let { whitespace -> + emit(whitespace.startOffset, "No whitespace expected", true) + if (autoCorrect) { + whitespace.treeParent.removeChild(whitespace) + } + } + } + return whiteSpaceCorrection } diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundParensRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundParensRule.kt index 33cf472e18..b86eac62c9 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundParensRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundParensRule.kt @@ -9,6 +9,7 @@ import com.pinterest.ktlint.rule.engine.core.api.ElementType.LPAR import com.pinterest.ktlint.rule.engine.core.api.ElementType.PRIMARY_CONSTRUCTOR import com.pinterest.ktlint.rule.engine.core.api.ElementType.RPAR import com.pinterest.ktlint.rule.engine.core.api.ElementType.SUPER_KEYWORD +import com.pinterest.ktlint.rule.engine.core.api.ElementType.TYPE_ARGUMENT_LIST import com.pinterest.ktlint.rule.engine.core.api.ElementType.VALUE_ARGUMENT_LIST import com.pinterest.ktlint.rule.engine.core.api.ElementType.VALUE_PARAMETER_LIST import com.pinterest.ktlint.rule.engine.core.api.RuleId @@ -46,7 +47,8 @@ public class SpacingAroundParensRule : StandardRule("paren-spacing") { node.treeParent?.treeParent?.elementType != FUNCTION_TYPE || // Super keyword needs special-casing prevLeaf.prevLeaf()?.elementType == SUPER_KEYWORD || - prevLeaf.prevLeaf()?.treeParent?.elementType == PRIMARY_CONSTRUCTOR + prevLeaf.prevLeaf()?.treeParent?.elementType == PRIMARY_CONSTRUCTOR || + prevLeaf.prevLeaf()?.treeParent?.elementType == TYPE_ARGUMENT_LIST ) && ( node.treeParent?.elementType == VALUE_PARAMETER_LIST || diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ClassSignatureRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ClassSignatureRuleTest.kt index 06b02bff53..a7338e7e8b 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ClassSignatureRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/ClassSignatureRuleTest.kt @@ -1734,6 +1734,55 @@ class ClassSignatureRuleTest { .hasNoLintViolations() } + @Nested + inner class `Issue 2630 - White space in super type call entry` { + @Test + fun `Issue 2630 - Given a super type call entry without type argument list`() { + val code = + """ + class Foo1 : Bar("foobar") + class Foo2 : Bar ("foobar") + class Foo3 : Bar + ("foobar") + """.trimIndent() + val formattedCode = + """ + class Foo1 : Bar("foobar") + class Foo2 : Bar("foobar") + class Foo3 : Bar("foobar") + """.trimIndent() + classSignatureWrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 17, "No whitespace expected"), + LintViolation(3, 14, "Super type should start on a newline"), + LintViolation(3, 17, "No whitespace expected"), + ).isFormattedAs(formattedCode) + } + + @Test + fun `Issue 2630 - Given a super type call entry with type argument list`() { + val code = + """ + class Foo1 : Bar("foobar") + class Foo2 : Bar ("foobar") + class Foo3 : Bar + ("foobar") + """.trimIndent() + val formattedCode = + """ + class Foo1 : Bar("foobar") + class Foo2 : Bar("foobar") + class Foo3 : Bar("foobar") + """.trimIndent() + classSignatureWrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 25, "No whitespace expected"), + LintViolation(3, 14, "Super type should start on a newline"), + LintViolation(3, 25, "No whitespace expected"), + ).isFormattedAs(formattedCode) + } + } + private companion object { const val UNEXPECTED_SPACES = " " const val NO_SPACE = "" diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundParensRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundParensRuleTest.kt index ee1bc869a7..1812e0e506 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundParensRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/SpacingAroundParensRuleTest.kt @@ -28,6 +28,40 @@ class SpacingAroundParensRuleTest { .isFormattedAs(formattedCode) } + @Test + fun `Given class with superclass constructor call`() { + val code = + """ + open class Bar(param: String) + class Foo : Bar ("test") + """.trimIndent() + val formattedCode = + """ + open class Bar(param: String) + class Foo : Bar("test") + """.trimIndent() + spacingAroundParensRuleAssertThat(code) + .hasLintViolation(2, 16, "Unexpected spacing before \"(\"") + .isFormattedAs(formattedCode) + } + + @Test + fun `Given class with superclass constructor call with type parameter`() { + val code = + """ + open class Bar(param: T) + class Foo : Bar ("test") + """.trimIndent() + val formattedCode = + """ + open class Bar(param: T) + class Foo : Bar("test") + """.trimIndent() + spacingAroundParensRuleAssertThat(code) + .hasLintViolation(2, 24, "Unexpected spacing before \"(\"") + .isFormattedAs(formattedCode) + } + @Test fun `Given a variable declaration with unexpected spacing around the opening parenthesis of the expression`() { val code =