Skip to content

Commit

Permalink
Fix wrapping of multiline postfix expression (#2184)
Browse files Browse the repository at this point in the history
* Fix wrapping of multiline postfix expression

Closes #2183
  • Loading branch information
paul-dingemans authored Aug 15, 2023
1 parent 26e2837 commit b14eaef
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
* Fix null pointer exception for if-else statement with empty THEN block `if-else-bracing` [#2135](https://github.com/pinterest/ktlint/issues/2135)
* Do not wrap a single line enum class `statement-wrapping` [#2177](https://github.com/pinterest/ktlint/issues/2177)
* Fix alignment of type constraints after `where` keyword in function signature `indent` [#2175](https://github.com/pinterest/ktlint/issues/2175)
* Fix wrapping of multiline postfix expression `multiline-expression-wrapping` [#2183](https://github.com/pinterest/ktlint/issues/2183)

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -581,10 +581,11 @@ public class IndentationRule :
node.prevSibling { it.isWhiteSpaceWithNewline() } == null &&
node == node.treeParent.findChildByType(VALUE_PARAMETER)
) {
nextToAstNode = startIndentContext(
fromAstNode = fromAstNode,
toAstNode = nextToAstNode,
).fromASTNode.prevLeaf { !it.isWhiteSpace() }!!
nextToAstNode =
startIndentContext(
fromAstNode = fromAstNode,
toAstNode = nextToAstNode,
).fromASTNode.prevLeaf { !it.isWhiteSpace() }!!
} else {
startIndentContext(
fromAstNode = node,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.pinterest.ktlint.rule.engine.core.api.ElementType.IF
import com.pinterest.ktlint.rule.engine.core.api.ElementType.IS_EXPRESSION
import com.pinterest.ktlint.rule.engine.core.api.ElementType.OBJECT_LITERAL
import com.pinterest.ktlint.rule.engine.core.api.ElementType.OPERATION_REFERENCE
import com.pinterest.ktlint.rule.engine.core.api.ElementType.POSTFIX_EXPRESSION
import com.pinterest.ktlint.rule.engine.core.api.ElementType.PREFIX_EXPRESSION
import com.pinterest.ktlint.rule.engine.core.api.ElementType.REFERENCE_EXPRESSION
import com.pinterest.ktlint.rule.engine.core.api.ElementType.RPAR
Expand Down Expand Up @@ -181,6 +182,7 @@ public class MultilineExpressionWrappingRule :
IS_EXPRESSION,
OBJECT_LITERAL,
PREFIX_EXPRESSION,
POSTFIX_EXPRESSION,
REFERENCE_EXPRESSION,
SAFE_ACCESS_EXPRESSION,
TRY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,23 +210,24 @@ public class WrappingRule :
autoCorrect: Boolean,
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit,
) {
val rElementType = MATCHING_RTOKEN_MAP[node.elementType]
val closingElementType = MATCHING_RTOKEN_MAP[node.elementType]
var newlineInBetween = false
var parameterListInBetween = false
var numberOfArgs = 0
var firstArg: ASTNode? = null
// matching ), ] or }
val r = node.nextSibling {
val isValueArgument = it.elementType == VALUE_ARGUMENT
val hasLineBreak = if (isValueArgument) it.hasLineBreak(LAMBDA_EXPRESSION, FUN) else it.hasLineBreak()
newlineInBetween = newlineInBetween || hasLineBreak
parameterListInBetween = parameterListInBetween || it.elementType == VALUE_PARAMETER_LIST
if (isValueArgument) {
numberOfArgs++
firstArg = it
}
it.elementType == rElementType
}!!
val closingElement =
node.nextSibling {
val isValueArgument = it.elementType == VALUE_ARGUMENT
val hasLineBreak = if (isValueArgument) it.hasLineBreak(LAMBDA_EXPRESSION, FUN) else it.hasLineBreak()
newlineInBetween = newlineInBetween || hasLineBreak
parameterListInBetween = parameterListInBetween || it.elementType == VALUE_PARAMETER_LIST
if (isValueArgument) {
numberOfArgs++
firstArg = it
}
it.elementType == closingElementType
}!!
if (
!newlineInBetween ||
// keep { p ->
Expand Down Expand Up @@ -283,8 +284,8 @@ public class WrappingRule :
) {
requireNewlineAfterLeaf(node, autoCorrect, emit)
}
if (!r.prevLeaf().isWhiteSpaceWithNewline()) {
requireNewlineBeforeLeaf(r, autoCorrect, emit, indentConfig.parentIndentOf(node))
if (!closingElement.prevLeaf().isWhiteSpaceWithNewline()) {
requireNewlineBeforeLeaf(closingElement, autoCorrect, emit, indentConfig.parentIndentOf(node))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -784,4 +784,23 @@ class MultilineExpressionWrappingRuleTest {
.addAdditionalRuleProvider { IndentationRule() }
.hasNoLintViolations()
}

@Test
fun `Issue 2183 - Given a multiline postfix expression then reformat`() {
val code =
"""
val foobar = foo!!
.bar()
""".trimIndent()
val formattedCode =
"""
val foobar =
foo!!
.bar()
""".trimIndent()
multilineExpressionWrappingRuleAssertThat(code)
.addAdditionalRuleProvider { IndentationRule() }
.hasLintViolation(1, 14, "A multiline expression should start on a new line")
.isFormattedAs(formattedCode)
}
}

0 comments on commit b14eaef

Please sign in to comment.