Skip to content

Commit

Permalink
Add missing whitespace when else is on same line as true condition `m…
Browse files Browse the repository at this point in the history
…ultiline-if-else`

 Closes pinterest#1560
  • Loading branch information
paul-dingemans committed Aug 2, 2022
1 parent e0693a0 commit bed5f8f
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -126,6 +126,7 @@ The callback function provided as parameter to the format function is now called
* When a glob is specified then ensure that it matches files in the current directory and not only in subdirectories of the current directory ([#1533](https://github.com/pinterest/ktlint/issue/1533)).
* Execute `ktlint` cli on default kotlin extensions only when an (existing) path to a directory is given. ([#917](https://github.com/pinterest/ktlint/issue/917)).
* Invoke callback on `format` function for all errors including errors that are autocorrected ([#1491](https://github.com/pinterest/ktlint/issues/1491))
* Add missing whitespace when else is on same line as true condition `multiline-if-else` ([#1560](https://github.com/pinterest/ktlint/issues/1560))


### Changed
Expand Down
Expand Up @@ -3,13 +3,18 @@ package com.pinterest.ktlint.ruleset.standard
import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType.ELSE
import com.pinterest.ktlint.core.ast.ElementType.ELSE_KEYWORD
import com.pinterest.ktlint.core.ast.ElementType.IF
import com.pinterest.ktlint.core.ast.ElementType.LBRACE
import com.pinterest.ktlint.core.ast.ElementType.RBRACE
import com.pinterest.ktlint.core.ast.ElementType.RPAR
import com.pinterest.ktlint.core.ast.ElementType.THEN
import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE
import com.pinterest.ktlint.core.ast.isPartOf
import com.pinterest.ktlint.core.ast.isPartOfComment
import com.pinterest.ktlint.core.ast.isWhiteSpaceWithoutNewline
import com.pinterest.ktlint.core.ast.nextSibling
import com.pinterest.ktlint.core.ast.prevLeaf
import com.pinterest.ktlint.core.ast.upsertWhitespaceBeforeMe
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
Expand Down Expand Up @@ -42,9 +47,17 @@ class MultiLineIfElseRule : Rule("multiline-if-else") {

private fun autocorrect(node: ASTNode) {
val prevLeaves =
node.leaves(forward = false).takeWhile { it.elementType !in listOf(RPAR, ELSE_KEYWORD) }.toList().reversed()
node
.leaves(forward = false)
.takeWhile { it.elementType !in listOf(RPAR, ELSE_KEYWORD) }
.toList()
.reversed()
val nextLeaves =
node.leaves(forward = true).takeWhile { it.isWhiteSpaceWithoutNewline() || it.isPartOfComment() }.toList()
node
.leaves(forward = true)
.takeWhile { it.isWhiteSpaceWithoutNewline() || it.isPartOfComment() }
.toList()
.dropLastWhile { it.isWhiteSpaceWithoutNewline() }
val rightBraceIndent = node.treeParent
.prevLeaf { it is PsiWhiteSpace && it.textContains('\n') }?.text.orEmpty()
.let { "\n${it.substringAfterLast("\n")}" }
Expand All @@ -62,8 +75,17 @@ class MultiLineIfElseRule : Rule("multiline-if-else") {
}

// Make sure else starts on same line as newly inserted right brace
if (node.elementType == THEN && node.treeNext?.treeNext?.elementType == ELSE_KEYWORD) {
node.treeParent.replaceChild(node.treeNext, PsiWhiteSpaceImpl(" "))
if (node.elementType == THEN) {
node
.nextSibling { !it.isPartOfComment() }
?.let { nextSibling ->
if (nextSibling.elementType == ELSE_KEYWORD) {
(nextSibling as LeafPsiElement).upsertWhitespaceBeforeMe(" ")
}
if (nextSibling.elementType == WHITE_SPACE && nextSibling.text != " ") {
(nextSibling as LeafPsiElement).rawReplaceWithText(" ")
}
}
}
}
}
Expand Up @@ -492,4 +492,27 @@ class MultiLineIfElseRuleTest {
.hasLintViolation(6, 13, "Missing { ... }")
.isFormattedAs(formattedCode)
}

@Test
fun `Issue 1560 - Given an if statement with else keyword on same line as true branch`() {
val code =
"""
fun foo() = if (bar())
"a" else
"b"
""".trimIndent()
val formattedCode =
"""
fun foo() = if (bar()) {
"a"
} else {
"b"
}
""".trimIndent()
multiLineIfElseRuleAssertThat(code)
.hasLintViolations(
LintViolation(2, 5, "Missing { ... }"),
LintViolation(3, 5, "Missing { ... }")
).isFormattedAs(formattedCode)
}
}

0 comments on commit bed5f8f

Please sign in to comment.