Translate KClass references to built-in types in serialization plugin correctly.
Add overload with ClassDescriptor to `getPrimitiveClass` translation function and increase it visibility to public to be usable from plugin.
This commit is contained in:
+49
-42
@@ -267,11 +267,13 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
DoubleColonLHS lhs = context.bindingContext().get(DOUBLE_COLON_LHS, receiverExpression);
|
||||
assert lhs != null : "Class literal expression should have LHS resolved";
|
||||
|
||||
ClassifierDescriptor descriptor = lhs.getType().getConstructor().getDeclarationDescriptor();
|
||||
|
||||
if (lhs instanceof DoubleColonLHS.Expression && !((DoubleColonLHS.Expression) lhs).isObjectQualifier()) {
|
||||
JsExpression receiver = translateAsExpression(receiverExpression, context);
|
||||
receiver = TranslationUtils.coerce(context, receiver, context.getCurrentModule().getBuiltIns().getAnyType());
|
||||
if (isPrimitiveClassLiteral(lhs.getType())) {
|
||||
JsExpression primitiveExpression = getPrimitiveClass(context, lhs.getType());
|
||||
JsExpression primitiveExpression = getPrimitiveClass(context, descriptor);
|
||||
if (primitiveExpression != null) {
|
||||
return JsAstUtils.newSequence(Arrays.asList(receiver, primitiveExpression));
|
||||
}
|
||||
@@ -279,54 +281,59 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
return new JsInvocation(context.namer().kotlin(GET_KCLASS_FROM_EXPRESSION), receiver);
|
||||
}
|
||||
|
||||
JsExpression primitiveExpression = getPrimitiveClass(context, lhs.getType());
|
||||
if (primitiveExpression != null) return primitiveExpression;
|
||||
return new JsInvocation(context.getReferenceToIntrinsic(GET_KCLASS), UtilsKt.getReferenceToJsClass(lhs.getType(), context));
|
||||
return getObjectKClass(context, descriptor);
|
||||
}
|
||||
|
||||
private static JsExpression getPrimitiveClass(@NotNull TranslationContext context, @NotNull KotlinType type) {
|
||||
@NotNull
|
||||
public static JsExpression getObjectKClass(@NotNull TranslationContext context, @Nullable ClassifierDescriptor descriptor) {
|
||||
JsExpression primitiveExpression = getPrimitiveClass(context, descriptor);
|
||||
if (primitiveExpression != null) return primitiveExpression;
|
||||
return new JsInvocation(context.getReferenceToIntrinsic(GET_KCLASS), UtilsKt.getReferenceToJsClass(descriptor, context));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JsExpression getPrimitiveClass(@NotNull TranslationContext context, @Nullable ClassifierDescriptor classifierDescriptor) {
|
||||
if (!context.getConfig().isAtLeast(LanguageVersion.KOTLIN_1_2) || findPrimitiveClassesObject(context) == null) return null;
|
||||
if (!(classifierDescriptor instanceof ClassDescriptor)) return null;
|
||||
ClassDescriptor descriptor = (ClassDescriptor) classifierDescriptor;
|
||||
|
||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
FqName fqName = DescriptorUtilsKt.getFqNameSafe(descriptor);
|
||||
switch (fqName.asString()) {
|
||||
case "kotlin.Boolean":
|
||||
case "kotlin.Byte":
|
||||
case "kotlin.Short":
|
||||
case "kotlin.Int":
|
||||
case "kotlin.Float":
|
||||
case "kotlin.Double":
|
||||
case "kotlin.String":
|
||||
case "kotlin.Array":
|
||||
case "kotlin.Any":
|
||||
case "kotlin.Throwable":
|
||||
case "kotlin.Number":
|
||||
case "kotlin.Nothing":
|
||||
case "kotlin.BooleanArray":
|
||||
case "kotlin.CharArray":
|
||||
case "kotlin.ByteArray":
|
||||
case "kotlin.ShortArray":
|
||||
case "kotlin.IntArray":
|
||||
case "kotlin.LongArray":
|
||||
case "kotlin.FloatArray":
|
||||
case "kotlin.DoubleArray":
|
||||
return getKotlinPrimitiveClassRef(context, StringUtil.decapitalize(fqName.shortName().asString()) + "Class");
|
||||
FqName fqName = DescriptorUtilsKt.getFqNameSafe(descriptor);
|
||||
switch (fqName.asString()) {
|
||||
case "kotlin.Boolean":
|
||||
case "kotlin.Byte":
|
||||
case "kotlin.Short":
|
||||
case "kotlin.Int":
|
||||
case "kotlin.Float":
|
||||
case "kotlin.Double":
|
||||
case "kotlin.String":
|
||||
case "kotlin.Array":
|
||||
case "kotlin.Any":
|
||||
case "kotlin.Throwable":
|
||||
case "kotlin.Number":
|
||||
case "kotlin.Nothing":
|
||||
case "kotlin.BooleanArray":
|
||||
case "kotlin.CharArray":
|
||||
case "kotlin.ByteArray":
|
||||
case "kotlin.ShortArray":
|
||||
case "kotlin.IntArray":
|
||||
case "kotlin.LongArray":
|
||||
case "kotlin.FloatArray":
|
||||
case "kotlin.DoubleArray":
|
||||
return getKotlinPrimitiveClassRef(context, StringUtil.decapitalize(fqName.shortName().asString()) + "Class");
|
||||
|
||||
default: {
|
||||
if (descriptor instanceof FunctionClassDescriptor) {
|
||||
FunctionClassDescriptor functionClassDescriptor = (FunctionClassDescriptor) descriptor;
|
||||
if (functionClassDescriptor.getFunctionKind() == FunctionClassDescriptor.Kind.Function) {
|
||||
ClassDescriptor primitivesObject = findPrimitiveClassesObject(context);
|
||||
assert primitivesObject != null;
|
||||
FunctionDescriptor function = DescriptorUtils.getFunctionByName(
|
||||
primitivesObject.getUnsubstitutedMemberScope(), Name.identifier("functionClass"));
|
||||
JsExpression functionRef = pureFqn(context.getInlineableInnerNameForDescriptor(function), null);
|
||||
return new JsInvocation(functionRef, new JsIntLiteral(functionClassDescriptor.getArity()));
|
||||
}
|
||||
default: {
|
||||
if (descriptor instanceof FunctionClassDescriptor) {
|
||||
FunctionClassDescriptor functionClassDescriptor = (FunctionClassDescriptor) descriptor;
|
||||
if (functionClassDescriptor.getFunctionKind() == FunctionClassDescriptor.Kind.Function) {
|
||||
ClassDescriptor primitivesObject = findPrimitiveClassesObject(context);
|
||||
assert primitivesObject != null;
|
||||
FunctionDescriptor function = DescriptorUtils.getFunctionByName(
|
||||
primitivesObject.getUnsubstitutedMemberScope(), Name.identifier("functionClass"));
|
||||
JsExpression functionRef = pureFqn(context.getInlineableInnerNameForDescriptor(function), null);
|
||||
return new JsInvocation(functionRef, new JsIntLiteral(functionClassDescriptor.getArity()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -122,9 +122,10 @@ fun <T, S> List<T>.splitToRanges(classifier: (T) -> S): List<Pair<List<T>, S>> {
|
||||
return result
|
||||
}
|
||||
|
||||
fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsExpression {
|
||||
val classifierDescriptor = type.constructor.declarationDescriptor
|
||||
fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsExpression =
|
||||
getReferenceToJsClass(type.constructor.declarationDescriptor, context)
|
||||
|
||||
fun getReferenceToJsClass(classifierDescriptor: ClassifierDescriptor?, context: TranslationContext): JsExpression {
|
||||
return when (classifierDescriptor) {
|
||||
is ClassDescriptor -> {
|
||||
ReferenceTranslator.translateAsTypeReference(classifierDescriptor, context)
|
||||
@@ -135,10 +136,10 @@ fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsExpr
|
||||
context.usageTracker()?.used(classifierDescriptor)
|
||||
|
||||
context.captureTypeIfNeedAndGetCapturedName(classifierDescriptor)
|
||||
?: context.getNameForDescriptor(classifierDescriptor).makeRef()
|
||||
?: context.getNameForDescriptor(classifierDescriptor).makeRef()
|
||||
}
|
||||
else -> {
|
||||
throw IllegalStateException("Can't get reference for $type")
|
||||
throw IllegalStateException("Can't get reference for $classifierDescriptor")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user