diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRule.kt index 9ef7ba0b7f..fa00dc4ef1 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRule.kt @@ -2,28 +2,35 @@ package com.pinterest.ktlint.ruleset.standard import com.pinterest.ktlint.core.Rule import com.pinterest.ktlint.core.ast.ElementType.EQ -import com.pinterest.ktlint.core.ast.ElementType.REGULAR_STRING_PART +import com.pinterest.ktlint.core.ast.isPartOfComment +import com.pinterest.ktlint.core.ast.isWhiteSpace +import com.pinterest.ktlint.core.ast.isWhiteSpaceWithNewline +import com.pinterest.ktlint.core.ast.prevCodeSibling import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement +import org.jetbrains.kotlin.psi.psiUtil.siblings class NoLineBreakBeforeAssignmentRule : Rule("no-line-break-before-assignment") { override fun visit(node: ASTNode, autoCorrect: Boolean, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) { if (node.elementType == EQ) { - val prevElement = node.treePrev?.psi - if (prevElement is PsiWhiteSpace && prevElement.text.contains("\n")) { + val prevCodeSibling = node.prevCodeSibling() + val hasLineBreakBeforeAssignment = prevCodeSibling + ?.siblings() + ?.takeWhile { it.isWhiteSpace() || it.isPartOfComment() } + ?.any { it.isWhiteSpaceWithNewline() } + if (hasLineBreakBeforeAssignment == true) { emit(node.startOffset, "Line break before assignment is not allowed", true) if (autoCorrect) { - val leaf = node.treeNext?.psi as? LeafPsiElement - if (leaf != null) { - leaf.rawReplaceWithText(prevElement.text) - } else { - (node.psi as LeafPsiElement).rawInsertAfterMe( - LeafPsiElement(REGULAR_STRING_PART, prevElement.text) - ) + val next = prevCodeSibling.treeNext + val newText = buildString { + append(" =") + if (next !is PsiWhiteSpace) append(" ") + append(next.text) } - (prevElement as LeafPsiElement).rawReplaceWithText(" ") + (next as? LeafPsiElement)?.rawReplaceWithText(newText) + (node as? LeafPsiElement)?.delete() } } } diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRuleTest.kt index c95fad1ac0..b54a71945f 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRuleTest.kt @@ -97,4 +97,76 @@ class NoLineBreakBeforeAssignmentRuleTest { """.trimIndent() ) } + + @Test + fun `test assignment with comment 1`() { + assertThat( + NoLineBreakBeforeAssignmentRule().format( + """ + fun sum(a: Int, b: Int): Int + // comment + = a + b + """.trimIndent() + ) + ).isEqualTo( + """ + fun sum(a: Int, b: Int): Int = + // comment + a + b + """.trimIndent() + ) + } + + @Test + fun `test assignment with comment 2`() { + assertThat( + NoLineBreakBeforeAssignmentRule().format( + """ + fun sum(a: Int, b: Int): Int + // comment + =a + b + """.trimIndent() + ) + ).isEqualTo( + """ + fun sum(a: Int, b: Int): Int = + // comment + a + b + """.trimIndent() + ) + } + + @Test + fun `test assignment with comment 3`() { + assertThat( + NoLineBreakBeforeAssignmentRule().format( + """ + fun sum(a: Int, b: Int): Int // comment + = a + b + """.trimIndent() + ) + ).isEqualTo( + """ + fun sum(a: Int, b: Int): Int = // comment + a + b + """.trimIndent() + ) + } + + @Test + fun `test assignment with comment 4`() { + assertThat( + NoLineBreakBeforeAssignmentRule().format( + """ + fun sum(a: Int, b: Int): Int// comment + = a + b + """.trimIndent() + ) + ).isEqualTo( + """ + fun sum(a: Int, b: Int): Int = // comment + a + b + """.trimIndent() + ) + } }