Do not rely on descriptors in KTypeParameterImpl.equals/hashCode
Descriptors are cached via weak references in moduleByClassLoader.kt and can be garbage-collected at any point. So relying on identity of descriptors in KTypeParameterImpl is dangerous because the same type parameter can be represented by different descriptors. For example, the test equalsOnFunctionParameters.kt was flaky before this change because of this issue, and that could be reproduced by running it a few hundred times in the same process. Instead, use the type parameter's container (which is either KClass or KCallable) and name, in equals/hashCode. KClass and KCallable already have equals/hashCode independent of descriptors, so this works in case the descriptor is invalidated.
This commit is contained in:
Generated
+15
@@ -26192,6 +26192,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsHashCode.kt");
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsHashCode.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParametersEqualsWithClearCaches.kt")
|
||||||
|
public void testTypeParametersEqualsWithClearCaches() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsWithClearCaches.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeParametersToString.kt")
|
@TestMetadata("typeParametersToString.kt")
|
||||||
public void testTypeParametersToString() throws Exception {
|
public void testTypeParametersToString() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersToString.kt");
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersToString.kt");
|
||||||
@@ -27078,6 +27083,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeParameters/declarationSiteVariance.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/declarationSiteVariance.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerGenericParameter.kt")
|
||||||
|
public void testInnerGenericParameter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/innerGenericParameter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaGenericTypeConstructor.kt")
|
||||||
|
public void testJavaGenericTypeConstructor() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/javaGenericTypeConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeParametersAndNames.kt")
|
@TestMetadata("typeParametersAndNames.kt")
|
||||||
public void testTypeParametersAndNames() throws Exception {
|
public void testTypeParametersAndNames() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt");
|
||||||
|
|||||||
Vendored
+56
@@ -0,0 +1,56 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_REFLECT
|
||||||
|
// FILE: box.kt
|
||||||
|
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
inline fun check(message: String, generate: () -> Any?) {
|
||||||
|
val x1: Any?
|
||||||
|
val x2: Any?
|
||||||
|
try {
|
||||||
|
x1 = generate()
|
||||||
|
|
||||||
|
// Force clear the internal maps, as if the weak values in them are garbage-collected.
|
||||||
|
kotlin.reflect.jvm.internal.ReflectionFactoryImpl.clearCaches()
|
||||||
|
|
||||||
|
x2 = generate()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
throw AssertionError("Fail $message", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(x1, x2, "Fail equals $message")
|
||||||
|
assertEquals(x2, x1, "Fail equals $message")
|
||||||
|
assertEquals(x1.hashCode(), x2.hashCode(), "Fail hashCode $message")
|
||||||
|
}
|
||||||
|
|
||||||
|
class C<T> {
|
||||||
|
fun <V> v(): V? = null
|
||||||
|
fun t(): T? = null
|
||||||
|
val <U> U.u: U get() = this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <W> W.w() {}
|
||||||
|
val <X> X.x: X get() = this
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
check("T from C's typeParameters") { C::class.typeParameters.single() }
|
||||||
|
check("V from v's typeParameters") { C::class.members.single { it.name == "v" }.typeParameters.single() }
|
||||||
|
|
||||||
|
check("V from v's returnType") { C::class.members.single { it.name == "v" }.returnType.classifier }
|
||||||
|
check("T from t's returnType") { C::class.members.single { it.name == "t" }.returnType.classifier }
|
||||||
|
check("U from u's parameter type") { C::class.members.single { it.name == "u" }.parameters[1].type.classifier }
|
||||||
|
|
||||||
|
check("W from w's parameter type") { Any::w.parameters.single().type.classifier }
|
||||||
|
check("X from x's parameter type") { Any::x.parameters.single().type.classifier }
|
||||||
|
|
||||||
|
check("Z from J's typeParameters") { J::class.typeParameters.single() }
|
||||||
|
check("Z from z's returnType") { J::class.members.single { it.name == "z" }.returnType.classifier }
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: J.java
|
||||||
|
|
||||||
|
public interface J<Z> {
|
||||||
|
Z z();
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
import kotlin.reflect.KVariance
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class A<out T> {
|
||||||
|
inner class B<in U> {
|
||||||
|
fun test(u: U): T? = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val fn = A.B::class.members.single { it.name == "test" }
|
||||||
|
|
||||||
|
val t = A::class.typeParameters.single()
|
||||||
|
val u = A.B::class.typeParameters.single()
|
||||||
|
|
||||||
|
assertEquals("T", t.name)
|
||||||
|
assertEquals(KVariance.OUT, t.variance)
|
||||||
|
assertEquals("U", u.name)
|
||||||
|
assertEquals(KVariance.IN, u.variance)
|
||||||
|
|
||||||
|
assertEquals(t, fn.returnType.classifier)
|
||||||
|
assertEquals(u, fn.parameters[1].type.classifier)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_REFLECT
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
import kotlin.reflect.KVariance
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val ctor = J::class.constructors.single()
|
||||||
|
val ab = ctor.typeParameters
|
||||||
|
assertEquals(2, ab.size, ab.toString())
|
||||||
|
|
||||||
|
assertEquals("A", ab[0].name)
|
||||||
|
assertEquals(KVariance.INVARIANT, ab[0].variance)
|
||||||
|
assertEquals("B", ab[1].name)
|
||||||
|
assertEquals(KVariance.INVARIANT, ab[1].variance)
|
||||||
|
|
||||||
|
// TODO: currently fails with "AssertionError: Expected <A>, actual <A>"
|
||||||
|
// assertEquals(ab[0], ctor.parameters[0].type.classifier)
|
||||||
|
|
||||||
|
assertEquals(ab[1], ctor.parameters[1].type.classifier)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: J.java
|
||||||
|
|
||||||
|
public class J<A> {
|
||||||
|
public <B> J(A a, B b) {}
|
||||||
|
}
|
||||||
+15
@@ -27778,6 +27778,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsHashCode.kt");
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsHashCode.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParametersEqualsWithClearCaches.kt")
|
||||||
|
public void testTypeParametersEqualsWithClearCaches() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsWithClearCaches.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeParametersToString.kt")
|
@TestMetadata("typeParametersToString.kt")
|
||||||
public void testTypeParametersToString() throws Exception {
|
public void testTypeParametersToString() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersToString.kt");
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersToString.kt");
|
||||||
@@ -28664,6 +28669,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeParameters/declarationSiteVariance.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/declarationSiteVariance.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerGenericParameter.kt")
|
||||||
|
public void testInnerGenericParameter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/innerGenericParameter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaGenericTypeConstructor.kt")
|
||||||
|
public void testJavaGenericTypeConstructor() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/javaGenericTypeConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeParametersAndNames.kt")
|
@TestMetadata("typeParametersAndNames.kt")
|
||||||
public void testTypeParametersAndNames() throws Exception {
|
public void testTypeParametersAndNames() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt");
|
||||||
|
|||||||
+15
@@ -25412,6 +25412,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsHashCode.kt");
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsHashCode.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParametersEqualsWithClearCaches.kt")
|
||||||
|
public void testTypeParametersEqualsWithClearCaches() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsWithClearCaches.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeParametersToString.kt")
|
@TestMetadata("typeParametersToString.kt")
|
||||||
public void testTypeParametersToString() throws Exception {
|
public void testTypeParametersToString() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersToString.kt");
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersToString.kt");
|
||||||
@@ -26298,6 +26303,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeParameters/declarationSiteVariance.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/declarationSiteVariance.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerGenericParameter.kt")
|
||||||
|
public void testInnerGenericParameter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/innerGenericParameter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaGenericTypeConstructor.kt")
|
||||||
|
public void testJavaGenericTypeConstructor() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/javaGenericTypeConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeParametersAndNames.kt")
|
@TestMetadata("typeParametersAndNames.kt")
|
||||||
public void testTypeParametersAndNames() throws Exception {
|
public void testTypeParametersAndNames() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt");
|
||||||
|
|||||||
+15
@@ -26192,6 +26192,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsHashCode.kt");
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsHashCode.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParametersEqualsWithClearCaches.kt")
|
||||||
|
public void testTypeParametersEqualsWithClearCaches() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersEqualsWithClearCaches.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeParametersToString.kt")
|
@TestMetadata("typeParametersToString.kt")
|
||||||
public void testTypeParametersToString() throws Exception {
|
public void testTypeParametersToString() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersToString.kt");
|
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/typeParametersToString.kt");
|
||||||
@@ -27078,6 +27083,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/reflection/typeParameters/declarationSiteVariance.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/declarationSiteVariance.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerGenericParameter.kt")
|
||||||
|
public void testInnerGenericParameter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/innerGenericParameter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaGenericTypeConstructor.kt")
|
||||||
|
public void testJavaGenericTypeConstructor() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/javaGenericTypeConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typeParametersAndNames.kt")
|
@TestMetadata("typeParametersAndNames.kt")
|
||||||
public void testTypeParametersAndNames() throws Exception {
|
public void testTypeParametersAndNames() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt");
|
runTest("compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt");
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import kotlin.reflect.jvm.internal.calls.Caller
|
|||||||
import kotlin.reflect.jvm.javaType
|
import kotlin.reflect.jvm.javaType
|
||||||
import kotlin.reflect.jvm.jvmErasure
|
import kotlin.reflect.jvm.jvmErasure
|
||||||
|
|
||||||
internal abstract class KCallableImpl<out R> : KCallable<R> {
|
internal abstract class KCallableImpl<out R> : KCallable<R>, KTypeParameterOwnerImpl {
|
||||||
abstract val descriptor: CallableMemberDescriptor
|
abstract val descriptor: CallableMemberDescriptor
|
||||||
|
|
||||||
// The instance which is used to perform a positional call, i.e. `call`
|
// The instance which is used to perform a positional call, i.e. `call`
|
||||||
@@ -82,7 +82,7 @@ internal abstract class KCallableImpl<out R> : KCallable<R> {
|
|||||||
get() = _returnType()
|
get() = _returnType()
|
||||||
|
|
||||||
private val _typeParameters = ReflectProperties.lazySoft {
|
private val _typeParameters = ReflectProperties.lazySoft {
|
||||||
descriptor.typeParameters.map(::KTypeParameterImpl)
|
descriptor.typeParameters.map { descriptor -> KTypeParameterImpl(this, descriptor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val typeParameters: List<KTypeParameter>
|
override val typeParameters: List<KTypeParameter>
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ import org.jetbrains.kotlin.descriptors.runtime.components.ReflectKotlinClass
|
|||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.functionClassArity
|
import org.jetbrains.kotlin.descriptors.runtime.structure.functionClassArity
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.wrapperByPrimitive
|
import org.jetbrains.kotlin.descriptors.runtime.structure.wrapperByPrimitive
|
||||||
|
|
||||||
internal class KClassImpl<T : Any>(override val jClass: Class<T>) : KDeclarationContainerImpl(), KClass<T>, KClassifierImpl {
|
internal class KClassImpl<T : Any>(
|
||||||
|
override val jClass: Class<T>
|
||||||
|
) : KDeclarationContainerImpl(), KClass<T>, KClassifierImpl, KTypeParameterOwnerImpl {
|
||||||
inner class Data : KDeclarationContainerImpl.Data() {
|
inner class Data : KDeclarationContainerImpl.Data() {
|
||||||
val descriptor: ClassDescriptor by ReflectProperties.lazySoft {
|
val descriptor: ClassDescriptor by ReflectProperties.lazySoft {
|
||||||
val classId = classId
|
val classId = classId
|
||||||
@@ -115,7 +117,7 @@ internal class KClassImpl<T : Any>(override val jClass: Class<T>) : KDeclaration
|
|||||||
}
|
}
|
||||||
|
|
||||||
val typeParameters: List<KTypeParameter> by ReflectProperties.lazySoft {
|
val typeParameters: List<KTypeParameter> by ReflectProperties.lazySoft {
|
||||||
descriptor.declaredTypeParameters.map(::KTypeParameterImpl)
|
descriptor.declaredTypeParameters.map { descriptor -> KTypeParameterImpl(this@KClassImpl, descriptor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val supertypes: List<KType> by ReflectProperties.lazySoft {
|
val supertypes: List<KType> by ReflectProperties.lazySoft {
|
||||||
|
|||||||
@@ -17,7 +17,11 @@
|
|||||||
package kotlin.reflect.jvm.internal
|
package kotlin.reflect.jvm.internal
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
|
import org.jetbrains.kotlin.descriptors.runtime.components.RuntimeModuleData
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.components.tryLoadClass
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.structure.createArrayType
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.structure.safeClassLoader
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.structure.wrapperByPrimitive
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
@@ -25,11 +29,6 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|||||||
import java.lang.reflect.Constructor
|
import java.lang.reflect.Constructor
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import kotlin.jvm.internal.ClassBasedDeclarationContainer
|
import kotlin.jvm.internal.ClassBasedDeclarationContainer
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.components.RuntimeModuleData
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.components.tryLoadClass
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.createArrayType
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.safeClassLoader
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.wrapperByPrimitive
|
|
||||||
|
|
||||||
internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer {
|
internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer {
|
||||||
abstract inner class Data {
|
abstract inner class Data {
|
||||||
@@ -51,17 +50,10 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
|
|||||||
abstract fun getLocalProperty(index: Int): PropertyDescriptor?
|
abstract fun getLocalProperty(index: Int): PropertyDescriptor?
|
||||||
|
|
||||||
protected fun getMembers(scope: MemberScope, belonginess: MemberBelonginess): Collection<KCallableImpl<*>> {
|
protected fun getMembers(scope: MemberScope, belonginess: MemberBelonginess): Collection<KCallableImpl<*>> {
|
||||||
val visitor = object : DeclarationDescriptorVisitorEmptyBodies<KCallableImpl<*>, Unit>() {
|
val visitor = object : CreateKCallableVisitor(this) {
|
||||||
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Unit): KCallableImpl<*> =
|
|
||||||
createProperty(descriptor)
|
|
||||||
|
|
||||||
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit): KCallableImpl<*> =
|
|
||||||
KFunctionImpl(this@KDeclarationContainerImpl, descriptor)
|
|
||||||
|
|
||||||
override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Unit): KCallableImpl<*> =
|
override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Unit): KCallableImpl<*> =
|
||||||
throw IllegalStateException("No constructors should appear in this scope: $descriptor")
|
throw IllegalStateException("No constructors should appear here: $descriptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
return scope.getContributedDescriptors().mapNotNull { descriptor ->
|
return scope.getContributedDescriptors().mapNotNull { descriptor ->
|
||||||
if (descriptor is CallableMemberDescriptor &&
|
if (descriptor is CallableMemberDescriptor &&
|
||||||
descriptor.visibility != Visibilities.INVISIBLE_FAKE &&
|
descriptor.visibility != Visibilities.INVISIBLE_FAKE &&
|
||||||
@@ -78,26 +70,6 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
|
|||||||
member.kind.isReal == (this == DECLARED)
|
member.kind.isReal == (this == DECLARED)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createProperty(descriptor: PropertyDescriptor): KPropertyImpl<*> {
|
|
||||||
val receiverCount = (descriptor.dispatchReceiverParameter?.let { 1 } ?: 0) +
|
|
||||||
(descriptor.extensionReceiverParameter?.let { 1 } ?: 0)
|
|
||||||
|
|
||||||
when {
|
|
||||||
descriptor.isVar -> when (receiverCount) {
|
|
||||||
0 -> return KMutableProperty0Impl<Any?>(this, descriptor)
|
|
||||||
1 -> return KMutableProperty1Impl<Any?, Any?>(this, descriptor)
|
|
||||||
2 -> return KMutableProperty2Impl<Any?, Any?, Any?>(this, descriptor)
|
|
||||||
}
|
|
||||||
else -> when (receiverCount) {
|
|
||||||
0 -> return KProperty0Impl<Any?>(this, descriptor)
|
|
||||||
1 -> return KProperty1Impl<Any?, Any?>(this, descriptor)
|
|
||||||
2 -> return KProperty2Impl<Any?, Any?, Any?>(this, descriptor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw KotlinReflectionInternalError("Unsupported property: $descriptor")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun findPropertyDescriptor(name: String, signature: String): PropertyDescriptor {
|
fun findPropertyDescriptor(name: String, signature: String): PropertyDescriptor {
|
||||||
val match = LOCAL_PROPERTY_SIGNATURE.matchEntire(signature)
|
val match = LOCAL_PROPERTY_SIGNATURE.matchEntire(signature)
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ internal class KTypeImpl(
|
|||||||
|
|
||||||
return KClassImpl(jClass)
|
return KClassImpl(jClass)
|
||||||
}
|
}
|
||||||
is TypeParameterDescriptor -> return KTypeParameterImpl(descriptor)
|
is TypeParameterDescriptor -> return KTypeParameterImpl(null, descriptor)
|
||||||
is TypeAliasDescriptor -> TODO("Type alias classifiers are not yet supported")
|
is TypeAliasDescriptor -> TODO("Type alias classifiers are not yet supported")
|
||||||
else -> return null
|
else -> return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,23 @@
|
|||||||
|
|
||||||
package kotlin.reflect.jvm.internal
|
package kotlin.reflect.jvm.internal
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.components.ReflectKotlinClass
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import kotlin.jvm.internal.TypeParameterReference
|
import kotlin.jvm.internal.TypeParameterReference
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
import kotlin.reflect.KTypeParameter
|
import kotlin.reflect.KTypeParameter
|
||||||
import kotlin.reflect.KVariance
|
import kotlin.reflect.KVariance
|
||||||
|
|
||||||
internal class KTypeParameterImpl(override val descriptor: TypeParameterDescriptor) : KTypeParameter, KClassifierImpl {
|
internal class KTypeParameterImpl(
|
||||||
|
container: KTypeParameterOwnerImpl?,
|
||||||
|
override val descriptor: TypeParameterDescriptor,
|
||||||
|
) : KTypeParameter, KClassifierImpl {
|
||||||
override val name: String
|
override val name: String
|
||||||
get() = descriptor.name.asString()
|
get() = descriptor.name.asString()
|
||||||
|
|
||||||
@@ -45,11 +54,41 @@ internal class KTypeParameterImpl(override val descriptor: TypeParameterDescript
|
|||||||
override val isReified: Boolean
|
override val isReified: Boolean
|
||||||
get() = descriptor.isReified
|
get() = descriptor.isReified
|
||||||
|
|
||||||
|
private val container: KTypeParameterOwnerImpl = container ?: run {
|
||||||
|
when (val declaration = descriptor.containingDeclaration) {
|
||||||
|
is ClassDescriptor -> {
|
||||||
|
declaration.toKClassImpl()
|
||||||
|
}
|
||||||
|
is CallableMemberDescriptor -> {
|
||||||
|
val callableContainerClass = when (val callableContainer = declaration.containingDeclaration) {
|
||||||
|
is ClassDescriptor -> {
|
||||||
|
callableContainer.toKClassImpl()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val deserializedMember = declaration as? DeserializedMemberDescriptor
|
||||||
|
?: throw KotlinReflectionInternalError("Non-class callable descriptor must be deserialized: $declaration")
|
||||||
|
deserializedMember.getContainerClass().kotlin as KClassImpl<*>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declaration.accept(CreateKCallableVisitor(callableContainerClass), Unit)
|
||||||
|
}
|
||||||
|
else -> throw KotlinReflectionInternalError("Unknown type parameter container: $declaration")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ClassDescriptor.toKClassImpl(): KClassImpl<*> =
|
||||||
|
toJavaClass()?.kotlin as KClassImpl<*>?
|
||||||
|
?: throw KotlinReflectionInternalError("Type parameter container is not resolved: $containingDeclaration")
|
||||||
|
|
||||||
|
private fun DeserializedMemberDescriptor.getContainerClass(): Class<*> =
|
||||||
|
containerSource.safeAs<JvmPackagePartSource>()?.knownJvmBinaryClass.safeAs<ReflectKotlinClass>()?.klass
|
||||||
|
?: throw KotlinReflectionInternalError("Container of deserialized member is not resolved: $this")
|
||||||
|
|
||||||
override fun equals(other: Any?) =
|
override fun equals(other: Any?) =
|
||||||
other is KTypeParameterImpl && descriptor == other.descriptor
|
other is KTypeParameterImpl && container == other.container && name == other.name
|
||||||
|
|
||||||
override fun hashCode() =
|
override fun hashCode() =
|
||||||
descriptor.hashCode()
|
container.hashCode() * 31 + name.hashCode()
|
||||||
|
|
||||||
override fun toString() =
|
override fun toString() =
|
||||||
TypeParameterReference.toString(this)
|
TypeParameterReference.toString(this)
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.jvm.internal
|
||||||
|
|
||||||
|
import kotlin.reflect.KTypeParameter
|
||||||
|
|
||||||
|
interface KTypeParameterOwnerImpl {
|
||||||
|
val typeParameters: List<KTypeParameter>
|
||||||
|
}
|
||||||
@@ -20,6 +20,14 @@ import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.components.ReflectAnnotationSource
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.components.ReflectKotlinClass
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.components.RuntimeSourceElementFactory
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.components.tryLoadClass
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaAnnotation
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaClass
|
||||||
|
import org.jetbrains.kotlin.descriptors.runtime.structure.safeClassLoader
|
||||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||||
@@ -32,23 +40,16 @@ import org.jetbrains.kotlin.protobuf.MessageLite
|
|||||||
import org.jetbrains.kotlin.resolve.constants.*
|
import org.jetbrains.kotlin.resolve.constants.*
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
|
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationContext
|
import org.jetbrains.kotlin.serialization.deserialization.DeserializationContext
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer
|
import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer
|
||||||
|
import java.lang.reflect.Type
|
||||||
import kotlin.jvm.internal.FunctionReference
|
import kotlin.jvm.internal.FunctionReference
|
||||||
import kotlin.jvm.internal.PropertyReference
|
import kotlin.jvm.internal.PropertyReference
|
||||||
|
import kotlin.reflect.KType
|
||||||
import kotlin.reflect.KVisibility
|
import kotlin.reflect.KVisibility
|
||||||
import kotlin.reflect.full.IllegalCallableAccessException
|
import kotlin.reflect.full.IllegalCallableAccessException
|
||||||
import kotlin.reflect.jvm.internal.calls.createAnnotationInstance
|
import kotlin.reflect.jvm.internal.calls.createAnnotationInstance
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.components.ReflectAnnotationSource
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.components.ReflectKotlinClass
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.components.RuntimeSourceElementFactory
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.components.tryLoadClass
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaAnnotation
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.ReflectJavaClass
|
|
||||||
import org.jetbrains.kotlin.descriptors.runtime.structure.safeClassLoader
|
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
|
||||||
import java.lang.reflect.Type
|
|
||||||
import kotlin.reflect.KType
|
|
||||||
|
|
||||||
internal val JVM_STATIC = FqName("kotlin.jvm.JvmStatic")
|
internal val JVM_STATIC = FqName("kotlin.jvm.JvmStatic")
|
||||||
|
|
||||||
@@ -217,3 +218,29 @@ internal fun defaultPrimitiveValue(type: Type): Any? =
|
|||||||
else -> throw UnsupportedOperationException("Unknown primitive: $type")
|
else -> throw UnsupportedOperationException("Unknown primitive: $type")
|
||||||
}
|
}
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
|
internal open class CreateKCallableVisitor(private val container: KDeclarationContainerImpl) :
|
||||||
|
DeclarationDescriptorVisitorEmptyBodies<KCallableImpl<*>, Unit>() {
|
||||||
|
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Unit): KCallableImpl<*> {
|
||||||
|
val receiverCount = (descriptor.dispatchReceiverParameter?.let { 1 } ?: 0) +
|
||||||
|
(descriptor.extensionReceiverParameter?.let { 1 } ?: 0)
|
||||||
|
|
||||||
|
when {
|
||||||
|
descriptor.isVar -> when (receiverCount) {
|
||||||
|
0 -> return KMutableProperty0Impl<Any?>(container, descriptor)
|
||||||
|
1 -> return KMutableProperty1Impl<Any?, Any?>(container, descriptor)
|
||||||
|
2 -> return KMutableProperty2Impl<Any?, Any?, Any?>(container, descriptor)
|
||||||
|
}
|
||||||
|
else -> when (receiverCount) {
|
||||||
|
0 -> return KProperty0Impl<Any?>(container, descriptor)
|
||||||
|
1 -> return KProperty1Impl<Any?, Any?>(container, descriptor)
|
||||||
|
2 -> return KProperty2Impl<Any?, Any?, Any?>(container, descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw KotlinReflectionInternalError("Unsupported property: $descriptor")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit): KCallableImpl<*> =
|
||||||
|
KFunctionImpl(container, descriptor)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user