Skip to content

Commit

Permalink
Prevent conflict between multiline-expression-wrapping and `functio…
Browse files Browse the repository at this point in the history
…n-signature`

When `function-signature` rule is configured with `ktlint_function_signature_body_expression_wrapping` set to `default` then the first line of a multiline expression body should be kept on the same line as the end of function signature, as long as max line length is not exceeded. In this case the `multiline-expression-wrapping` rule has to ignore the multiline function expression body.

Closes #2650
  • Loading branch information
paul-dingemans committed Aug 20, 2024
1 parent 34556a6 commit 9fbcd2e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import com.pinterest.ktlint.rule.engine.core.api.prevCodeSibling
import com.pinterest.ktlint.rule.engine.core.api.prevLeaf
import com.pinterest.ktlint.rule.engine.core.api.upsertWhitespaceBeforeMe
import com.pinterest.ktlint.ruleset.standard.StandardRule
import com.pinterest.ktlint.ruleset.standard.rules.FunctionSignatureRule.Companion.FUNCTION_BODY_EXPRESSION_WRAPPING_PROPERTY
import com.pinterest.ktlint.ruleset.standard.rules.FunctionSignatureRule.FunctionBodyExpressionWrapping.default
import org.jetbrains.kotlin.com.intellij.lang.ASTNode

/**
Expand All @@ -64,17 +66,20 @@ public class MultilineExpressionWrappingRule :
setOf(
INDENT_SIZE_PROPERTY,
INDENT_STYLE_PROPERTY,
FUNCTION_BODY_EXPRESSION_WRAPPING_PROPERTY,
),
),
Rule.OfficialCodeStyle {
private var indentConfig = DEFAULT_INDENT_CONFIG
private lateinit var functionBodyExpressionWrapping: FunctionSignatureRule.FunctionBodyExpressionWrapping

override fun beforeFirstNode(editorConfig: EditorConfig) {
indentConfig =
IndentConfig(
indentStyle = editorConfig[INDENT_STYLE_PROPERTY],
tabWidth = editorConfig[INDENT_SIZE_PROPERTY],
)
functionBodyExpressionWrapping = editorConfig[FUNCTION_BODY_EXPRESSION_WRAPPING_PROPERTY]
}

override fun beforeVisitChildNodes(
Expand Down Expand Up @@ -172,6 +177,7 @@ public class MultilineExpressionWrappingRule :
null !=
prevCodeSibling()
?.takeIf { it.elementType == EQ || it.elementType == OPERATION_REFERENCE }
?.takeUnless { functionBodyExpressionWrapping == default && it.treeParent.elementType == FUN }
?.takeUnless { it.isElvisOperator() }
?.takeUnless {
it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.pinterest.ktlint.ruleset.standard.rules

import com.pinterest.ktlint.rule.engine.core.api.editorconfig.CODE_STYLE_PROPERTY
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.CodeStyleValue
import com.pinterest.ktlint.ruleset.standard.rules.FunctionSignatureRule.Companion.FUNCTION_BODY_EXPRESSION_WRAPPING_PROPERTY
import com.pinterest.ktlint.ruleset.standard.rules.FunctionSignatureRule.FunctionBodyExpressionWrapping.default
import com.pinterest.ktlint.test.KtLintAssertThat
import com.pinterest.ktlint.test.LintViolation
import com.pinterest.ktlint.test.MULTILINE_STRING_QUOTE
Expand Down Expand Up @@ -360,6 +362,22 @@ class MultilineExpressionWrappingRuleTest {
.isFormattedAs(formattedCode)
}

@Test
fun `Given a function with a multiline body expression, and the function signature body expression wrapping is set to 'default' (eg keep first line of expression on same line)`() {
val code =
"""
fun foo() = bar(
"bar"
)
""".trimIndent()
multilineExpressionWrappingRuleAssertThat(code)
.addAdditionalRuleProvider { IndentationRule() }
.addAdditionalRuleProvider { FunctionSignatureRule() }
.withEditorConfigOverride(CODE_STYLE_PROPERTY to CodeStyleValue.ktlint_official)
.withEditorConfigOverride(FUNCTION_BODY_EXPRESSION_WRAPPING_PROPERTY to default)
.hasNoLintViolations()
}

@Test
fun `Given a function with a multiline signature without a return type but with a multiline expression body starting on same line as closing parenthesis of function`() {
val code =
Expand Down

0 comments on commit 9fbcd2e

Please # to comment.