aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Dingemans <paul-dingemans@users.noreply.github.com>2024-03-15 15:23:03 +0100
committerGitHub <noreply@github.com>2024-03-15 15:23:03 +0100
commitafd32bc573345c2b8c5795c8b27b13483bdf2ae9 (patch)
tree3b085fb7e5aa9f147f41b6754750fbde7363ca1f
parentd42914269714c8ca9cd1e3901b684c4492bad928 (diff)
downloadktlint-afd32bc573345c2b8c5795c8b27b13483bdf2ae9.tar.gz
Do not merge opening quotes of multiline string template with (single line) function signature (#2609)
Closes #2592
-rw-r--r--ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRule.kt31
-rw-r--r--ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionSignatureRuleTest.kt51
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 = ""