[JS] Support typeOf
This commit is contained in:
@@ -75,6 +75,15 @@ public final class Namer {
|
||||
public static final String GET_KCLASS = "getKClass";
|
||||
public static final String GET_KCLASS_FROM_EXPRESSION = "getKClassFromExpression";
|
||||
|
||||
public static final String CREATE_KTYPE = "createKType";
|
||||
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";
|
||||
public static final String GET_START_KTYPE_PROJECTION = "getStarKTypeProjection";
|
||||
public static final String CREATE_COVARIANT_KTYPE_PROJECTION = "createCovariantKTypeProjection";
|
||||
public static final String CREATE_INVARIANT_KTYPE_PROJECTION = "createInvariantKTypeProjection";
|
||||
public static final String CREATE_CONTRAVARIANT_KTYPE_PROJECTION = "createContravariantKTypeProjection";
|
||||
|
||||
public static final String CALLEE_NAME = "$fun";
|
||||
|
||||
public static final String CALL_FUNCTION = "call";
|
||||
|
||||
+2
-1
@@ -39,7 +39,8 @@ class FunctionIntrinsics {
|
||||
AsDynamicFIF,
|
||||
CoroutineContextFIF,
|
||||
SuspendCoroutineUninterceptedOrReturnFIF,
|
||||
InterceptedFIF
|
||||
InterceptedFIF,
|
||||
TypeOfFIF
|
||||
)
|
||||
|
||||
fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.specialFunction
|
||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallInfo
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
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
|
||||
|
||||
object TypeOfFIF : FunctionIntrinsicFactory {
|
||||
override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? =
|
||||
Intrinsic.takeIf { descriptor.fqNameUnsafe.asString() == "kotlin.reflect.typeOf" }
|
||||
|
||||
object Intrinsic : FunctionIntrinsic() {
|
||||
override fun apply(callInfo: CallInfo, arguments: List<JsExpression>, context: TranslationContext): JsExpression {
|
||||
val type = callInfo.resolvedCall.typeArguments.values.single() as SimpleType
|
||||
return KTypeConstructor(context).createKType(type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KTypeConstructor(val context: TranslationContext) {
|
||||
fun callHelperFunction(name: String, vararg arguments: JsExpression) =
|
||||
JsInvocation(context.getReferenceToIntrinsic(name), *arguments)
|
||||
|
||||
fun createKType(type: SimpleType): JsExpression {
|
||||
val classifier: ClassifierDescriptor = type.constructor.declarationDescriptor!!
|
||||
|
||||
if (classifier is TypeParameterDescriptor && classifier.isReified) {
|
||||
val kClassName = context.getNameForIntrinsic(SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE.suggestedName)
|
||||
kClassName.specialFunction = SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE
|
||||
|
||||
val reifiedTypeParameterType = JsInvocation(kClassName.makeRef(), getReferenceToJsClass(classifier, context))
|
||||
if (type.isMarkedNullable) {
|
||||
return callHelperFunction(Namer.MARK_KTYPE_NULLABLE, reifiedTypeParameterType)
|
||||
}
|
||||
|
||||
return reifiedTypeParameterType
|
||||
}
|
||||
|
||||
val kClassifier = createKClassifier(classifier)
|
||||
val arguments = JsArrayLiteral(type.arguments.map { createKTypeProjection(it) })
|
||||
val isMarkedNullable = JsBooleanLiteral(type.isMarkedNullable)
|
||||
return callHelperFunction(
|
||||
Namer.CREATE_KTYPE,
|
||||
kClassifier,
|
||||
arguments,
|
||||
isMarkedNullable
|
||||
)
|
||||
}
|
||||
|
||||
fun createKTypeProjection(tp: TypeProjection): JsExpression {
|
||||
if (tp.isStarProjection) {
|
||||
return callHelperFunction(Namer.GET_START_KTYPE_PROJECTION)
|
||||
}
|
||||
|
||||
val factoryName = when (tp.projectionKind) {
|
||||
Variance.INVARIANT -> Namer.CREATE_INVARIANT_KTYPE_PROJECTION
|
||||
Variance.IN_VARIANCE -> Namer.CREATE_CONTRAVARIANT_KTYPE_PROJECTION
|
||||
Variance.OUT_VARIANCE -> Namer.CREATE_COVARIANT_KTYPE_PROJECTION
|
||||
}
|
||||
|
||||
val kType = createKType(tp.type as SimpleType)
|
||||
return callHelperFunction(factoryName, kType)
|
||||
|
||||
}
|
||||
|
||||
fun createKClassifier(classifier: ClassifierDescriptor): JsExpression =
|
||||
when (classifier) {
|
||||
is TypeParameterDescriptor -> createKTypeParameter(classifier)
|
||||
else -> ExpressionVisitor.getObjectKClass(context, classifier)
|
||||
}
|
||||
|
||||
fun createKTypeParameter(typeParameter: TypeParameterDescriptor): JsExpression {
|
||||
val name = JsStringLiteral(typeParameter.name.asString())
|
||||
val upperBounds = JsArrayLiteral(typeParameter.upperBounds.map { createKType(it as SimpleType) })
|
||||
val variance = when (typeParameter.variance) {
|
||||
Variance.INVARIANT -> JsStringLiteral("invariant")
|
||||
Variance.IN_VARIANCE -> JsStringLiteral("in")
|
||||
Variance.OUT_VARIANCE -> JsStringLiteral("out")
|
||||
}
|
||||
if (typeParameter.isReified) {
|
||||
val kClassName = context.getNameForIntrinsic(SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE.suggestedName)
|
||||
kClassName.specialFunction = SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE
|
||||
|
||||
return JsInvocation(kClassName.makeRef(), getReferenceToJsClass(typeParameter, context))
|
||||
}
|
||||
|
||||
return callHelperFunction(
|
||||
Namer.CREATE_KTYPE_PARAMETER,
|
||||
name,
|
||||
upperBounds,
|
||||
variance
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.expression.ExpressionVisitor
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsicWithReceiverComputed
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.KTypeConstructor
|
||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -39,6 +40,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
@@ -126,7 +128,9 @@ 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)
|
||||
getReferenceToJsClass(type.constructor.declarationDescriptor, context).also {
|
||||
it.kType = KTypeConstructor(context).createKType(type as SimpleType)
|
||||
}
|
||||
|
||||
fun getReferenceToJsClass(classifierDescriptor: ClassifierDescriptor?, context: TranslationContext): JsExpression {
|
||||
return when (classifierDescriptor) {
|
||||
|
||||
Reference in New Issue
Block a user