JS: improve representation of KClass for primitive types
See KT-17933, KT-17629, KT-17760
This commit is contained in:
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
@@ -586,11 +587,10 @@ public class DescriptorUtils {
|
||||
|
||||
@Nullable
|
||||
public static FunctionDescriptor getFunctionByNameOrNull(@NotNull MemberScope scope, @NotNull Name name) {
|
||||
Collection<DeclarationDescriptor> functions = scope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS,
|
||||
MemberScope.Companion.getALL_NAME_FILTER());
|
||||
for (DeclarationDescriptor d : functions) {
|
||||
if (d instanceof FunctionDescriptor && name.equals(d.getOriginal().getName())) {
|
||||
return (FunctionDescriptor) d;
|
||||
Collection<SimpleFunctionDescriptor> functions = scope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND);
|
||||
for (SimpleFunctionDescriptor d : functions) {
|
||||
if (name.equals(d.getOriginal().getName())) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,11 +599,10 @@ public class DescriptorUtils {
|
||||
|
||||
@NotNull
|
||||
public static PropertyDescriptor getPropertyByName(@NotNull MemberScope scope, @NotNull Name name) {
|
||||
Collection<DeclarationDescriptor> callables = scope.getContributedDescriptors(
|
||||
DescriptorKindFilter.CALLABLES, MemberScope.Companion.getALL_NAME_FILTER());
|
||||
for (DeclarationDescriptor d : callables) {
|
||||
if (d instanceof PropertyDescriptor && name.equals(d.getOriginal().getName())) {
|
||||
return (PropertyDescriptor) d;
|
||||
Collection<PropertyDescriptor> properties = scope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND);
|
||||
for (PropertyDescriptor d : properties) {
|
||||
if (name.equals(d.getOriginal().getName())) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,12 @@ public class JsConfig {
|
||||
return getConfiguration().getList(JSConfigurationKeys.FRIEND_PATHS);
|
||||
}
|
||||
|
||||
public boolean isAtLeast(@NotNull LanguageVersion expected) {
|
||||
LanguageVersion actual = CommonConfigurationKeysKt.getLanguageVersionSettings(configuration).getLanguageVersion();
|
||||
return actual.getMajor() > expected.getMajor() ||
|
||||
actual.getMajor() == expected.getMajor() && actual.getMinor() >= expected.getMinor();
|
||||
}
|
||||
|
||||
|
||||
public static abstract class Reporter {
|
||||
public void error(@NotNull String message) { /*Do nothing*/ }
|
||||
|
||||
@@ -18,17 +18,9 @@ package kotlin.reflect.js.internal
|
||||
|
||||
import kotlin.reflect.*
|
||||
|
||||
internal class KClassImpl<T : Any>(
|
||||
internal val jClass: JsClass<T>
|
||||
internal abstract class KClassImpl<T : Any>(
|
||||
internal open val jClass: JsClass<T>
|
||||
) : KClass<T> {
|
||||
|
||||
private val metadata = jClass.asDynamic().`$metadata$`
|
||||
// TODO: use FQN
|
||||
private val hashCode = simpleName?.hashCode() ?: 0
|
||||
|
||||
override val simpleName: String?
|
||||
get() = metadata?.simpleName
|
||||
|
||||
override val annotations: List<Annotation>
|
||||
get() = TODO()
|
||||
override val constructors: Collection<KFunction<T>>
|
||||
@@ -66,16 +58,49 @@ internal class KClassImpl<T : Any>(
|
||||
return other is KClassImpl<*> && jClass == other.jClass
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return hashCode
|
||||
}
|
||||
|
||||
override fun isInstance(value: Any?): Boolean {
|
||||
return js("Kotlin").isType(value, jClass)
|
||||
}
|
||||
// TODO: use FQN
|
||||
override fun hashCode(): Int = simpleName?.hashCode() ?: 0
|
||||
|
||||
override fun toString(): String {
|
||||
// TODO: use FQN
|
||||
return "class $simpleName"
|
||||
}
|
||||
}
|
||||
|
||||
internal class SimpleKClassImpl<T : Any>(jClass: JsClass<T>) : KClassImpl<T>(jClass) {
|
||||
override val simpleName: String? = jClass.asDynamic().`$metadata$`?.simpleName.unsafeCast<String?>()
|
||||
|
||||
override fun isInstance(value: Any?): Boolean {
|
||||
return js("Kotlin").isType(value, jClass)
|
||||
}
|
||||
}
|
||||
|
||||
internal class PrimitiveKClassImpl<T : Any>(
|
||||
jClass: JsClass<T>,
|
||||
private val givenSimpleName: String,
|
||||
private val isInstanceFunction: (Any?) -> Boolean
|
||||
) : KClassImpl<T>(jClass) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is PrimitiveKClassImpl<*>) return false
|
||||
return super.equals(other) && givenSimpleName == other.givenSimpleName
|
||||
}
|
||||
|
||||
override val simpleName: String? get() = givenSimpleName
|
||||
|
||||
override fun isInstance(value: Any?): Boolean {
|
||||
return isInstanceFunction(value)
|
||||
}
|
||||
}
|
||||
|
||||
internal object NothingKClassImpl : KClassImpl<Nothing>(js("Object")) {
|
||||
override val simpleName: String = "Nothing"
|
||||
|
||||
override fun isInstance(value: Any?): Boolean = false
|
||||
|
||||
override val jClass: JsClass<Nothing>
|
||||
get() = throw UnsupportedOperationException("There's no native JS class for Nothing type")
|
||||
|
||||
override fun equals(other: Any?): Boolean = other === this
|
||||
|
||||
override fun hashCode(): Int = 0
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlin.reflect.js.internal
|
||||
|
||||
import kotlin.js.JsClass
|
||||
|
||||
@JsName("PrimitiveClasses")
|
||||
internal object PrimitiveClasses {
|
||||
@JsName("anyClass")
|
||||
val anyClass = PrimitiveKClassImpl(js("Object").unsafeCast<JsClass<Any>>(), "Any", { it is Any })
|
||||
|
||||
@JsName("numberClass")
|
||||
val numberClass = PrimitiveKClassImpl(js("Number").unsafeCast<JsClass<Number>>(), "Number", { it is Number })
|
||||
|
||||
@JsName("nothingClass")
|
||||
val nothingClass = NothingKClassImpl
|
||||
|
||||
@JsName("booleanClass")
|
||||
val booleanClass = PrimitiveKClassImpl(js("Boolean").unsafeCast<JsClass<Boolean>>(), "Boolean", { it is Boolean })
|
||||
|
||||
@JsName("byteClass")
|
||||
val byteClass = PrimitiveKClassImpl(js("Number").unsafeCast<JsClass<Byte>>(), "Byte", { it is Byte })
|
||||
|
||||
@JsName("shortClass")
|
||||
val shortClass = PrimitiveKClassImpl(js("Number").unsafeCast<JsClass<Short>>(), "Short", { it is Short })
|
||||
|
||||
@JsName("intClass")
|
||||
val intClass = PrimitiveKClassImpl(js("Number").unsafeCast<JsClass<Int>>(), "Int", { it is Int })
|
||||
|
||||
@JsName("floatClass")
|
||||
val floatClass = PrimitiveKClassImpl(js("Number").unsafeCast<JsClass<Float>>(), "Float", { it is Float })
|
||||
|
||||
@JsName("doubleClass")
|
||||
val doubleClass = PrimitiveKClassImpl(js("Number").unsafeCast<JsClass<Double>>(), "Double", { it is Double })
|
||||
|
||||
@JsName("arrayClass")
|
||||
val arrayClass = PrimitiveKClassImpl(js("Array").unsafeCast<JsClass<Array<*>>>(), "Array", { it is Array<*> })
|
||||
|
||||
@JsName("stringClass")
|
||||
val stringClass = PrimitiveKClassImpl(js("String").unsafeCast<JsClass<String>>(), "String", { it is String })
|
||||
|
||||
@JsName("throwableClass")
|
||||
val throwableClass = PrimitiveKClassImpl(js("Error").unsafeCast<JsClass<Throwable>>(), "Throwable", { it is Throwable })
|
||||
|
||||
@JsName("booleanArrayClass")
|
||||
val booleanArrayClass = PrimitiveKClassImpl(js("Array").unsafeCast<JsClass<BooleanArray>>(), "BooleanArray", { it is BooleanArray })
|
||||
|
||||
@JsName("charArrayClass")
|
||||
val charArrayClass = PrimitiveKClassImpl(js("Uint16Array").unsafeCast<JsClass<CharArray>>(), "CharArray", { it is CharArray })
|
||||
|
||||
@JsName("byteArrayClass")
|
||||
val byteArrayClass = PrimitiveKClassImpl(js("Int8Array").unsafeCast<JsClass<ByteArray>>(), "ByteArray", { it is ByteArray })
|
||||
|
||||
@JsName("shortArrayClass")
|
||||
val shortArrayClass = PrimitiveKClassImpl(js("Int16Array").unsafeCast<JsClass<ShortArray>>(), "ShortArray", { it is ShortArray })
|
||||
|
||||
@JsName("intArrayClass")
|
||||
val intArrayClass = PrimitiveKClassImpl(js("Int32Array").unsafeCast<JsClass<IntArray>>(), "IntArray", { it is IntArray })
|
||||
|
||||
@JsName("longArrayClass")
|
||||
val longArrayClass = PrimitiveKClassImpl(js("Array").unsafeCast<JsClass<LongArray>>(), "LongArray", { it is LongArray })
|
||||
|
||||
@JsName("floatArrayClass")
|
||||
val floatArrayClass = PrimitiveKClassImpl(js("Float32Array").unsafeCast<JsClass<FloatArray>>(), "FloatArray", { it is FloatArray })
|
||||
|
||||
@JsName("doubleArrayClass")
|
||||
val doubleArrayClass = PrimitiveKClassImpl(js("Float64Array").unsafeCast<JsClass<DoubleArray>>(), "DoubleArray", { it is DoubleArray })
|
||||
|
||||
@JsName("functionClass")
|
||||
fun functionClass(arity: Int): KClassImpl<Any> {
|
||||
return functionClasses.get(arity) ?: run {
|
||||
val result = PrimitiveKClassImpl(js("Function").unsafeCast<JsClass<Any>>(), "Function$arity",
|
||||
{ jsTypeOf(it) === "function" && it.asDynamic().length == arity })
|
||||
functionClasses.asDynamic()[arity] = result
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val functionClasses = arrayOfNulls<KClassImpl<Any>>(0)
|
||||
@@ -17,19 +17,52 @@
|
||||
// a package is omitted to get declarations directly under the module
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.js.internal.KClassImpl
|
||||
import kotlin.reflect.js.internal.*
|
||||
|
||||
@JsName("getKClass")
|
||||
internal fun <T : Any> getKClass(jClass: JsClass<T>): KClass<T> = getOrCreateKClass(jClass)
|
||||
@JsName("getKClassFromExpression")
|
||||
internal fun <T : Any> getKClassFromExpression(e: T): KClass<T> = getOrCreateKClass(e.jsClass)
|
||||
internal fun <T : Any> getKClassFromExpression(e: T): KClass<T> =
|
||||
when (jsTypeOf(e)) {
|
||||
"string" -> PrimitiveClasses.stringClass
|
||||
"number" -> if (js("e | 0") === e) PrimitiveClasses.intClass else PrimitiveClasses.doubleClass
|
||||
"boolean" -> PrimitiveClasses.booleanClass
|
||||
"function" -> PrimitiveClasses.functionClass(e.asDynamic().length)
|
||||
else -> {
|
||||
when {
|
||||
e is BooleanArray -> PrimitiveClasses.booleanArrayClass
|
||||
e is CharArray -> PrimitiveClasses.charArrayClass
|
||||
e is ByteArray -> PrimitiveClasses.byteArrayClass
|
||||
e is ShortArray -> PrimitiveClasses.shortArrayClass
|
||||
e is IntArray -> PrimitiveClasses.intArrayClass
|
||||
e is LongArray -> PrimitiveClasses.longArrayClass
|
||||
e is FloatArray -> PrimitiveClasses.floatArrayClass
|
||||
e is DoubleArray -> PrimitiveClasses.doubleArrayClass
|
||||
e is KClass<*> -> KClass::class
|
||||
e is Array<*> -> PrimitiveClasses.arrayClass
|
||||
else -> {
|
||||
val constructor = js("Object").getPrototypeOf(e).constructor
|
||||
when {
|
||||
constructor === js("Object") -> PrimitiveClasses.anyClass
|
||||
constructor === js("Error") -> PrimitiveClasses.throwableClass
|
||||
else -> {
|
||||
val jsClass: JsClass<T> = constructor
|
||||
getOrCreateKClass(jsClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.unsafeCast<KClass<T>>()
|
||||
|
||||
private fun <T : Any> getOrCreateKClass(jClass: JsClass<T>): KClass<T> {
|
||||
if (jClass === js("String")) return PrimitiveClasses.stringClass.unsafeCast<KClass<T>>()
|
||||
|
||||
val metadata = jClass.asDynamic().`$metadata$`
|
||||
|
||||
return if (metadata != null) {
|
||||
if (metadata.`$kClass$` == null) {
|
||||
val kClass = KClassImpl(jClass)
|
||||
val kClass = SimpleKClassImpl(jClass)
|
||||
metadata.`$kClass$` = kClass
|
||||
kClass
|
||||
}
|
||||
@@ -38,7 +71,7 @@ private fun <T : Any> getOrCreateKClass(jClass: JsClass<T>): KClass<T> {
|
||||
}
|
||||
}
|
||||
else {
|
||||
KClassImpl(jClass)
|
||||
SimpleKClassImpl(jClass)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7441,6 +7441,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/reflection/primitives.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("primitives-12.kt")
|
||||
public void testPrimitives_12() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/reflection/primitives-12.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/regression")
|
||||
|
||||
+86
-2
@@ -16,10 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.expression;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
|
||||
import org.jetbrains.kotlin.config.LanguageVersion;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention;
|
||||
@@ -40,10 +44,14 @@ import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.UtilsKt;
|
||||
import org.jetbrains.kotlin.js.translate.utils.mutator.CoercionMutator;
|
||||
import org.jetbrains.kotlin.js.translate.utils.mutator.LastExpressionMutator;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||
@@ -54,14 +62,15 @@ import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.descriptors.FindClassInModuleKt.findClassAcrossModuleDependencies;
|
||||
import static org.jetbrains.kotlin.js.translate.context.Namer.*;
|
||||
import static org.jetbrains.kotlin.js.translate.general.Translation.translateAsExpression;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.*;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils.message;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.newVar;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForDeclaration;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateInitializerForProperty;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
@@ -72,6 +81,8 @@ import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFun
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
||||
|
||||
public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
private static final FqName primitiveClassesFqName = new FqName("kotlin.reflect.js.internal.PrimitiveClasses");
|
||||
|
||||
@Override
|
||||
protected JsNode emptyResult(@NotNull TranslationContext context) {
|
||||
return new JsNullLiteral();
|
||||
@@ -260,12 +271,85 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
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());
|
||||
if (primitiveExpression != null) {
|
||||
return JsAstUtils.newSequence(Arrays.asList(receiver, primitiveExpression));
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
private static JsExpression getPrimitiveClass(@NotNull TranslationContext context, @NotNull KotlinType type) {
|
||||
if (!context.getConfig().isAtLeast(LanguageVersion.KOTLIN_1_2) || findPrimitiveClassesObject(context) == null) return null;
|
||||
|
||||
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");
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JsExpression getKotlinPrimitiveClassRef(@NotNull TranslationContext context, @NotNull String name) {
|
||||
ClassDescriptor primitivesObject = findPrimitiveClassesObject(context);
|
||||
assert primitivesObject != null;
|
||||
PropertyDescriptor property = DescriptorUtils.getPropertyByName(
|
||||
primitivesObject.getUnsubstitutedMemberScope(), Name.identifier(name));
|
||||
return pureFqn(context.getInlineableInnerNameForDescriptor(property), null);
|
||||
}
|
||||
|
||||
private static boolean isPrimitiveClassLiteral(@NotNull KotlinType type) {
|
||||
return KotlinBuiltIns.isPrimitiveType(type) || KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ClassDescriptor findPrimitiveClassesObject(@NotNull TranslationContext context) {
|
||||
return findClassAcrossModuleDependencies(context.getCurrentModule(), ClassId.topLevel(primitiveClassesFqName));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// EXPECTED_REACHABLE_NODES: 994
|
||||
// EXPECTED_REACHABLE_NODES: 1094
|
||||
package foo
|
||||
|
||||
class A
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1070
|
||||
// EXPECTED_REACHABLE_NODES: 1181
|
||||
// MODULE: lib1
|
||||
// FILE: lib1.js
|
||||
define("lib1", [], function() {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1072
|
||||
// EXPECTED_REACHABLE_NODES: 1181
|
||||
// MODULE: lib-1
|
||||
// FILE: lib-1.js
|
||||
define("lib-1", [], function() {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1055
|
||||
// EXPECTED_REACHABLE_NODES: 1172
|
||||
// FILE: a.kt
|
||||
// WITH_RUNTIME
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// EXPECTED_REACHABLE_NODES: 997
|
||||
// EXPECTED_REACHABLE_NODES: 1099
|
||||
external class A
|
||||
|
||||
external object O
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1119
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
fun box(): String {
|
||||
check(js("Object"), "Any", Any::class)
|
||||
check(js("String"), "String", String::class)
|
||||
check(js("Boolean"), "Boolean", Boolean::class)
|
||||
check(js("Error"), "Throwable", Throwable::class)
|
||||
check(js("Array"), "Array", Array<Any>::class)
|
||||
check(js("Function"), "Function0", Function0::class)
|
||||
check(js("Function"), "Function1", Function1::class)
|
||||
|
||||
check(js("Number"), "Byte", Byte::class)
|
||||
check(js("Number"), "Short", Short::class)
|
||||
check(js("Number"), "Int", Int::class)
|
||||
check(js("Number"), "Float", Float::class)
|
||||
check(js("Number"), "Double", Double::class)
|
||||
check(js("Number"), "Number", Number::class)
|
||||
|
||||
check(js("Array"), "BooleanArray", BooleanArray::class)
|
||||
check(js("Uint16Array"), "CharArray", CharArray::class)
|
||||
check(js("Int8Array"), "ByteArray", ByteArray::class)
|
||||
check(js("Int16Array"), "ShortArray", ShortArray::class)
|
||||
check(js("Int32Array"), "IntArray", IntArray::class)
|
||||
check(js("Array"), "LongArray", LongArray::class)
|
||||
check(js("Float32Array"), "FloatArray", FloatArray::class)
|
||||
check(js("Float64Array"), "DoubleArray", DoubleArray::class)
|
||||
|
||||
check(js("Object"), "Any", Any())
|
||||
check(js("String"), "String", "*")
|
||||
check(js("Boolean"), "Boolean", true)
|
||||
check(js("Error"), "Throwable", Throwable())
|
||||
check(js("Array"), "Array", arrayOf(1, 2, 3))
|
||||
check(js("Function"), "Function0", { -> 23 })
|
||||
check(js("Function"), "Function1", { x: Int -> x })
|
||||
|
||||
check(js("Array"), "BooleanArray", booleanArrayOf())
|
||||
check(js("Uint16Array"), "CharArray", charArrayOf())
|
||||
check(js("Int8Array"), "ByteArray", byteArrayOf())
|
||||
check(js("Int16Array"), "ShortArray", shortArrayOf())
|
||||
check(js("Int32Array"), "IntArray", intArrayOf())
|
||||
check(js("Array"), "LongArray", longArrayOf())
|
||||
check(js("Float32Array"), "FloatArray", floatArrayOf())
|
||||
check(js("Float64Array"), "DoubleArray", doubleArrayOf())
|
||||
|
||||
check(js("Number"), "Int", 23.toByte())
|
||||
check(js("Number"), "Int", 23.toShort())
|
||||
check(js("Number"), "Int", 23)
|
||||
check(js("Number"), "Int", 23.0)
|
||||
check(js("Number"), "Double", 23.1F)
|
||||
check(js("Number"), "Double", 23.2)
|
||||
|
||||
check(js("Number"), "Int", Int::class)
|
||||
check(js("Number"), "Byte", Byte::class)
|
||||
check(js("Number"), "Double", Double::class)
|
||||
|
||||
assertEquals("Long", Long::class.simpleName)
|
||||
assertEquals("Long", 23L::class.simpleName)
|
||||
assertEquals("BoxedChar", Char::class.simpleName)
|
||||
assertEquals("BoxedChar", '@'::class.simpleName)
|
||||
assertEquals("RuntimeException", RuntimeException::class.simpleName)
|
||||
assertEquals("RuntimeException", RuntimeException()::class.simpleName)
|
||||
assertEquals("KClass", KClass::class.simpleName)
|
||||
assertEquals("KClass", Any::class::class.simpleName)
|
||||
assertEquals("KClass", Map::class::class.simpleName)
|
||||
|
||||
try {
|
||||
assertEquals("Nothing", Nothing::class.simpleName)
|
||||
Nothing::class.js
|
||||
fail("Exception expected when trying to get JS class for Nothing type")
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
// It's OK
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
private fun check(nativeClass: dynamic, simpleName: String, c: KClass<*>) {
|
||||
assertEquals(simpleName, c.simpleName, "Simple name of class has unexpected value")
|
||||
assertEquals(nativeClass, c.js, "Kotlin class does not correspond native class ${nativeClass.name}")
|
||||
}
|
||||
|
||||
private fun check(nativeClass: dynamic, simpleName: String, value: Any) {
|
||||
check(nativeClass, simpleName, value::class)
|
||||
assertTrue(value::class.isInstance(value), "isInstance should return true for $simpleName")
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,5 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1003
|
||||
// LANGUAGE_VERSION: 1.1
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
fun box(): String {
|
||||
@@ -35,13 +36,12 @@ fun box(): String {
|
||||
assertEquals("RuntimeException", RuntimeException::class.simpleName)
|
||||
assertEquals("RuntimeException", RuntimeException()::class.simpleName)
|
||||
assertEquals("KClass", KClass::class.simpleName)
|
||||
assertEquals("KClassImpl", Any::class::class.simpleName)
|
||||
assertEquals("KClass", Any::class::class.simpleName)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
private fun check(nativeClass: dynamic, c: KClass<*>) {
|
||||
assertEquals(null, c.simpleName, "Simple name of native class ${nativeClass.name} must be null")
|
||||
assertEquals(nativeClass, c.js, "Kotlin class does not correspond native class ${nativeClass.name}")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user