diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/dynamicCalls.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/dynamicCalls.kt index c53e521504b..4c4a62258d6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/dynamicCalls.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/dynamicCalls.kt @@ -49,10 +49,10 @@ import org.jetbrains.jet.lexer.JetTokens import org.jetbrains.jet.lang.types.expressions.OperatorConventions import org.jetbrains.jet.lang.psi.JetOperationReferenceExpression import org.jetbrains.jet.lang.resolve.DescriptorFactory -import org.jetbrains.jet.lang.psi.JetFunctionLiteralArgument import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns -import org.jetbrains.jet.lang.types.TypeUtils +import org.jetbrains.jet.lang.psi.ValueArgument +import java.util.ArrayList object DynamicCallableDescriptors { @@ -165,36 +165,71 @@ object DynamicCallableDescriptors { ) } - private fun createValueParameters(owner: DeclarationDescriptor, call: Call): List = - call.getValueArguments().withIndices().map { p -> - val (index, arg) = p + private fun createValueParameters(owner: DeclarationDescriptor, call: Call): List { - val type = - when (arg) { - is JetFunctionLiteralArgument -> { - val funLiteral = arg.getFunctionLiteral().getFunctionLiteral() + val parameters = ArrayList() - val receiverType = funLiteral.getReceiverTypeReference()?.let { DynamicType } - val parameterTypes = funLiteral.getValueParameters().map { DynamicType } + fun addParameter(arg : ValueArgument, outType: JetType, varargElementType: JetType?) { + val index = parameters.size() - KotlinBuiltIns.getInstance().getFunctionType(Annotations.EMPTY, receiverType, parameterTypes, DynamicType) - } + parameters.add(ValueParameterDescriptorImpl( + owner, + null, + index, + Annotations.EMPTY, + arg.getArgumentName()?.getReferenceExpression()?.getReferencedNameAsName() ?: Name.identifier("p$index"), + outType, + false, + varargElementType, + SourceElement.NO_SOURCE + )) + } - else -> DynamicType - } + fun getFunctionType(arg: JetFunctionLiteralArgument): JetType { + val funLiteral = arg.getFunctionLiteral().getFunctionLiteral() - ValueParameterDescriptorImpl( - owner, - null, - index, - Annotations.EMPTY, - arg.getArgumentName()?.getReferenceExpression()?.getReferencedNameAsName() ?: Name.identifier("p$index"), - type, - false, - null, - SourceElement.NO_SOURCE - ) + val receiverType = funLiteral.getReceiverTypeReference()?.let { DynamicType } + val parameterTypes = funLiteral.getValueParameters().map { DynamicType } + + return KotlinBuiltIns.getInstance().getFunctionType(Annotations.EMPTY, receiverType, parameterTypes, DynamicType) + } + + for (arg in call.getValueArguments()) { + val outType: JetType + val varargElementType: JetType? + var hasSpreadOperator = false + + when { + arg is JetFunctionLiteralArgument -> { + outType = getFunctionType(arg) + varargElementType = null + } + + arg.getSpreadElement() != null -> { + hasSpreadOperator = true + outType = KotlinBuiltIns.getInstance().getArrayType(Variance.OUT_VARIANCE, DynamicType) + varargElementType = DynamicType + } + + else -> { + outType = DynamicType + varargElementType = null + } } + + addParameter(arg, outType, varargElementType) + + if (hasSpreadOperator) { + for (funLiteralArg in call.getFunctionLiteralArguments()) { + addParameter(funLiteralArg, getFunctionType(funLiteralArg), null) + } + + break + } + } + + return parameters + } } public fun DeclarationDescriptor.isDynamic(): Boolean { diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/spreadOperator.kt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/spreadOperator.kt new file mode 100644 index 00000000000..5df9a2e7f84 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/spreadOperator.kt @@ -0,0 +1,14 @@ +fun test(d: dynamic) { + val a = array(1, 2, 3) + + d.foo(*d) + d.foo(*a) + d.foo(1, "2", *a) + d.foo(1, *a) { } + d.foo(*a) { "" } + d.foo(*a, *a) + d.foo(*a, *a) { "" } + d.foo(*a, 1, { "" }, *a) + d.foo(*a, 1) + d.foo(*a, *a, { "" }) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/spreadOperator.txt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/spreadOperator.txt new file mode 100644 index 00000000000..41a648f7f82 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/spreadOperator.txt @@ -0,0 +1,3 @@ +package + +internal fun test(/*0*/ d: dynamic): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestWithJsStdLibGenerated.java index 3e1dbbec8a0..b9f677b9328 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestWithJsStdLibGenerated.java @@ -195,6 +195,12 @@ public class JetDiagnosticsTestWithJsStdLibGenerated extends AbstractJetDiagnost doTest(fileName); } + @TestMetadata("spreadOperator.kt") + public void testSpreadOperator() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/spreadOperator.kt"); + doTest(fileName); + } + @TestMetadata("staticCallsInDynamicContext.kt") public void testStaticCallsInDynamicContext() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/staticCallsInDynamicContext.kt");