diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCount.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCount.kt index e0d05d66850..2215668712b 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCount.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCount.kt @@ -13,8 +13,7 @@ import io.gitlab.arturbosch.detekt.api.internal.Configuration import io.gitlab.arturbosch.detekt.api.simplePatternToRegex import io.gitlab.arturbosch.detekt.rules.parentsOfTypeUntil import io.gitlab.arturbosch.detekt.rules.yieldStatementsSkippingGuardClauses -import org.jetbrains.kotlin.psi.KtCallExpression -import org.jetbrains.kotlin.psi.KtNameReferenceExpression +import org.jetbrains.kotlin.psi.KtLambdaExpression import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtReturnExpression import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType @@ -93,11 +92,9 @@ class ReturnCount(config: Config = Config.empty) : Rule(config) { private fun shouldBeIgnored(function: KtNamedFunction) = function.name in excludedFunctions private fun countReturnStatements(function: KtNamedFunction): Int { - fun KtReturnExpression.isExcluded(): Boolean = when { - excludeLabeled && labeledExpression != null -> true - excludeReturnFromLambda && isNamedReturnFromLambda() -> true - else -> false - } + fun KtReturnExpression.isExcluded(): Boolean = + (excludeReturnFromLambda && isNamedReturnFromLambda()) || + (excludeLabeled && labeledExpression != null) val statements = if (excludeGuardClauses) { function.yieldStatementsSkippingGuardClauses() @@ -113,11 +110,7 @@ class ReturnCount(config: Config = Config.empty) : Rule(config) { private fun KtReturnExpression.isNamedReturnFromLambda(): Boolean { val label = this.labeledExpression if (label != null) { - return this.parentsOfTypeUntil() - .map { it.calleeExpression } - .filterIsInstance() - .map { it.text } - .any { it in label.text } + return this.parentsOfTypeUntil().any() } return false } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCountSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCountSpec.kt index a0966fc9154..b9e43bd7dc8 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCountSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCountSpec.kt @@ -512,4 +512,42 @@ class ReturnCountSpec { assertThat(findings).isEmpty() } } + + @Nested + inner class `function with lambda which has explicit label` { + val code = """ + fun test() { + listOf(1, 2, 3, 4, 5).forEach lit@{ + if (it == 3) return@lit + if (it == 4) return@lit + } + return + } + """.trimIndent() + + @Test + fun `should count labeled return of lambda with explicit label`() { + val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_RETURN_FROM_LAMBDA to "false"))).compileAndLint(code) + assertThat(findings).hasSize(1) + } + + @Test + fun `should not count labeled return of lambda with explicit label when deactivated by default`() { + val findings = ReturnCount().compileAndLint(code) + assertThat(findings).isEmpty() + } + + @Test + fun `excludeReturnFromLambda should take precedence over excludeLabeled`() { + val findings = ReturnCount( + TestConfig( + mapOf( + EXCLUDE_RETURN_FROM_LAMBDA to "true", + EXCLUDE_LABELED to "false" + ) + ) + ).compileAndLint(code) + assertThat(findings).isEmpty() + } + } }