[JS] Support typeOf
This commit is contained in:
@@ -126,6 +126,9 @@ val reducedRuntimeSources by task<Sync> {
|
|||||||
"libraries/stdlib/js/src/kotlin/regexp.kt",
|
"libraries/stdlib/js/src/kotlin/regexp.kt",
|
||||||
"libraries/stdlib/js/src/kotlin/sequence.kt",
|
"libraries/stdlib/js/src/kotlin/sequence.kt",
|
||||||
"libraries/stdlib/js/src/kotlin/text/**",
|
"libraries/stdlib/js/src/kotlin/text/**",
|
||||||
|
"libraries/stdlib/js/src/kotlin/reflect/KTypeHelpers.kt",
|
||||||
|
"libraries/stdlib/js/src/kotlin/reflect/KTypeParameterImpl.kt",
|
||||||
|
"libraries/stdlib/js/src/kotlin/reflect/KTypeImpl.kt",
|
||||||
"libraries/stdlib/src/kotlin/collections/**",
|
"libraries/stdlib/src/kotlin/collections/**",
|
||||||
"libraries/stdlib/src/kotlin/experimental/bitwiseOperations.kt",
|
"libraries/stdlib/src/kotlin/experimental/bitwiseOperations.kt",
|
||||||
"libraries/stdlib/src/kotlin/properties/Delegates.kt",
|
"libraries/stdlib/src/kotlin/properties/Delegates.kt",
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||||
|
// TARGET_BACKEND: JS
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class C
|
||||||
|
|
||||||
|
fun check(expected: String, actual: KType) {
|
||||||
|
assertEquals(expected, actual.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
check("Any", typeOf<Any>())
|
||||||
|
check("String", typeOf<String>())
|
||||||
|
check("String?", typeOf<String?>())
|
||||||
|
check("Unit", typeOf<Unit>())
|
||||||
|
|
||||||
|
check("C", typeOf<C>())
|
||||||
|
check("C?", typeOf<C?>())
|
||||||
|
|
||||||
|
check("List<String>", typeOf<List<String>>())
|
||||||
|
check("Map<in Number, *>?", typeOf<Map<in Number, *>?>())
|
||||||
|
check("Enum<*>", typeOf<Enum<*>>())
|
||||||
|
check("Enum<AnnotationRetention>", typeOf<Enum<AnnotationRetention>>())
|
||||||
|
|
||||||
|
check("Array<Any>", typeOf<Array<Any>>())
|
||||||
|
check("Array<*>", typeOf<Array<*>>())
|
||||||
|
check("Array<IntArray>", typeOf<Array<IntArray>>())
|
||||||
|
check("Array<in Array<C>?>", typeOf<Array<in Array<C>?>>())
|
||||||
|
|
||||||
|
check("Int", typeOf<Int>())
|
||||||
|
check("Int?", typeOf<Int?>())
|
||||||
|
check("Boolean", typeOf<Boolean>())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||||
|
// TARGET_BACKEND: JS
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
inline class Z(val value: String)
|
||||||
|
|
||||||
|
fun check(expected: String, actual: KType) {
|
||||||
|
assertEquals(expected, actual.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
check("Z", typeOf<Z>())
|
||||||
|
check("Z?", typeOf<Z?>())
|
||||||
|
check("Array<Z>", typeOf<Array<Z>>())
|
||||||
|
check("Array<Z?>", typeOf<Array<Z?>>())
|
||||||
|
|
||||||
|
check("UInt", typeOf<UInt>())
|
||||||
|
check("UInt?", typeOf<UInt?>())
|
||||||
|
check("ULong?", typeOf<ULong?>())
|
||||||
|
check("UShortArray", typeOf<UShortArray>())
|
||||||
|
check("UShortArray?", typeOf<UShortArray?>())
|
||||||
|
check("Array<UByteArray>", typeOf<Array<UByteArray>>())
|
||||||
|
check("Array<UByteArray?>?", typeOf<Array<UByteArray?>?>())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||||
|
// TARGET_BACKEND: JS
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
import kotlin.test.*
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
inline fun <reified R> kType() = typeOf<R>()
|
||||||
|
|
||||||
|
inline fun <reified R> kType(obj: R) = kType<R>()
|
||||||
|
|
||||||
|
class C<T>
|
||||||
|
class D
|
||||||
|
|
||||||
|
fun <T> kTypeForCWithTypeParameter() = kType<C<T>>()
|
||||||
|
|
||||||
|
class Outer<T> {
|
||||||
|
companion object Friend
|
||||||
|
inner class Inner<S>
|
||||||
|
}
|
||||||
|
|
||||||
|
object Object
|
||||||
|
|
||||||
|
fun testBasics1() {
|
||||||
|
assertEquals("C<Int?>", kType<C<Int?>>().toString())
|
||||||
|
assertEquals("C<C<Any>>", kType<C<C<Any>>>().toString())
|
||||||
|
|
||||||
|
assertEquals("C<T>", kTypeForCWithTypeParameter<D>().toString())
|
||||||
|
assertEquals("Object", kType<Object>().toString())
|
||||||
|
assertEquals("Friend", kType<Outer.Friend>().toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testInner() {
|
||||||
|
val innerKType = kType<Outer<D>.Inner<String>>()
|
||||||
|
assertEquals(Outer.Inner::class, innerKType.classifier)
|
||||||
|
assertEquals(String::class, innerKType.arguments.first().type!!.classifier)
|
||||||
|
assertEquals(D::class, innerKType.arguments.last().type!!.classifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testAnonymousObject() {
|
||||||
|
val obj = object {}
|
||||||
|
val objType = kType(obj)
|
||||||
|
|
||||||
|
assertEquals("(non-denotable type)", objType.toString())
|
||||||
|
assertEquals(obj::class, objType.classifier)
|
||||||
|
|
||||||
|
assertTrue(objType.arguments.isEmpty())
|
||||||
|
assertFalse(objType.isMarkedNullable)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
testBasics1()
|
||||||
|
testInner()
|
||||||
|
testAnonymousObject()
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||||
|
// TARGET_BACKEND: JS
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
interface I1
|
||||||
|
interface I2
|
||||||
|
interface I3
|
||||||
|
interface I4
|
||||||
|
interface I5
|
||||||
|
interface I6
|
||||||
|
interface I7
|
||||||
|
|
||||||
|
class C<T1, T2, T3, T4, T5, T6, T7>
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(
|
||||||
|
"C<I1, I2, I3?, in I4, out I5, I6, I7?>",
|
||||||
|
typeOf<C<I1, I2, I3?, in I4, out I5, I6, I7?>>().toString()
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
"C<out I1, I2?, I3, I4, I5, I6?, in I7>?",
|
||||||
|
typeOf<C<out I1, I2?, I3, I4, I5, I6?, in I7>?>().toString()
|
||||||
|
)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||||
|
// TARGET_BACKEND: JS
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
interface C
|
||||||
|
|
||||||
|
inline fun <reified T> get() = typeOf<T>()
|
||||||
|
|
||||||
|
inline fun <reified U> get1() = get<U?>()
|
||||||
|
|
||||||
|
inline fun <reified V> get2(): KType {
|
||||||
|
return get1<Map<in V?, Array<V>>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals("C?", get1<C>().toString())
|
||||||
|
assertEquals("Map<in C?, Array<C>>?", get2<C>().toString())
|
||||||
|
assertEquals("Map<in List<C>?, Array<List<C>>>?", get2<List<C>>().toString())
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||||
|
// TARGET_BACKEND: JS
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
// MODULE: lib1
|
||||||
|
// FILE: lib1.kt
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
|
inline fun <reified T> get() = typeOf<T>()
|
||||||
|
|
||||||
|
// MODULE: lib2(lib1)
|
||||||
|
// FILE: lib2.kt
|
||||||
|
inline fun <reified U> get1() = get<U?>()
|
||||||
|
|
||||||
|
// MODULE: lib3(lib1, lib2)
|
||||||
|
// FILE: lib3.kt
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
inline fun <reified V> get2(): KType {
|
||||||
|
return get1<Map<in V?, Array<V>>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: main(lib1, lib2, lib3)
|
||||||
|
// FILE: lib4.kt
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
interface C
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals("C?", get1<C>().toString())
|
||||||
|
assertEquals("Map<in C?, Array<C>>?", get2<C>().toString())
|
||||||
|
assertEquals("Map<in List<C>?, Array<List<C>>>?", get2<List<C>>().toString())
|
||||||
|
|
||||||
|
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())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+13
@@ -22565,6 +22565,19 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/js")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Js extends AbstractBlackBoxCodegenTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInJs() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf/js"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+13
@@ -22565,6 +22565,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/js")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Js extends AbstractLightAnalysisModeTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInJs() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf/js"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+13
@@ -21455,6 +21455,19 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/js")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Js extends AbstractIrBlackBoxCodegenTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInJs() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf/js"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -129,6 +129,8 @@ var JsExpression.range: Pair<RangeType, RangeKind>? by MetadataProperty(default
|
|||||||
|
|
||||||
var JsExpression.primitiveKClass: JsExpression? by MetadataProperty(default = null)
|
var JsExpression.primitiveKClass: JsExpression? by MetadataProperty(default = null)
|
||||||
|
|
||||||
|
var JsExpression.kType: JsExpression? by MetadataProperty(default = null)
|
||||||
|
|
||||||
data class CoroutineMetadata(
|
data class CoroutineMetadata(
|
||||||
val doResumeName: JsName,
|
val doResumeName: JsName,
|
||||||
val stateName: JsName,
|
val stateName: JsName,
|
||||||
@@ -166,7 +168,8 @@ enum class SpecialFunction(val suggestedName: String) {
|
|||||||
COROUTINE_CONTROLLER("coroutineController"),
|
COROUTINE_CONTROLLER("coroutineController"),
|
||||||
COROUTINE_RECEIVER("coroutineReceiver"),
|
COROUTINE_RECEIVER("coroutineReceiver"),
|
||||||
SET_COROUTINE_RESULT("setCoroutineResult"),
|
SET_COROUTINE_RESULT("setCoroutineResult"),
|
||||||
GET_KCLASS("getKClass")
|
GET_KCLASS("getKClass"),
|
||||||
|
GET_REIFIED_TYPE_PARAMETER_KTYPE("getReifiedTypeParameterKType")
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class BoxingKind {
|
enum class BoxingKind {
|
||||||
|
|||||||
+15
-6
@@ -23,19 +23,27 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.NotFoundClasses
|
import org.jetbrains.kotlin.descriptors.NotFoundClasses
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED
|
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.AbstractReflectionApiCallChecker
|
import org.jetbrains.kotlin.resolve.calls.checkers.AbstractReflectionApiCallChecker
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.storage.getValue
|
import org.jetbrains.kotlin.storage.getValue
|
||||||
|
|
||||||
private val ALLOWED_KCLASS_MEMBERS = setOf("simpleName", "isInstance")
|
private val ALLOWED_KCLASS_MEMBERS = setOf("simpleName", "isInstance")
|
||||||
|
private val ALLOWED_CLASSES = setOf(
|
||||||
|
FqName("kotlin.reflect.KType"),
|
||||||
|
FqName("kotlin.reflect.KTypeProjection"),
|
||||||
|
FqName("kotlin.reflect.KTypeProjection.Companion"),
|
||||||
|
FqName("kotlin.reflect.KVariance")
|
||||||
|
)
|
||||||
|
|
||||||
class JsReflectionAPICallChecker(
|
class JsReflectionAPICallChecker(
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
private val reflectionTypes: ReflectionTypes,
|
private val reflectionTypes: ReflectionTypes,
|
||||||
notFoundClasses: NotFoundClasses,
|
notFoundClasses: NotFoundClasses,
|
||||||
storageManager: StorageManager
|
storageManager: StorageManager
|
||||||
) : AbstractReflectionApiCallChecker(module, notFoundClasses, storageManager) {
|
) : AbstractReflectionApiCallChecker(module, notFoundClasses, storageManager) {
|
||||||
override val isWholeReflectionApiAvailable: Boolean
|
override val isWholeReflectionApiAvailable: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
@@ -47,6 +55,7 @@ class JsReflectionAPICallChecker(
|
|||||||
private val kClass by storageManager.createLazyValue { reflectionTypes.kClass }
|
private val kClass by storageManager.createLazyValue { reflectionTypes.kClass }
|
||||||
|
|
||||||
override fun isAllowedReflectionApi(descriptor: CallableDescriptor, containingClass: ClassDescriptor): Boolean =
|
override fun isAllowedReflectionApi(descriptor: CallableDescriptor, containingClass: ClassDescriptor): Boolean =
|
||||||
super.isAllowedReflectionApi(descriptor, containingClass) ||
|
super.isAllowedReflectionApi(descriptor, containingClass) ||
|
||||||
DescriptorUtils.isSubclass(containingClass, kClass) && descriptor.name.asString() in ALLOWED_KCLASS_MEMBERS
|
DescriptorUtils.isSubclass(containingClass, kClass) && descriptor.name.asString() in ALLOWED_KCLASS_MEMBERS ||
|
||||||
|
containingClass.fqNameSafe in ALLOWED_CLASSES
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.inlineStrategy
|
|||||||
import org.jetbrains.kotlin.js.backend.ast.metadata.psiElement
|
import org.jetbrains.kotlin.js.backend.ast.metadata.psiElement
|
||||||
import org.jetbrains.kotlin.js.inline.clean.FunctionPostProcessor
|
import org.jetbrains.kotlin.js.inline.clean.FunctionPostProcessor
|
||||||
import org.jetbrains.kotlin.js.inline.clean.removeUnusedLocalFunctionDeclarations
|
import org.jetbrains.kotlin.js.inline.clean.removeUnusedLocalFunctionDeclarations
|
||||||
|
import org.jetbrains.kotlin.js.inline.clean.substituteKTypes
|
||||||
import org.jetbrains.kotlin.js.inline.util.extractFunction
|
import org.jetbrains.kotlin.js.inline.util.extractFunction
|
||||||
import org.jetbrains.kotlin.js.inline.util.refreshLabelNames
|
import org.jetbrains.kotlin.js.inline.util.refreshLabelNames
|
||||||
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
|
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
|
||||||
@@ -47,11 +48,11 @@ class InlineAstVisitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun endVisit(function: JsFunction, ctx: JsContext<*>) {
|
override fun endVisit(function: JsFunction, ctx: JsContext<*>) {
|
||||||
// Cleanup
|
|
||||||
patchReturnsFromSecondaryConstructor(function)
|
patchReturnsFromSecondaryConstructor(function)
|
||||||
refreshLabelNames(function.body, function.scope)
|
refreshLabelNames(function.body, function.scope)
|
||||||
removeUnusedLocalFunctionDeclarations(function)
|
removeUnusedLocalFunctionDeclarations(function)
|
||||||
FunctionPostProcessor(function).apply()
|
FunctionPostProcessor(function).apply()
|
||||||
|
substituteKTypes(function)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.inline.clean
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.metadata.kType
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.metadata.specialFunction
|
||||||
|
|
||||||
|
// Replaces getReifiedTypeParameterKType(<Class Constructor>) with its KType
|
||||||
|
fun substituteKTypes(root: JsNode) {
|
||||||
|
val visitor = object : JsVisitorWithContextImpl() {
|
||||||
|
override fun endVisit(invocation: JsInvocation, ctx: JsContext<in JsNode>) {
|
||||||
|
val qualifier = invocation.qualifier as? JsNameRef ?: return
|
||||||
|
if (qualifier.name?.specialFunction != SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE) return
|
||||||
|
val firstArg = invocation.arguments.first()
|
||||||
|
firstArg.kType?.let {
|
||||||
|
ctx.replaceMe(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visitor.accept(root)
|
||||||
|
}
|
||||||
@@ -465,6 +465,7 @@ enum SpecialFunction {
|
|||||||
COROUTINE_RECEIVER = 8;
|
COROUTINE_RECEIVER = 8;
|
||||||
SET_COROUTINE_RESULT = 9;
|
SET_COROUTINE_RESULT = 9;
|
||||||
GET_KCLASS = 10;
|
GET_KCLASS = 10;
|
||||||
|
GET_REIFIED_TYPE_PARAMETER_KTYPE = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -558,6 +558,7 @@ class JsAstDeserializer(program: JsProgram, private val sourceRoots: Iterable<Fi
|
|||||||
JsAstProtoBuf.SpecialFunction.COROUTINE_RECEIVER -> SpecialFunction.COROUTINE_RECEIVER
|
JsAstProtoBuf.SpecialFunction.COROUTINE_RECEIVER -> SpecialFunction.COROUTINE_RECEIVER
|
||||||
JsAstProtoBuf.SpecialFunction.SET_COROUTINE_RESULT -> SpecialFunction.SET_COROUTINE_RESULT
|
JsAstProtoBuf.SpecialFunction.SET_COROUTINE_RESULT -> SpecialFunction.SET_COROUTINE_RESULT
|
||||||
JsAstProtoBuf.SpecialFunction.GET_KCLASS -> SpecialFunction.GET_KCLASS
|
JsAstProtoBuf.SpecialFunction.GET_KCLASS -> SpecialFunction.GET_KCLASS
|
||||||
|
JsAstProtoBuf.SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE -> SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : JsNode> withLocation(fileId: Int?, location: Location?, action: () -> T): T {
|
private fun <T : JsNode> withLocation(fileId: Int?, location: Location?, action: () -> T): T {
|
||||||
|
|||||||
@@ -183,6 +183,10 @@ public final class JsAstProtoBuf {
|
|||||||
* <code>GET_KCLASS = 10;</code>
|
* <code>GET_KCLASS = 10;</code>
|
||||||
*/
|
*/
|
||||||
GET_KCLASS(9, 10),
|
GET_KCLASS(9, 10),
|
||||||
|
/**
|
||||||
|
* <code>GET_REIFIED_TYPE_PARAMETER_KTYPE = 11;</code>
|
||||||
|
*/
|
||||||
|
GET_REIFIED_TYPE_PARAMETER_KTYPE(10, 11),
|
||||||
;
|
;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -225,6 +229,10 @@ public final class JsAstProtoBuf {
|
|||||||
* <code>GET_KCLASS = 10;</code>
|
* <code>GET_KCLASS = 10;</code>
|
||||||
*/
|
*/
|
||||||
public static final int GET_KCLASS_VALUE = 10;
|
public static final int GET_KCLASS_VALUE = 10;
|
||||||
|
/**
|
||||||
|
* <code>GET_REIFIED_TYPE_PARAMETER_KTYPE = 11;</code>
|
||||||
|
*/
|
||||||
|
public static final int GET_REIFIED_TYPE_PARAMETER_KTYPE_VALUE = 11;
|
||||||
|
|
||||||
|
|
||||||
public final int getNumber() { return value; }
|
public final int getNumber() { return value; }
|
||||||
@@ -241,6 +249,7 @@ public final class JsAstProtoBuf {
|
|||||||
case 8: return COROUTINE_RECEIVER;
|
case 8: return COROUTINE_RECEIVER;
|
||||||
case 9: return SET_COROUTINE_RESULT;
|
case 9: return SET_COROUTINE_RESULT;
|
||||||
case 10: return GET_KCLASS;
|
case 10: return GET_KCLASS;
|
||||||
|
case 11: return GET_REIFIED_TYPE_PARAMETER_KTYPE;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -601,6 +601,7 @@ class JsAstSerializer(private val jsAstValidator: ((JsProgramFragment, Set<JsNam
|
|||||||
SpecialFunction.COROUTINE_RECEIVER -> JsAstProtoBuf.SpecialFunction.COROUTINE_RECEIVER
|
SpecialFunction.COROUTINE_RECEIVER -> JsAstProtoBuf.SpecialFunction.COROUTINE_RECEIVER
|
||||||
SpecialFunction.SET_COROUTINE_RESULT -> JsAstProtoBuf.SpecialFunction.SET_COROUTINE_RESULT
|
SpecialFunction.SET_COROUTINE_RESULT -> JsAstProtoBuf.SpecialFunction.SET_COROUTINE_RESULT
|
||||||
SpecialFunction.GET_KCLASS -> JsAstProtoBuf.SpecialFunction.GET_KCLASS
|
SpecialFunction.GET_KCLASS -> JsAstProtoBuf.SpecialFunction.GET_KCLASS
|
||||||
|
SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE -> JsAstProtoBuf.SpecialFunction.GET_REIFIED_TYPE_PARAMETER_KTYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun serialize(name: JsName): Int = nameMap.getOrPut(name) {
|
private fun serialize(name: JsName): Int = nameMap.getOrPut(name) {
|
||||||
|
|||||||
Generated
+43
@@ -17310,6 +17310,49 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/js")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Js extends AbstractIrJsCodegenBoxTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInJs() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf/js"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classes.kt")
|
||||||
|
public void testClasses() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/classes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineClasses.kt")
|
||||||
|
public void testInlineClasses() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/inlineClasses.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kType.kt")
|
||||||
|
public void testKType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/kType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("manyTypeArguments.kt")
|
||||||
|
public void testManyTypeArguments() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/manyTypeArguments.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleLayers.kt")
|
||||||
|
public void testMultipleLayers() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/multipleLayers.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleModules.kt")
|
||||||
|
public void testMultipleModules() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/multipleModules.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+43
@@ -18465,6 +18465,49 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/js")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Js extends AbstractJsCodegenBoxTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInJs() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf/js"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classes.kt")
|
||||||
|
public void testClasses() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/classes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineClasses.kt")
|
||||||
|
public void testInlineClasses() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/inlineClasses.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kType.kt")
|
||||||
|
public void testKType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/kType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("manyTypeArguments.kt")
|
||||||
|
public void testManyTypeArguments() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/manyTypeArguments.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleLayers.kt")
|
||||||
|
public void testMultipleLayers() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/multipleLayers.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleModules.kt")
|
||||||
|
public void testMultipleModules() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeOf/js/multipleModules.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
@TestMetadata("compiler/testData/codegen/box/reflection/typeOf/noReflect")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -75,6 +75,15 @@ public final class Namer {
|
|||||||
public static final String GET_KCLASS = "getKClass";
|
public static final String GET_KCLASS = "getKClass";
|
||||||
public static final String GET_KCLASS_FROM_EXPRESSION = "getKClassFromExpression";
|
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 CALLEE_NAME = "$fun";
|
||||||
|
|
||||||
public static final String CALL_FUNCTION = "call";
|
public static final String CALL_FUNCTION = "call";
|
||||||
|
|||||||
+2
-1
@@ -39,7 +39,8 @@ class FunctionIntrinsics {
|
|||||||
AsDynamicFIF,
|
AsDynamicFIF,
|
||||||
CoroutineContextFIF,
|
CoroutineContextFIF,
|
||||||
SuspendCoroutineUninterceptedOrReturnFIF,
|
SuspendCoroutineUninterceptedOrReturnFIF,
|
||||||
InterceptedFIF
|
InterceptedFIF,
|
||||||
|
TypeOfFIF
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
|
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.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.expression.ExpressionVisitor
|
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.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.reference.ReferenceTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
|
||||||
import org.jetbrains.kotlin.psi.*
|
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.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
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 =
|
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 {
|
fun getReferenceToJsClass(classifierDescriptor: ClassifierDescriptor?, context: TranslationContext): JsExpression {
|
||||||
return when (classifierDescriptor) {
|
return when (classifierDescriptor) {
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// a package is omitted to get declarations directly under the module
|
||||||
|
|
||||||
|
// TODO: Remove once JsReflectionAPICallChecker supports more reflection types
|
||||||
|
@file:Suppress("Unsupported")
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
import kotlin.reflect.js.internal.*
|
||||||
|
|
||||||
|
@JsName("createKType")
|
||||||
|
internal fun createKType(
|
||||||
|
classifier: KClassifier,
|
||||||
|
arguments: Array<KTypeProjection>,
|
||||||
|
isMarkedNullable: Boolean
|
||||||
|
) =
|
||||||
|
KTypeImpl(classifier, arguments.asList(), isMarkedNullable)
|
||||||
|
|
||||||
|
@JsName("markKTypeNullable")
|
||||||
|
internal fun markKTypeNullable(kType: KType) = KTypeImpl(kType.classifier!!, kType.arguments, true)
|
||||||
|
|
||||||
|
@JsName("createKTypeParameter")
|
||||||
|
internal fun createKTypeParameter(
|
||||||
|
name: String,
|
||||||
|
upperBounds: Array<KType>,
|
||||||
|
variance: String
|
||||||
|
): KTypeParameter {
|
||||||
|
val kVariance = when (variance) {
|
||||||
|
"in" -> KVariance.IN
|
||||||
|
"out" -> KVariance.OUT
|
||||||
|
else -> KVariance.INVARIANT
|
||||||
|
}
|
||||||
|
|
||||||
|
return KTypeParameterImpl(name, upperBounds.asList(), kVariance, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsName("getStarKTypeProjection")
|
||||||
|
internal fun getStarKTypeProjection(): KTypeProjection =
|
||||||
|
KTypeProjection.STAR
|
||||||
|
|
||||||
|
@JsName("createCovariantKTypeProjection")
|
||||||
|
internal fun createCovariantKTypeProjection(type: KType): KTypeProjection =
|
||||||
|
KTypeProjection.covariant(type)
|
||||||
|
|
||||||
|
@JsName("createInvariantKTypeProjection")
|
||||||
|
internal fun createInvariantKTypeProjection(type: KType): KTypeProjection =
|
||||||
|
KTypeProjection.invariant(type)
|
||||||
|
|
||||||
|
@JsName("createContravariantKTypeProjection")
|
||||||
|
internal fun createContravariantKTypeProjection(type: KType): KTypeProjection =
|
||||||
|
KTypeProjection.contravariant(type)
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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 kotlin.reflect.js.internal
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
internal class KTypeImpl(
|
||||||
|
override val classifier: KClassifier,
|
||||||
|
override val arguments: List<KTypeProjection>,
|
||||||
|
override val isMarkedNullable: Boolean
|
||||||
|
) : KType {
|
||||||
|
override val annotations: List<Annotation>
|
||||||
|
get() = emptyList()
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
other is KTypeImpl &&
|
||||||
|
classifier == other.classifier && arguments == other.arguments && isMarkedNullable == other.isMarkedNullable
|
||||||
|
|
||||||
|
override fun hashCode(): Int =
|
||||||
|
(classifier.hashCode() * 31 + arguments.hashCode()) * 31 + isMarkedNullable.hashCode()
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val kClass = (classifier as? KClass<*>)
|
||||||
|
val classifierName = when {
|
||||||
|
kClass == null -> classifier.toString()
|
||||||
|
kClass.simpleName != null -> kClass.simpleName
|
||||||
|
else -> "(non-denotable type)"
|
||||||
|
}
|
||||||
|
|
||||||
|
val args =
|
||||||
|
if (arguments.isEmpty()) ""
|
||||||
|
else arguments.joinToString(", ", "<", ">") { it.asString() }
|
||||||
|
val nullable = if (isMarkedNullable) "?" else ""
|
||||||
|
|
||||||
|
return classifierName + args + nullable
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this should be the implementation of KTypeProjection.toString, see KT-30071
|
||||||
|
private fun KTypeProjection.asString(): String {
|
||||||
|
if (variance == null) return "*"
|
||||||
|
return variance.prefixString() + type.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KVariance.prefixString() =
|
||||||
|
when (this) {
|
||||||
|
KVariance.INVARIANT -> ""
|
||||||
|
KVariance.IN -> "in "
|
||||||
|
KVariance.OUT -> "out "
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* 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 kotlin.reflect.js.internal
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
internal data class KTypeParameterImpl(
|
||||||
|
override val name: String,
|
||||||
|
override val upperBounds: List<KType>,
|
||||||
|
override val variance: KVariance,
|
||||||
|
override val isReified: Boolean
|
||||||
|
) : KTypeParameter {
|
||||||
|
override fun toString(): String = name
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
// a package is omitted to get declarations directly under the module
|
// a package is omitted to get declarations directly under the module
|
||||||
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.*
|
||||||
import kotlin.reflect.js.internal.*
|
import kotlin.reflect.js.internal.*
|
||||||
|
|
||||||
@JsName("getKClass")
|
@JsName("getKClass")
|
||||||
@@ -62,4 +62,3 @@ private fun <T : Any> getOrCreateKClass(jClass: JsClass<T>): KClass<T> {
|
|||||||
SimpleKClassImpl(jClass)
|
SimpleKClassImpl(jClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user