forked from pinterest/ktlint
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new experimental rule to check consistent spacing around the retu…
…rn type of a function This rule is required for implementing pinterest#1341.
- Loading branch information
1 parent
5f02996
commit 640eee5
Showing
5 changed files
with
173 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
...rc/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionReturnTypeSpacingRule.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.pinterest.ktlint.ruleset.experimental | ||
|
||
import com.pinterest.ktlint.core.Rule | ||
import com.pinterest.ktlint.core.ast.ElementType.COLON | ||
import com.pinterest.ktlint.core.ast.ElementType.FUN | ||
import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE | ||
import com.pinterest.ktlint.core.ast.nextLeaf | ||
import com.pinterest.ktlint.core.ast.prevLeaf | ||
import com.pinterest.ktlint.core.ast.upsertWhitespaceAfterMe | ||
import org.jetbrains.kotlin.com.intellij.lang.ASTNode | ||
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafElement | ||
|
||
public class FunctionReturnTypeSpacingRule : Rule("function-return-type-spacing") { | ||
override fun visit( | ||
node: ASTNode, | ||
autoCorrect: Boolean, | ||
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit | ||
) { | ||
node | ||
.takeIf { node.elementType == FUN } | ||
?.let { node.findChildByType(COLON) } | ||
?.let { colonNode -> | ||
removeWhiteSpaceBetweenClosingParenthesisAndColon(colonNode, emit, autoCorrect) | ||
fixWhiteSpaceBetweenColonAndReturnType(colonNode, emit, autoCorrect) | ||
} | ||
} | ||
|
||
private fun removeWhiteSpaceBetweenClosingParenthesisAndColon( | ||
node: ASTNode, | ||
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit, | ||
autoCorrect: Boolean | ||
) { | ||
require(node.elementType == COLON) | ||
node | ||
.prevLeaf() | ||
?.takeIf { it.elementType == WHITE_SPACE } | ||
?.let { whitespaceBeforeColonNode -> | ||
emit(whitespaceBeforeColonNode.startOffset, "Unexpected whitespace", true) | ||
if (autoCorrect) { | ||
whitespaceBeforeColonNode.treeParent?.removeChild(whitespaceBeforeColonNode) | ||
} | ||
} | ||
} | ||
|
||
private fun fixWhiteSpaceBetweenColonAndReturnType( | ||
node: ASTNode, | ||
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit, | ||
autoCorrect: Boolean | ||
) { | ||
require(node.elementType == COLON) | ||
node | ||
.nextLeaf() | ||
?.takeIf { it.elementType == WHITE_SPACE } | ||
.let { whiteSpaceAfterColon -> | ||
if (whiteSpaceAfterColon == null) { | ||
emit(node.startOffset, "Single space expected between colon and return type", true) | ||
if (autoCorrect) { | ||
(node as LeafElement).upsertWhitespaceAfterMe(" ") | ||
} | ||
} else if (whiteSpaceAfterColon.text != " ") { | ||
emit(node.startOffset, "Unexpected whitespace", true) | ||
if (autoCorrect) { | ||
(whiteSpaceAfterColon as LeafElement).rawReplaceWithText(" ") | ||
} | ||
} | ||
} | ||
} | ||
} |
101 changes: 101 additions & 0 deletions
101
...est/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionReturnTypeSpacingRuleTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package com.pinterest.ktlint.ruleset.experimental | ||
|
||
import com.pinterest.ktlint.core.LintError | ||
import com.pinterest.ktlint.test.format | ||
import com.pinterest.ktlint.test.lint | ||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.jupiter.api.Test | ||
|
||
class FunctionReturnTypeSpacingRuleTest { | ||
@Test | ||
fun `Given a function signature without whitespace between the closing parenthesis and the colon of the return type then do not reformat`() { | ||
val code = | ||
""" | ||
fun foo(): String = "some-result" | ||
""".trimIndent() | ||
assertThat(FunctionReturnTypeSpacingRule().lint(code)).isEmpty() | ||
assertThat(FunctionReturnTypeSpacingRule().format(code)).isEqualTo(code) | ||
} | ||
|
||
@Test | ||
fun `Given a function signature with at least one space between the closing parenthesis and the colon of the return type then reformat`() { | ||
val code = | ||
""" | ||
fun foo() : String = "some-result" | ||
""".trimIndent() | ||
val formattedCode = | ||
""" | ||
fun foo(): String = "some-result" | ||
""".trimIndent() | ||
assertThat(FunctionReturnTypeSpacingRule().lint(code)).containsExactly( | ||
LintError(1, 10, "function-return-type-spacing", "Unexpected whitespace") | ||
) | ||
assertThat(FunctionReturnTypeSpacingRule().format(code)).isEqualTo(formattedCode) | ||
} | ||
|
||
@Test | ||
fun `Given a function signature with a newline between the closing parenthesis and the colon of the return type then reformat`() { | ||
val code = | ||
""" | ||
fun foo() | ||
: String = "some-result" | ||
""".trimIndent() | ||
val formattedCode = | ||
""" | ||
fun foo(): String = "some-result" | ||
""".trimIndent() | ||
assertThat(FunctionReturnTypeSpacingRule().lint(code)).containsExactly( | ||
LintError(1, 10, "function-return-type-spacing", "Unexpected whitespace") | ||
) | ||
assertThat(FunctionReturnTypeSpacingRule().format(code)).isEqualTo(formattedCode) | ||
} | ||
|
||
@Test | ||
fun `Given a function signature without space between the colon and the return type then reformat`() { | ||
val code = | ||
""" | ||
fun foo():String = "some-result" | ||
""".trimIndent() | ||
val formattedCode = | ||
""" | ||
fun foo(): String = "some-result" | ||
""".trimIndent() | ||
assertThat(FunctionReturnTypeSpacingRule().lint(code)).containsExactly( | ||
LintError(1, 10, "function-return-type-spacing", "Single space expected between colon and return type") | ||
) | ||
assertThat(FunctionReturnTypeSpacingRule().format(code)).isEqualTo(formattedCode) | ||
} | ||
|
||
@Test | ||
fun `Given a function signature with multiple spaces between the colon and the return type then reformat`() { | ||
val code = | ||
""" | ||
fun foo(): String = "some-result" | ||
""".trimIndent() | ||
val formattedCode = | ||
""" | ||
fun foo(): String = "some-result" | ||
""".trimIndent() | ||
assertThat(FunctionReturnTypeSpacingRule().lint(code)).containsExactly( | ||
LintError(1, 10, "function-return-type-spacing", "Unexpected whitespace") | ||
) | ||
assertThat(FunctionReturnTypeSpacingRule().format(code)).isEqualTo(formattedCode) | ||
} | ||
|
||
@Test | ||
fun `Given a function signature with a new line between the colon and the return type then reformat`() { | ||
val code = | ||
""" | ||
fun foo(): | ||
String = "some-result" | ||
""".trimIndent() | ||
val formattedCode = | ||
""" | ||
fun foo(): String = "some-result" | ||
""".trimIndent() | ||
assertThat(FunctionReturnTypeSpacingRule().lint(code)).containsExactly( | ||
LintError(1, 10, "function-return-type-spacing", "Unexpected whitespace") | ||
) | ||
assertThat(FunctionReturnTypeSpacingRule().format(code)).isEqualTo(formattedCode) | ||
} | ||
} |