[JS] Support wrapped and dynamic types in typeOf

This commit is contained in:
Svyatoslav Kuzmich
2019-09-30 18:10:41 +03:00
parent 030aaee117
commit 5d7f18b1b9
6 changed files with 32 additions and 10 deletions
@@ -35,6 +35,7 @@ fun box(): String {
assertEquals("Short?", get1<Short>().toString())
assertEquals("Map<in Short?, Array<Short>>?", get2<Short>().toString())
assertEquals("Map<in List<Short>?, Array<List<Short>>>?", get2<List<Short>>().toString())
assertEquals("Map<in List<dynamic>?, Array<List<dynamic>>>?", get2<List<dynamic>>().toString())
return "OK"
}
@@ -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";
@@ -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<JsExpression>, 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")
@@ -129,9 +129,7 @@ fun <T, S> List<T>.splitToRanges(classifier: (T) -> S): List<Pair<List<T>, 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 {
@@ -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)
@@ -45,6 +45,14 @@ internal class KTypeImpl(
}
}
internal object DynamicKType : KType {
override val classifier: KClassifier? = null
override val arguments: List<KTypeProjection> = emptyList()
override val isMarkedNullable: Boolean = false
override val annotations: List<Annotation> = emptyList()
override fun toString(): String = "dynamic"
}
internal fun KVariance.prefixString() =
when (this) {
KVariance.INVARIANT -> ""