JS: improve representation of KClass for primitive types

See KT-17933, KT-17629, KT-17760
This commit is contained in:
Alexey Andreev
2017-09-20 10:18:09 +03:00
parent bbb571260b
commit 93a3026c6d
14 changed files with 375 additions and 40 deletions
@@ -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*/ }
+42 -17
View File
@@ -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
}
+94
View File
@@ -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)
+37 -4
View File
@@ -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")
@@ -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
View File
@@ -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,4 +1,4 @@
// EXPECTED_REACHABLE_NODES: 1072
// EXPECTED_REACHABLE_NODES: 1181
// MODULE: lib-1
// FILE: lib-1.js
define("lib-1", [], function() {
+1 -1
View File
@@ -1,4 +1,4 @@
// EXPECTED_REACHABLE_NODES: 1055
// EXPECTED_REACHABLE_NODES: 1172
// FILE: a.kt
// WITH_RUNTIME
import kotlin.coroutines.experimental.*
+1 -1
View File
@@ -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
View File
@@ -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}")
}