Frontend: allow to use the spread operator in dynamic calls.

This commit is contained in:
Zalim Bashorov
2014-12-11 23:56:21 +03:00
parent 4ac3cbc384
commit 59c4f55988
4 changed files with 84 additions and 26 deletions
@@ -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<ValueParameterDescriptor> =
call.getValueArguments().withIndices().map { p ->
val (index, arg) = p
private fun createValueParameters(owner: DeclarationDescriptor, call: Call): List<ValueParameterDescriptor> {
val type =
when (arg) {
is JetFunctionLiteralArgument -> {
val funLiteral = arg.getFunctionLiteral().getFunctionLiteral()
val parameters = ArrayList<ValueParameterDescriptor>()
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 {
@@ -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, { "" })
}
@@ -0,0 +1,3 @@
package
internal fun test(/*0*/ d: dynamic): kotlin.Unit
@@ -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");