diff --git a/compiler/frontend.script/src/org/jetbrains/kotlin/script/reflectionUtil.kt b/compiler/frontend.script/src/org/jetbrains/kotlin/script/reflectionUtil.kt index a496bab472f..f92b293a5f1 100644 --- a/compiler/frontend.script/src/org/jetbrains/kotlin/script/reflectionUtil.kt +++ b/compiler/frontend.script/src/org/jetbrains/kotlin/script/reflectionUtil.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.script -import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import kotlin.reflect.* import kotlin.reflect.full.isSubclassOf import kotlin.reflect.jvm.jvmErasure @@ -160,18 +159,6 @@ private class StringArgsConverter : ArgsConverter { override fun tryConvertVararg(parameter: KParameter, firstArg: NamedArgument, restArgsIt: Iterator>): ArgsConverter.Result { - fun convertAnyArray(classifier: KClassifier?, args: Sequence): Any? = - when (classifier) { - String::class -> args.toList().toTypedArray() - is KClass<*> -> classifier.constructors.firstNotNullResult { ctor -> - try { - args.map { ctor.call(it) }.toList().toTypedArray() - } - catch (e: Exception) { null } - } - else -> null - } - fun convertPrimitivesArray(type: KType, args: Sequence): Any? = when (type.classifier) { IntArray::class -> args.map { it?.toIntOrNull() } @@ -228,9 +215,42 @@ private class AnyArgsConverter : ArgsConverter { ?: ArgsConverter.Result.Failure } - override fun tryConvertVararg(parameter: KParameter, firstArg: NamedArgument, restArgsIt: Iterator>): ArgsConverter.Result = - ArgsConverter.Result.Failure + override fun tryConvertVararg( + parameter: KParameter, firstArg: NamedArgument, restArgsIt: Iterator> + ): ArgsConverter.Result { + + val parameterType = parameter.type + if (parameterType.jvmErasure.java.isArray) { + val argsSequence = sequenceOf(firstArg.value) + restArgsIt.asSequence().map { it.value } + val arrayElementType = parameterType.arguments.firstOrNull()?.type + val arrayArgCandidate = convertAnyArray(arrayElementType?.classifier, argsSequence) + if (arrayArgCandidate != null) + return ArgsConverter.Result.Success(arrayArgCandidate) + } + + return ArgsConverter.Result.Failure + } override fun tryConvertTail(parameter: KParameter, firstArg: NamedArgument, restArgsIt: Iterator>): ArgsConverter.Result = tryConvertSingle(parameter, firstArg) } + +@Suppress("UNCHECKED_CAST") +private inline fun convertAnyArray(classifier: KClassifier?, args: Sequence): Any? = + if (classifier == T::class) args.toList().toTypedArray() // simple case + else convertAnyArrayImpl(classifier, args) + +private fun convertAnyArrayImpl(classifier: KClassifier?, args: Sequence): Any? { + val elementClass = (classifier as? KClass<*>) ?: return null + + val argsList = args.toList() + val result = java.lang.reflect.Array.newInstance(elementClass.java, argsList.size) + argsList.forEachIndexed { idx, arg -> + try { + java.lang.reflect.Array.set(result, idx, arg) + } catch (e: IllegalArgumentException) { + return@convertAnyArrayImpl null + } + } + return result +} diff --git a/compiler/tests/org/jetbrains/kotlin/util/ArgsToParamsMatchingTest.kt b/compiler/tests/org/jetbrains/kotlin/util/ArgsToParamsMatchingTest.kt index de13befd5cb..1d7842b7289 100644 --- a/compiler/tests/org/jetbrains/kotlin/util/ArgsToParamsMatchingTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/util/ArgsToParamsMatchingTest.kt @@ -74,6 +74,9 @@ class ArgsToParamsMatchingTest { assertParamMapsEquals(tryCreateCallableMappingFromNamedArgs(::notNullNumber, listOf(null to 42)), "n" to 42) Assert.assertNull(tryCreateCallableMappingFromNamedArgs(::notNullNumber, listOf(null to "42"))) + + assertParamMapsEquals(tryCreateCallableMappingFromNamedArgs(::varargStrings, listOf("a", "b", "c").map { null to it }), + "s" to arrayOf("a", "b", "c")) } }