diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TypeParameterListSpacingRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TypeParameterListSpacingRule.kt index ece836f096..abad5abd0b 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TypeParameterListSpacingRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TypeParameterListSpacingRule.kt @@ -19,6 +19,7 @@ import com.pinterest.ktlint.rule.engine.core.api.SinceKtlint.Status.STABLE import com.pinterest.ktlint.rule.engine.core.api.editorconfig.EditorConfig import com.pinterest.ktlint.rule.engine.core.api.editorconfig.INDENT_SIZE_PROPERTY import com.pinterest.ktlint.rule.engine.core.api.editorconfig.INDENT_STYLE_PROPERTY +import com.pinterest.ktlint.rule.engine.core.api.isWhiteSpaceWithNewline import com.pinterest.ktlint.rule.engine.core.api.isWhiteSpaceWithoutNewline import com.pinterest.ktlint.rule.engine.core.api.nextCodeSibling import com.pinterest.ktlint.rule.engine.core.api.nextLeaf @@ -91,19 +92,34 @@ public class TypeParameterListSpacingRule : ?.takeIf { it.elementType == WHITE_SPACE && it.nextCodeSibling()?.elementType == PRIMARY_CONSTRUCTOR } ?.let { whiteSpace -> if (whiteSpace.nextCodeSibling()?.findChildByType(CONSTRUCTOR_KEYWORD) != null) { - // Single space or newline expected before (modifier list of) constructor - // class Bar constructor(...) - // class Bar actual constructor(...) - // class Bar @SomeAnnotation constructor(...) - if (whiteSpace.text != " " && whiteSpace.text != indentConfig.childIndentOf(node)) { - emit( - whiteSpace.startOffset, - "Expected a single space or newline (with indent)", - true, - ) - if (autoCorrect) { - // If line is to be wrapped this should have been done by other rules before running this rule - whiteSpace.upsertWhitespaceBeforeMe(" ") + if (whiteSpace.isWhiteSpaceWithNewline()) { + // Newline is acceptable before (modifier list of) constructor + // class Bar + // constructor(...) + // class Bar + // actual constructor(...) + // class Bar + // @SomeAnnotation constructor(...) + // class Bar + // @SomeAnnotation1 + // @SomeAnnotation2 + // constructor(...) + // class Bar + // /** + // * Some kdoc + // */ + // constructor(...) + } else { + // Single space before (modifier list of) constructor + // class Bar constructor(...) + // class Bar actual constructor(...) + // class Bar @SomeAnnotation constructor(...) + if (whiteSpace.text != " ") { + emit(whiteSpace.startOffset, "Expected a single space", true) + if (autoCorrect) { + // If line is to be wrapped this should have been done by other rules before running this rule + whiteSpace.upsertWhitespaceBeforeMe(" ") + } } } } else { diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TypeParameterListSpacingRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TypeParameterListSpacingRuleTest.kt index 425a20c603..32e2fa64ee 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TypeParameterListSpacingRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/TypeParameterListSpacingRuleTest.kt @@ -1,5 +1,7 @@ package com.pinterest.ktlint.ruleset.standard.rules +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.CODE_STYLE_PROPERTY +import com.pinterest.ktlint.rule.engine.core.api.editorconfig.CodeStyleValue.android_studio import com.pinterest.ktlint.test.KtLintAssertThat.Companion.assertThatRule import com.pinterest.ktlint.test.LintViolation import org.junit.jupiter.api.Test @@ -201,12 +203,12 @@ class TypeParameterListSpacingRuleTest { """.trimIndent() typeParameterListSpacingRuleAssertThat(code) .hasLintViolations( - LintViolation(1, 16, "Expected a single space or newline (with indent)"), - LintViolation(2, 16, "Expected a single space or newline (with indent)"), - LintViolation(3, 16, "Expected a single space or newline (with indent)"), - LintViolation(4, 16, "Expected a single space or newline (with indent)"), - LintViolation(5, 16, "Expected a single space or newline (with indent)"), - LintViolation(6, 16, "Expected a single space or newline (with indent)"), + LintViolation(1, 16, "Expected a single space"), + LintViolation(2, 16, "Expected a single space"), + LintViolation(3, 16, "Expected a single space"), + LintViolation(4, 16, "Expected a single space"), + LintViolation(5, 16, "Expected a single space"), + LintViolation(6, 16, "Expected a single space"), ).isFormattedAs(formattedCode) } @@ -318,6 +320,21 @@ class TypeParameterListSpacingRuleTest { .hasNoLintViolations() } + @Test + fun `Issue 2360 - Given a class with a KDoc on an explicit constructor starting on a separate line then do not report a violation`() { + val code = + """ + class Foo + /** + * some-comment + */ + constructor(param: T) + """.trimIndent() + typeParameterListSpacingRuleAssertThat(code) + .withEditorConfigOverride(CODE_STYLE_PROPERTY to android_studio) + .hasNoLintViolations() + } + @Test fun `Given a class with an annotated constructor on same line as parameter type list then do not report a violation`() { val code = @@ -327,4 +344,14 @@ class TypeParameterListSpacingRuleTest { typeParameterListSpacingRuleAssertThat(code) .hasNoLintViolations() } + + @Test + fun `Issue 2360`() { + val code = + """ + class Foo @Bar constructor(val value: T?) : FooBar() + """.trimIndent() + typeParameterListSpacingRuleAssertThat(code) + .hasNoLintViolations() + } }