Repository: detekt/detekt (kotlin)

Issue:
NamedArguments: False positive on spread varargs
<!-- The bug you're experiencing might have already be reported! -->
<!-- Please search in the [issues](https://github.com/detekt/detekt/issues) before creating one. -->

## Expected Behavior
No flagging on varargs (unless maybe there's 3 or 4 other nameable arguments).

## Observed Behavior
> This function call has 4 arguments. To call a function with more than 3 arguments you should set the name of each argument. [NamedArguments]

## Steps to Reproduce
```kotlin
fun varargFun(str: String, vararg nums: Int) { TODO(str + nums) }

fun call() {
	varargFun("a", 1, 2, 3, 4, 5) // this is fine (no NamedArguments)
	val nums1 = intArrayOf(1, 2, 3) // simulate
	val nums2 = intArrayOf(4, 5, 6) // complex
	val nums3 = intArrayOf(7, 8, 9) // logic
	varargFun("a", *nums1, *nums2, *nums3) // this is not (unexpected NamedArguments)
}
```

## Context
It's impossible to add named arguments in this case, the best we can do is `varargFun(str = "a", ...)` but even that is flagged.

## Your Environment
<!-- Include as many relevant details about the environment you experienced the bug in -->
* Version of detekt used: 1.23.6
* Version of Gradle used (if applicable): 8.7
* Gradle scan link (add `--scan` option when running the gradle task): N/A
* Operating System and version: N/A
* Link to your project (if it's a public repository): N/A

Pull request:
Fixes #7272

Patch:
diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArguments.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArguments.kt
index 44c792757153..6cb3ca9040fd 100644
--- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArguments.kt
+++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArguments.kt
@@ -9,6 +9,7 @@ import io.gitlab.arturbosch.detekt.api.Rule
 import io.gitlab.arturbosch.detekt.api.config
 import org.jetbrains.kotlin.psi.KtCallExpression
 import org.jetbrains.kotlin.psi.KtLambdaArgument
+import org.jetbrains.kotlin.resolve.calls.components.isVararg
 import org.jetbrains.kotlin.resolve.calls.util.getParameterForArgument
 import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
 
@@ -58,17 +59,14 @@ class NamedArguments(config: Config) : Rule(
         val unnamedArguments = valueArguments.mapNotNull { argument ->
             if (argument.isNamed() || argument is KtLambdaArgument) return@mapNotNull null
             val parameter = resolvedCall.getParameterForArgument(argument) ?: return@mapNotNull null
-            if (ignoreArgumentsMatchingNames &&
-                parameter.name.asString() == argument.getArgumentExpression()?.text
-            ) {
+            if (ignoreArgumentsMatchingNames && parameter.name.asString() == argument.getArgumentExpression()?.text) {
                 return@mapNotNull null
             }
             argument to parameter
         }
-        if (unnamedArguments.isEmpty()) return false
 
-        return unnamedArguments.all { (argument, parameter) ->
-            argument.getSpreadElement() != null || parameter.varargElementType == null
-        }
+        return unnamedArguments.isNotEmpty() &&
+            unnamedArguments.count { (argument, _) -> argument.isSpread } <= 1 &&
+            unnamedArguments.all { (argument, parameter) -> argument.isSpread || !parameter.isVararg }
     }
 }


Test patch:
diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArgumentsSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArgumentsSpec.kt
index ad5e7cfe1ed7..eeaf340a0bb1 100644
--- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArgumentsSpec.kt
+++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArgumentsSpec.kt
@@ -144,6 +144,21 @@ class NamedArgumentsSpec(val env: KotlinCoreEnvironment) {
         assertThat(findings).isEmpty()
     }
 
+    @Test
+    fun `invocation with spread varargs should not be flagged`() {
+        val code = """
+            fun varargFun(str: String, vararg nums: Int) {}
+            fun call() {
+                val nums1 = intArrayOf(1, 2, 3)
+                val nums2 = intArrayOf(4, 5, 6)
+                val nums3 = intArrayOf(7, 8, 9)
+                varargFun("a", *nums1, *nums2, *nums3)
+            }
+        """.trimIndent()
+        val findings = subject.compileAndLintWithContext(env, code)
+        assertThat(findings).isEmpty()
+    }
+
     @Test
     fun `invocation with spread operator should be flagged`() {
         val code = """