From 5d7f18b1b91f9ebf1f1d7620e62657f74beaf308 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Mon, 30 Sep 2019 18:10:41 +0300 Subject: [PATCH] [JS] Support wrapped and dynamic types in typeOf --- .../reflection/typeOf/js/multipleModules.kt | 1 + .../kotlin/js/translate/context/Namer.java | 1 + .../functions/factories/TypeOfFIF.kt | 25 +++++++++++++------ .../kotlin/js/translate/utils/utils.kt | 4 +-- .../js/src/kotlin/reflect/KTypeHelpers.kt | 3 +++ .../stdlib/js/src/kotlin/reflect/KTypeImpl.kt | 8 ++++++ 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/compiler/testData/codegen/box/reflection/typeOf/js/multipleModules.kt b/compiler/testData/codegen/box/reflection/typeOf/js/multipleModules.kt index c9a54b40d09..08801847255 100644 --- a/compiler/testData/codegen/box/reflection/typeOf/js/multipleModules.kt +++ b/compiler/testData/codegen/box/reflection/typeOf/js/multipleModules.kt @@ -35,6 +35,7 @@ fun box(): String { assertEquals("Short?", get1().toString()) assertEquals("Map>?", get2().toString()) assertEquals("Map?, Array>>?", get2>().toString()) + assertEquals("Map?, Array>>?", get2>().toString()) return "OK" } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java index 4f550b9c76d..dd460cf3dd5 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java @@ -76,6 +76,7 @@ public final class Namer { public static final String GET_KCLASS_FROM_EXPRESSION = "getKClassFromExpression"; public static final String CREATE_KTYPE = "createKType"; + public static final String CREATE_DYNAMIC_KTYPE = "createDynamicKType"; public static final String MARK_KTYPE_NULLABLE = "markKTypeNullable"; public static final String CREATE_KTYPE_PARAMETER = "createKTypeParameter"; public static final String CREATE_REIFIED_KTYPE_PARAMETER = "getReifiedTypeParameterKType"; diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt index 1671b54023c..4737823d02e 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TypeOfFIF.kt @@ -18,9 +18,7 @@ import org.jetbrains.kotlin.js.translate.expression.ExpressionVisitor import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic import org.jetbrains.kotlin.js.translate.utils.getReferenceToJsClass import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe -import org.jetbrains.kotlin.types.SimpleType -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.* object TypeOfFIF : FunctionIntrinsicFactory { override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? = @@ -28,7 +26,7 @@ object TypeOfFIF : FunctionIntrinsicFactory { object Intrinsic : FunctionIntrinsic() { override fun apply(callInfo: CallInfo, arguments: List, context: TranslationContext): JsExpression { - val type = callInfo.resolvedCall.typeArguments.values.single() as SimpleType + val type = callInfo.resolvedCall.typeArguments.values.single() return KTypeConstructor(context).createKType(type) } } @@ -38,7 +36,20 @@ class KTypeConstructor(val context: TranslationContext) { fun callHelperFunction(name: String, vararg arguments: JsExpression) = JsInvocation(context.getReferenceToIntrinsic(name), *arguments) - fun createKType(type: SimpleType): JsExpression { + fun createKType(type: KotlinType): JsExpression { + val unwrappedType = type.unwrap() + if (unwrappedType is SimpleType) + return createSimpleKType(unwrappedType) + if (unwrappedType is DynamicType) + return createDynamicType() + error("Unexpected type $type") + } + + private fun createDynamicType(): JsExpression { + return callHelperFunction(Namer.CREATE_DYNAMIC_KTYPE) + } + + private fun createSimpleKType(type: SimpleType): JsExpression { val classifier: ClassifierDescriptor = type.constructor.declarationDescriptor!! if (classifier is TypeParameterDescriptor && classifier.isReified) { @@ -75,7 +86,7 @@ class KTypeConstructor(val context: TranslationContext) { Variance.OUT_VARIANCE -> Namer.CREATE_COVARIANT_KTYPE_PROJECTION } - val kType = createKType(tp.type as SimpleType) + val kType = createKType(tp.type) return callHelperFunction(factoryName, kType) } @@ -88,7 +99,7 @@ class KTypeConstructor(val context: TranslationContext) { fun createKTypeParameter(typeParameter: TypeParameterDescriptor): JsExpression { val name = JsStringLiteral(typeParameter.name.asString()) - val upperBounds = JsArrayLiteral(typeParameter.upperBounds.map { createKType(it as SimpleType) }) + val upperBounds = JsArrayLiteral(typeParameter.upperBounds.map { createKType(it) }) val variance = when (typeParameter.variance) { Variance.INVARIANT -> JsStringLiteral("invariant") Variance.IN_VARIANCE -> JsStringLiteral("in") diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/utils.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/utils.kt index 920117d8055..58e7f8d71c3 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/utils.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/utils.kt @@ -129,9 +129,7 @@ fun List.splitToRanges(classifier: (T) -> S): List, S>> { fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsExpression = getReferenceToJsClass(type.constructor.declarationDescriptor, context).also { - if (type is SimpleType) { - it.kType = KTypeConstructor(context).createKType(type) - } + it.kType = KTypeConstructor(context).createKType(type) } fun getReferenceToJsClass(classifierDescriptor: ClassifierDescriptor?, context: TranslationContext): JsExpression { diff --git a/libraries/stdlib/js/src/kotlin/reflect/KTypeHelpers.kt b/libraries/stdlib/js/src/kotlin/reflect/KTypeHelpers.kt index 9c3fd06a1da..d1011dcac79 100644 --- a/libraries/stdlib/js/src/kotlin/reflect/KTypeHelpers.kt +++ b/libraries/stdlib/js/src/kotlin/reflect/KTypeHelpers.kt @@ -19,6 +19,9 @@ internal fun createKType( ) = KTypeImpl(classifier, arguments.asList(), isMarkedNullable) +@JsName("createDynamicKType") +internal fun createDynamicKType(): KType = DynamicKType + @JsName("markKTypeNullable") internal fun markKTypeNullable(kType: KType) = KTypeImpl(kType.classifier!!, kType.arguments, true) diff --git a/libraries/stdlib/js/src/kotlin/reflect/KTypeImpl.kt b/libraries/stdlib/js/src/kotlin/reflect/KTypeImpl.kt index 2c3e03c8d9c..4a9b7d07be4 100644 --- a/libraries/stdlib/js/src/kotlin/reflect/KTypeImpl.kt +++ b/libraries/stdlib/js/src/kotlin/reflect/KTypeImpl.kt @@ -45,6 +45,14 @@ internal class KTypeImpl( } } +internal object DynamicKType : KType { + override val classifier: KClassifier? = null + override val arguments: List = emptyList() + override val isMarkedNullable: Boolean = false + override val annotations: List = emptyList() + override fun toString(): String = "dynamic" +} + internal fun KVariance.prefixString() = when (this) { KVariance.INVARIANT -> ""