From a89c78d15c77dccfc0dc333a51c1a4d1cc6c6197 Mon Sep 17 00:00:00 2001 From: paul-dingemans Date: Sat, 23 Sep 2023 14:00:17 +0200 Subject: [PATCH 1/2] Do not replace function body having a return statement only in case the return statement contains an intermediate exit point Closes #2269 --- CHANGELOG.md | 1 + .../standard/rules/FunctionExpressionBodyRule.kt | 7 +++++++ .../rules/FunctionExpressionBodyRuleTest.kt | 15 +++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23fd898cf5..f50741a9db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). * Fix indent of multiline object declaration inside class `indent` [#2257](https://github.com/pinterest/ktlint/issue/2257) * Ignore anonymous function in rule `function-naming` [#2260](https://github.com/pinterest/ktlint/issue/2260) * Do not force blank line before function in right hand side of assignment `blank-line-before-declaration` [#2260](https://github.com/pinterest/ktlint/issue/2260) +* Do not replace function body having a return statement only in case the return statement contains an intermediate exit point 'function-expression-body' [#2269](https://github.com/pinterest/ktlint/issue/2269) ### Changed 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 d9a7ef01b9..0e3b84cd8f 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 @@ -21,7 +21,9 @@ import com.pinterest.ktlint.rule.engine.core.api.editorconfig.EditorConfig import com.pinterest.ktlint.rule.engine.core.api.editorconfig.INDENT_SIZE_PROPERTY import com.pinterest.ktlint.rule.engine.core.api.editorconfig.INDENT_STYLE_PROPERTY 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.nextSibling import com.pinterest.ktlint.rule.engine.core.api.prevSibling import com.pinterest.ktlint.ruleset.standard.StandardRule @@ -36,6 +38,7 @@ import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtScript import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.psi.psiUtil.getChildOfType +import org.jetbrains.kotlin.psi.psiUtil.leaves /** * [Kotlin Coding Conventions](https://kotlinlang.org/docs/coding-conventions.html#functions): @@ -109,6 +112,7 @@ public class FunctionExpressionBodyRule : require(block.elementType == BLOCK) block .takeIf { it.containingOnly(RETURN) } + ?.takeUnless { it.containsMultipleReturns() } ?.findChildByType(RETURN) ?.findChildByType(RETURN_KEYWORD) ?.nextSibling { !it.isWhiteSpace() } @@ -161,6 +165,9 @@ public class FunctionExpressionBodyRule : .singleOrNull() ?.elementType + private fun ASTNode.containsMultipleReturns() = + firstChildLeafOrSelf().leavesIncludingSelf().count { it.elementType == RETURN_KEYWORD } > 1 + private fun ASTNode.createUnitTypeReference() = PsiFileFactory .getInstance(psi.project) 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 7c2fa3b07e..10bc76f00f 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 @@ -153,4 +153,19 @@ class FunctionExpressionBodyRuleTest { .isFormattedAs(formattedCode) .hasLintViolation(1, 16, "Function body should be replaced with body expression") } + + @Test + fun `Given a function with a single expression but having multiple return expression inside then do not covert as it results in a compilation error`() { + val code = + """ + fun foo(): Any { + return if (true) { + Foo() + } else { + return Bar() + } + } + """.trimIndent() + functionExpressionBodyRule(code).hasNoLintViolations() + } } From bb72b54990f88a9b8ced427365a50f77c21c5515 Mon Sep 17 00:00:00 2001 From: paul-dingemans Date: Sat, 23 Sep 2023 14:29:24 +0200 Subject: [PATCH 2/2] Fix lint violation --- .../ktlint/ruleset/standard/rules/FunctionExpressionBodyRule.kt | 1 - 1 file changed, 1 deletion(-) 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 0e3b84cd8f..8514b8a2e1 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 @@ -38,7 +38,6 @@ import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtScript import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.psi.psiUtil.getChildOfType -import org.jetbrains.kotlin.psi.psiUtil.leaves /** * [Kotlin Coding Conventions](https://kotlinlang.org/docs/coding-conventions.html#functions):