Repository: detekt/detekt (kotlin)

Issue:
False positive on UnnecessaryBracesAroundTrailingLambda with vararg lambdas
Already reported in issue #6593, but not fixed back in the day. Occurred to me since the update to 2.0.0-alpha.0.

Minimal reproducer:

```kotlin
import assertk.Assert
import assertk.assertThat

data class LogEvent(val message: String)

fun Assert<List<LogEvent>>.hasLogEvents(vararg matchers: Assert<LogEvent>.() -> Unit) =
    given { actual ->
        assertAll {
            actual.forEachIndexed { index, event ->
                matchers[index](assertThat(event, name = appendName(show(index, "[]"), separator = ".")))
            }
        }
    }

assertThat(listOf(LogEvent("foo")))
    .hasLogEvents({
        TODO("first assertion for first event")
    })

assertThat(listOf(LogEvent("foo"), LogEvent("bar")))
    .hasLogEvents({
        TODO("first assertion for first event")
    },
    {
        TODO("first assertion for second event")
    })
```

Pull request:
Fixes https://github.com/detekt/detekt/issues/8638

Patch:
diff --git a/detekt-rules-style/src/main/kotlin/dev/detekt/rules/style/movelambdaout/MoveLambdaOutsideParenthesesInspection.kt b/detekt-rules-style/src/main/kotlin/dev/detekt/rules/style/movelambdaout/MoveLambdaOutsideParenthesesInspection.kt
index 532f31423313..7accee197432 100644
--- a/detekt-rules-style/src/main/kotlin/dev/detekt/rules/style/movelambdaout/MoveLambdaOutsideParenthesesInspection.kt
+++ b/detekt-rules-style/src/main/kotlin/dev/detekt/rules/style/movelambdaout/MoveLambdaOutsideParenthesesInspection.kt
@@ -44,18 +44,20 @@ private fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean {
             val candidate =
                 callee.resolveToCall()?.successfulCallOrNull<KaCallableMemberCall<*, *>>()
                     ?: return false
-            val params = when (candidate) {
+            val paramsType = when (candidate) {
                 is KaFunctionCall -> {
-                    candidate.symbol.valueParameters.map { it.returnType }
+                    val params = candidate.symbol.valueParameters
+                    if (params.lastOrNull()?.isVararg != false) return false
+                    params.map { it.returnType }
                 }
 
                 is KaVariableAccessCall -> {
                     (candidate.symbol.returnType as? KaFunctionType)?.parameterTypes.orEmpty()
                 }
             }
-            val lastParamType = params.lastOrNull() ?: return false
+            val lastParamType = paramsType.lastOrNull() ?: return false
             return lastParamType.isFunctionOrSuspendingFunctionOrGenericType &&
-                params.count { it.isFunctionOrSuspendingFunctionOrGenericType } ==
+                paramsType.count { it.isFunctionOrSuspendingFunctionOrGenericType } ==
                 lambdaArgumentCount + referenceArgumentCount
         }
     }


Test patch:
diff --git a/detekt-rules-style/src/test/kotlin/dev/detekt/rules/style/movelambdaout/UnnecessaryBracesAroundTrailingLambdaSpec.kt b/detekt-rules-style/src/test/kotlin/dev/detekt/rules/style/movelambdaout/UnnecessaryBracesAroundTrailingLambdaSpec.kt
index 0dbff400386c..93da5e0f2603 100644
--- a/detekt-rules-style/src/test/kotlin/dev/detekt/rules/style/movelambdaout/UnnecessaryBracesAroundTrailingLambdaSpec.kt
+++ b/detekt-rules-style/src/test/kotlin/dev/detekt/rules/style/movelambdaout/UnnecessaryBracesAroundTrailingLambdaSpec.kt
@@ -327,4 +327,16 @@ class UnnecessaryBracesAroundTrailingLambdaSpec(val env: KotlinEnvironmentContai
         val findings = subject.lintWithContext(env, code)
         assertThat(findings).isEmpty()
     }
+
+    @Test
+    fun `does not report when lambdas is vararg - #8638`() {
+        val code = """
+            fun foo(vararg mappers: () -> Unit) = mappers.map { it() }
+            fun test() {
+                foo({})
+            }
+        """.trimIndent()
+        val findings = subject.lintWithContext(env, code)
+        assertThat(findings).isEmpty()
+    }
 }