diff options
author | Paul Dingemans <paul-dingemans@users.noreply.github.com> | 2024-03-15 15:23:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-15 15:23:03 +0100 |
commit | afd32bc573345c2b8c5795c8b27b13483bdf2ae9 (patch) | |
tree | 3b085fb7e5aa9f147f41b6754750fbde7363ca1f | |
parent | d42914269714c8ca9cd1e3901b684c4492bad928 (diff) | |
download | ktlint-afd32bc573345c2b8c5795c8b27b13483bdf2ae9.tar.gz |
Do not merge opening quotes of multiline string template with (single line) function signature (#2609)
Closes #2592
2 files changed, 74 insertions, 8 deletions
diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRule.kt index d41b35e5..b8f09641 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRule.kt @@ -1,5 +1,6 @@ package com.pinterest.ktlint.ruleset.standard.rules +import com.pinterest.ktlint.rule.engine.core.api.ElementType import com.pinterest.ktlint.rule.engine.core.api.ElementType.ANNOTATED_EXPRESSION import com.pinterest.ktlint.rule.engine.core.api.ElementType.ANNOTATION import com.pinterest.ktlint.rule.engine.core.api.ElementType.ANNOTATION_ENTRY @@ -33,6 +34,7 @@ import com.pinterest.ktlint.rule.engine.core.api.editorconfig.INDENT_STYLE_PROPE import com.pinterest.ktlint.rule.engine.core.api.editorconfig.MAX_LINE_LENGTH_PROPERTY import com.pinterest.ktlint.rule.engine.core.api.editorconfig.MAX_LINE_LENGTH_PROPERTY_OFF import com.pinterest.ktlint.rule.engine.core.api.indent +import com.pinterest.ktlint.rule.engine.core.api.isCodeLeaf import com.pinterest.ktlint.rule.engine.core.api.isWhiteSpace import com.pinterest.ktlint.rule.engine.core.api.isWhiteSpaceWithNewline import com.pinterest.ktlint.rule.engine.core.api.nextCodeLeaf @@ -563,14 +565,16 @@ public class FunctionSignatureRule : return } val mergeWithFunctionSignature = - if (firstLineOfBodyExpression.length < maxLengthRemainingForFirstLineOfBodyExpression) { - functionBodyExpressionWrapping == default || - (functionBodyExpressionWrapping == multiline && functionBodyExpressionLines.size == 1) || - node.isMultilineFunctionSignatureWithoutExplicitReturnType( - lastNodeOfFunctionSignatureWithBodyExpression, - ) - } else { - false + when { + firstLineOfBodyExpression.length < maxLengthRemainingForFirstLineOfBodyExpression -> { + (functionBodyExpressionWrapping == default && !functionBodyExpressionNodes.isMultilineStringTemplate()) || + (functionBodyExpressionWrapping == multiline && functionBodyExpressionLines.size == 1) || + node.isMultilineFunctionSignatureWithoutExplicitReturnType( + lastNodeOfFunctionSignatureWithBodyExpression, + ) + } + + else -> false } if (mergeWithFunctionSignature) { emit( @@ -621,6 +625,17 @@ public class FunctionSignatureRule : } } + private fun List<ASTNode>.isMultilineStringTemplate() = + first { it.isCodeLeaf() } + .let { + it.elementType == ElementType.OPEN_QUOTE && + it + .nextLeaf() + ?.text + .orEmpty() + .startsWith("\n") + } + private fun ASTNode.isMultilineFunctionSignatureWithoutExplicitReturnType(lastNodeOfFunctionSignatureWithBodyExpression: ASTNode?) = functionSignatureNodes() .childrenBetween( diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRuleTest.kt index 9473d606..0fbf6717 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRuleTest.kt @@ -13,6 +13,7 @@ import com.pinterest.ktlint.test.KtLintAssertThat.Companion.EOL_CHAR import com.pinterest.ktlint.test.KtLintAssertThat.Companion.MAX_LINE_LENGTH_MARKER import com.pinterest.ktlint.test.KtLintAssertThat.Companion.assertThatRuleBuilder import com.pinterest.ktlint.test.LintViolation +import com.pinterest.ktlint.test.MULTILINE_STRING_QUOTE import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.jupiter.api.DisplayName @@ -1313,6 +1314,56 @@ class FunctionSignatureRuleTest { .hasNoLintViolations() } + @Test + fun `Issue 2592 - Given a function signature with an expression body that is multiline raw string literal then do not join the first leaf with the function signature`() { + val code = + """ + // $MAX_LINE_LENGTH_MARKER $EOL_CHAR + fun foo1(): String = + $MULTILINE_STRING_QUOTE + some text + $MULTILINE_STRING_QUOTE.trimIndent() + fun foo2() = + $MULTILINE_STRING_QUOTE + some text + $MULTILINE_STRING_QUOTE.trimIndent() + """.trimIndent() + functionSignatureWrappingRuleAssertThat(code) + .setMaxLineLength() + .withEditorConfigOverride(FUNCTION_BODY_EXPRESSION_WRAPPING_PROPERTY to default) + .hasNoLintViolations() + } + + @Test + fun `Issue 2592 - Given a multiline function signature with an expression body that is multiline raw string literal then do join the first leaf with the function signature`() { + val code = + """ + // $MAX_LINE_LENGTH_MARKER $EOL_CHAR + fun foo( + foo: Foo, + bar: Bar, + ) = + $MULTILINE_STRING_QUOTE + some text + $MULTILINE_STRING_QUOTE.trimIndent() + """.trimIndent() + val formattedCode = + """ + // $MAX_LINE_LENGTH_MARKER $EOL_CHAR + fun foo( + foo: Foo, + bar: Bar, + ) = $MULTILINE_STRING_QUOTE + some text + $MULTILINE_STRING_QUOTE.trimIndent() + """.trimIndent() + functionSignatureWrappingRuleAssertThat(code) + .setMaxLineLength() + .withEditorConfigOverride(FUNCTION_BODY_EXPRESSION_WRAPPING_PROPERTY to default) + .hasLintViolation(5, 4, "First line of body expression fits on same line as function signature") + .isFormattedAs(formattedCode) + } + private companion object { const val UNEXPECTED_SPACES = " " const val NO_SPACE = "" |