Skip to content

Commit

Permalink
MultilineLambdaItParameter: fix false positive for one-line statement…
Browse files Browse the repository at this point in the history
…s with a lambda argument (#5505)
  • Loading branch information
t-kameyama committed Nov 5, 2022
1 parent 9b38f67 commit 9306a27
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
Expand Up @@ -12,8 +12,10 @@ import io.gitlab.arturbosch.detekt.rules.IT_LITERAL
import io.gitlab.arturbosch.detekt.rules.hasImplicitParameterReference
import io.gitlab.arturbosch.detekt.rules.implicitParameter
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
import org.jetbrains.kotlin.utils.ifEmpty

/**
* Lambda expressions are very useful in a lot of cases, and they often include very small chunks of
Expand Down Expand Up @@ -76,8 +78,10 @@ class MultilineLambdaItParameter(val config: Config) : Rule(config) {

override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {
super.visitLambdaExpression(lambdaExpression)
val size = lambdaExpression.collectDescendantsOfType<KtBlockExpression>().sumOf { it.statements.size }
if (size <= 1) return

val statements = lambdaExpression.bodyExpression?.statements.orEmpty().ifEmpty { return }
val single = statements.singleOrNull()
if (single != null && (single.hasNoLineBreak() || single.hasNoStatements())) return

val parameterNames = lambdaExpression.valueParameters.map { it.name }
// Explicit `it`
Expand Down Expand Up @@ -106,4 +110,9 @@ class MultilineLambdaItParameter(val config: Config) : Rule(config) {
}
}
}

private fun KtExpression.hasNoLineBreak() = !textContains('\n')

private fun KtExpression.hasNoStatements() =
!anyDescendantOfType<KtBlockExpression> { it.statements.isNotEmpty() }
}
Expand Up @@ -121,14 +121,32 @@ class MultilineLambdaItParameterSpec(val env: KotlinCoreEnvironment) {
fun f() {
val digits = 1234.let {
check(it > 0) {
println(it)
println("error")
}
}
}
""".trimIndent()
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).hasSize(1)
}

@Test
fun `does not report when statement has no nested statements`() {
val code = """
data class Foo(val x: Int, val y: Int)
fun f(i: Int?) {
val foo = i?.let {
Foo(
x = it,
y = 2
)
}
}
""".trimIndent()
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).isEmpty()
}
}

@Nested
Expand Down Expand Up @@ -171,6 +189,19 @@ class MultilineLambdaItParameterSpec(val env: KotlinCoreEnvironment) {
val code = """
fun f() {
val digits = 1234.let { param -> listOf(param) }
}
""".trimIndent()
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).isEmpty()
}

@Test
fun `does not report when statement has one-line lambda argument`() {
val code = """
fun f() {
val digits = 1234.let {
check(it > 0) { println("error") }
}
}
""".trimIndent()
val findings = subject.compileAndLintWithContext(env, code)
Expand Down

0 comments on commit 9306a27

Please sign in to comment.