diff --git a/core/src/main/java/com/facebook/ktfmt/format/KotlinInputAstVisitor.kt b/core/src/main/java/com/facebook/ktfmt/format/KotlinInputAstVisitor.kt index 22fe7bcc..54622e7a 100644 --- a/core/src/main/java/com/facebook/ktfmt/format/KotlinInputAstVisitor.kt +++ b/core/src/main/java/com/facebook/ktfmt/format/KotlinInputAstVisitor.kt @@ -1207,20 +1207,31 @@ class KotlinInputAstVisitor( val leftMostExpression = parts.first() visit(leftMostExpression.left) for (leftExpression in parts) { - when (leftExpression.operationToken) { - KtTokens.RANGE -> {} - KtTokens.ELVIS -> builder.breakOp(Doc.FillMode.INDEPENDENT, " ", expressionBreakIndent) - else -> builder.space() - } - builder.token(leftExpression.operationReference.text) val isFirst = leftExpression === leftMostExpression - if (isFirst) { - builder.open(expressionBreakIndent) - } + when (leftExpression.operationToken) { - KtTokens.RANGE -> {} - KtTokens.ELVIS -> builder.space() - else -> builder.breakOp(Doc.FillMode.UNIFIED, " ", ZERO) + KtTokens.RANGE -> { + if (isFirst) { + builder.open(expressionBreakIndent) + } + builder.token(leftExpression.operationReference.text) + } + KtTokens.ELVIS -> { + if (isFirst) { + builder.open(expressionBreakIndent) + } + builder.breakOp(Doc.FillMode.UNIFIED, " ", ZERO) + builder.token(leftExpression.operationReference.text) + builder.space() + } + else -> { + builder.space() + if (isFirst) { + builder.open(expressionBreakIndent) + } + builder.token(leftExpression.operationReference.text) + builder.breakOp(Doc.FillMode.UNIFIED, " ", ZERO) + } } visit(leftExpression.right) } diff --git a/core/src/test/java/com/facebook/ktfmt/format/FormatterTest.kt b/core/src/test/java/com/facebook/ktfmt/format/FormatterTest.kt index 42acdf67..4358c34d 100644 --- a/core/src/test/java/com/facebook/ktfmt/format/FormatterTest.kt +++ b/core/src/test/java/com/facebook/ktfmt/format/FormatterTest.kt @@ -4379,6 +4379,52 @@ class FormatterTest { .trimMargin(), deduceMaxWidth = true) + @Test + fun `chain of Elvis operator`() = + assertFormatted( + """ + |--------------------------- + |fun f() { + | return option1() + | ?: option2() + | ?: option3() + | ?: option4() + | ?: option5() + |} + |""" + .trimMargin(), + deduceMaxWidth = true) + + @Test + fun `Elvis operator mixed with plus operator breaking on plus`() = + assertFormatted( + """ + |------------------------ + |fun f() { + | return option1() + | ?: option2() + + | option3() + | ?: option4() + + | option5() + |} + |""" + .trimMargin(), + deduceMaxWidth = true) + + @Test + fun `Elvis operator mixed with plus operator breaking on elvis`() = + assertFormatted( + """ + |--------------------------------- + |fun f() { + | return option1() + | ?: option2() + option3() + | ?: option4() + option5() + |} + |""" + .trimMargin(), + deduceMaxWidth = true) + @Test fun `handle comments in the middle of calling chain`() = assertFormatted(