From dd91ffecd573609a8164d05eeb29f51becfc3409 Mon Sep 17 00:00:00 2001 From: paul-dingemans Date: Thu, 30 Nov 2023 21:23:59 +0100 Subject: [PATCH] Replace all function bodies with body expressions in a single run If a file contains multiple function bodies that have to be replaced with a body expression, then all should be replaced with a single run of ktlint. Closes #2394 --- .../rules/FunctionExpressionBodyRule.kt | 10 ++++---- .../rules/FunctionExpressionBodyRuleTest.kt | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionExpressionBodyRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionExpressionBodyRule.kt index 8514b8a2e1..ae3f7117a0 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionExpressionBodyRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionExpressionBodyRule.kt @@ -23,7 +23,8 @@ 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.firstChildLeafOrSelf import com.pinterest.ktlint.rule.engine.core.api.isWhiteSpace -import com.pinterest.ktlint.rule.engine.core.api.leavesIncludingSelf +import com.pinterest.ktlint.rule.engine.core.api.lastChildLeafOrSelf +import com.pinterest.ktlint.rule.engine.core.api.leavesInClosedRange import com.pinterest.ktlint.rule.engine.core.api.nextSibling import com.pinterest.ktlint.rule.engine.core.api.prevSibling import com.pinterest.ktlint.ruleset.standard.StandardRule @@ -111,7 +112,7 @@ public class FunctionExpressionBodyRule : require(block.elementType == BLOCK) block .takeIf { it.containingOnly(RETURN) } - ?.takeUnless { it.containsMultipleReturns() } + ?.takeUnless { it.countReturnKeywords() > 1 } ?.findChildByType(RETURN) ?.findChildByType(RETURN_KEYWORD) ?.nextSibling { !it.isWhiteSpace() } @@ -164,8 +165,9 @@ public class FunctionExpressionBodyRule : .singleOrNull() ?.elementType - private fun ASTNode.containsMultipleReturns() = - firstChildLeafOrSelf().leavesIncludingSelf().count { it.elementType == RETURN_KEYWORD } > 1 + private fun ASTNode.countReturnKeywords() = + leavesInClosedRange(this.firstChildLeafOrSelf(), this.lastChildLeafOrSelf()) + .count { it.elementType == RETURN_KEYWORD } private fun ASTNode.createUnitTypeReference() = PsiFileFactory diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionExpressionBodyRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionExpressionBodyRuleTest.kt index 10bc76f00f..13f412d84f 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionExpressionBodyRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/FunctionExpressionBodyRuleTest.kt @@ -1,6 +1,7 @@ package com.pinterest.ktlint.ruleset.standard.rules import com.pinterest.ktlint.test.KtLintAssertThat.Companion.assertThatRule +import com.pinterest.ktlint.test.LintViolation import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource @@ -168,4 +169,27 @@ class FunctionExpressionBodyRuleTest { """.trimIndent() functionExpressionBodyRule(code).hasNoLintViolations() } + + @Test + fun `Issue 2394 - Given multiple function bodies with a single return statement`() { + val code = + """ + fun foo1(): String { + return "foo1" + } + fun foo2(): String { + return "foo2" + } + """.trimIndent() + val formattedCode = + """ + fun foo1(): String = "foo1" + fun foo2(): String = "foo2" + """.trimIndent() + functionExpressionBodyRule(code) + .hasLintViolations( + LintViolation(1, 20, "Function body should be replaced with body expression"), + LintViolation(4, 20, "Function body should be replaced with body expression"), + ).isFormattedAs(formattedCode) + } }