From 8e708197b8164d2b6657c3b0bbcc645e5d990c49 Mon Sep 17 00:00:00 2001 From: Svyatoslav Chatchenko Date: Wed, 22 Nov 2017 11:42:33 +0100 Subject: [PATCH] new Rule: No line break before assignment Line break is allowed only after assignment (eg. equals sign) Auto formatting is supported via simplistic approach by putting same line break with same indent from left side to right side of assignment Closes shyiko/ktlint#105 --- .../NoLineBreakBeforeAssignmentRule.kt | 23 +++++++ .../NoLineBreakBeforeAssignmentRuleTest.kt | 69 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRule.kt create mode 100644 ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRuleTest.kt diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRule.kt new file mode 100644 index 0000000000..e82f4df45f --- /dev/null +++ b/ktlint-ruleset-standard/src/main/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRule.kt @@ -0,0 +1,23 @@ +package com.github.shyiko.ktlint.ruleset.standard + +import com.github.shyiko.ktlint.core.Rule +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.lexer.KtTokens + +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 == KtTokens.EQ) { + val prevElement = node.treePrev?.psi + if (prevElement is PsiWhiteSpace && prevElement.text.contains("\n")) { + emit(node.startOffset, "Line break before assignment is not allowed", true) + if (autoCorrect) { + (node.treeNext?.psi as LeafPsiElement).replaceWithText(prevElement.text) + (prevElement as LeafPsiElement).replaceWithText(" ") + } + } + } + } +} diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRuleTest.kt new file mode 100644 index 0000000000..55ac3e3990 --- /dev/null +++ b/ktlint-ruleset-standard/src/test/kotlin/com/github/shyiko/ktlint/ruleset/standard/NoLineBreakBeforeAssignmentRuleTest.kt @@ -0,0 +1,69 @@ +package com.github.shyiko.ktlint.ruleset.standard + +import com.github.shyiko.ktlint.core.LintError +import com.github.shyiko.ktlint.test.format +import com.github.shyiko.ktlint.test.lint +import org.assertj.core.api.Assertions.assertThat +import org.testng.annotations.Test + +const val ruleId = "no-line-break-before-assignment" + +class NoLineBreakBeforeAssignmentRuleTest { + @Test + fun testAllPartsOnSameLineIsValid() { + assertThat(NoLineBreakBeforeAssignmentRule().lint( + """ + val valA = "" + """.trimIndent() + )).isEmpty() + } + + @Test + fun testLineBreakAfterAssignmentIsValid() { + assertThat(NoLineBreakBeforeAssignmentRule().lint( + """ + val valA = + "" + """.trimIndent() + )).isEmpty() + } + + @Test + fun testLineBreakBeforeAssignmentIsViolation() { + assertThat(NoLineBreakBeforeAssignmentRule().lint( + """ + val valA + = "" + """.trimIndent() + )).isEqualTo(listOf( + LintError(2, 7, ruleId, "Line break before assignment is not allowed") + )) + } + + @Test + fun testViolationInFunction() { + assertThat(NoLineBreakBeforeAssignmentRule().lint( + """ + fun funA() + = "" + """.trimIndent() + )).isEqualTo(listOf( + LintError(2, 7, ruleId, "Line break before assignment is not allowed") + )) + } + + @Test + fun testFixViolationByRemovingLineBreakFromLeftAndPutItOnRightSide() { + assertThat(NoLineBreakBeforeAssignmentRule().format( + """ + fun funA() + = "" + """.trimIndent() + )).isEqualTo( + """ + fun funA() = + "" + """.trimIndent() + ) + } +}