Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent conflict between multiline-expression-wrapping and function-signature #2775

Merged
merged 2 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions documentation/snapshot/docs/rules/standard.md
Original file line number Diff line number Diff line change
Expand Up @@ -4454,6 +4454,8 @@ Suppress or disable rule (1)

Multiline expression on the right hand side of an expression are forced to start on a separate line. Expressions in return statement are excluded as that would result in a compilation error.

Setting `ktlint_function_signature_body_expression_wrapping` of the `function-signature` rule takes precedence when set to `default`. This setting keeps the first line of a multiline expression body on the same line as the end of function signature as long as the max line length is not exceeded. In that case, this rule does not wrap the multiline expression.

=== "[:material-heart:](#) Ktlint"

```kotlin
Expand Down
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