Skip to content

Commit

Permalink
An if-else followed by an elvis operator should not be wrapped in an …
Browse files Browse the repository at this point in the history
…else-block (#1923)

* An if-else followed by an elvis operator should not be wrapped in an else-block

Closes #1904
  • Loading branch information
paul-dingemans authored Apr 7, 2023
1 parent c9a3d2a commit 5e46778
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ if (node.isRoot()) {
* Add newline after adding trailing comma in parameter list of a function literal `trailing-comma-on-declaration-site` ([#1911](https://github.com/pinterest/ktlint/issues/1911))
* Wrap annotations before class constructor in code style `ktlint_official`. `annotation` ([#1916](https://github.com/pinterest/ktlint/issues/1916))
* Annotations on type projections should be wrapped in same way as other annotations `annotation` ([#1917](https://github.com/pinterest/ktlint/issues/1917))
* An if-else followed by an elvis operator should not be wrapped in an else-block `multiline-if-else` ([#1904](https://github.com/pinterest/ktlint/issues/1904))

### Changed
* Wrap the parameters of a function literal containing a multiline parameter list (only in `ktlint_official` code style) `parameter-list-wrapping` ([#1681](https://github.com/pinterest/ktlint/issues/1681)).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.pinterest.ktlint.ruleset.standard.rules

import com.pinterest.ktlint.rule.engine.core.api.ElementType.BINARY_EXPRESSION
import com.pinterest.ktlint.rule.engine.core.api.ElementType.BLOCK
import com.pinterest.ktlint.rule.engine.core.api.ElementType.DOT_QUALIFIED_EXPRESSION
import com.pinterest.ktlint.rule.engine.core.api.ElementType.ELSE
import com.pinterest.ktlint.rule.engine.core.api.ElementType.ELSE_KEYWORD
import com.pinterest.ktlint.rule.engine.core.api.ElementType.IF
Expand Down Expand Up @@ -52,29 +54,54 @@ public class MultiLineIfElseRule :
autoCorrect: Boolean,
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit,
) {
if (node.elementType == THEN || node.elementType == ELSE) {
if (node.firstChildNode?.elementType == BLOCK) {
if (node.elementType != THEN && node.elementType != ELSE) {
return
}

// Ignore when already wrapped in a block
if (node.firstChildNode?.elementType == BLOCK) {
return
}

if (node.elementType == ELSE && node.firstChildNode?.elementType == BINARY_EXPRESSION) {
// Allow
// val foo = if (bar1) {
// "bar1"
// } else {
// null
// } ?: "something-else"
return
}

if (node.elementType == ELSE && node.firstChildNode?.elementType == DOT_QUALIFIED_EXPRESSION) {
// Allow
// val foo = if (bar1) {
// "bar1"
// } else {
// "bar2"
// }.plus("foo")
return
}

if (!node.treePrev.textContains('\n')) {
if (node.firstChildNode.elementType == IF) {
// Allow single line for:
// else if (...)
return
}

if (!node.treePrev.textContains('\n')) {
if (node.firstChildNode.elementType == IF) {
// Allow single line for:
// else if (...)
return
}
if (!node.treeParent.textContains('\n')) {
// Allow single line if statements as long as they are really simple (e.g. do not contain newlines)
// if (...) <statement> // no else statement
// if (...) <statement> else <statement>
return
}
if (!node.treeParent.textContains('\n')) {
// Allow single line if statements as long as they are really simple (e.g. do not contain newlines)
// if (...) <statement> // no else statement
// if (...) <statement> else <statement>
return
}

emit(node.firstChildNode.startOffset, "Missing { ... }", true)
if (autoCorrect) {
autocorrect(node)
}
Unit
}

emit(node.firstChildNode.startOffset, "Missing { ... }", true)
if (autoCorrect) {
autocorrect(node)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,4 +569,32 @@ class MultiLineIfElseRuleTest {
LintViolation(3, 10, "Missing { ... }"),
).isFormattedAs(formattedCode)
}

@Test
fun `Issue 1904 - Given an nested if else statement followed by an elvis operator`() {
val code =
"""
val foo = if (bar1) {
"bar1"
} else {
null
} ?: "something-else"
""".trimIndent()
multiLineIfElseRuleAssertThat(code).hasNoLintViolations()
}

@Test
fun `Issue 1904 - Given an nested if else statement and else which is part of a dot qualified expression`() {
val code =
"""
val foo = if (bar1) {
"bar1"
} else if (bar2) {
"bar2"
} else {
"bar3"
}.plus("foo")
""".trimIndent()
multiLineIfElseRuleAssertThat(code).hasNoLintViolations()
}
}

0 comments on commit 5e46778

Please sign in to comment.