Support KClass.constructors in reflection
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
||||
@@ -43,6 +44,8 @@ abstract class KCallableContainerImpl : KDeclarationContainer {
|
||||
|
||||
abstract val scope: JetScope
|
||||
|
||||
abstract val constructorDescriptors: Collection<ConstructorDescriptor>
|
||||
|
||||
fun findPropertyDescriptor(name: String, signature: String): PropertyDescriptor {
|
||||
val properties = scope
|
||||
.getProperties(Name.guess(name))
|
||||
@@ -63,8 +66,7 @@ abstract class KCallableContainerImpl : KDeclarationContainer {
|
||||
}
|
||||
|
||||
fun findFunctionDescriptor(name: String, signature: String): FunctionDescriptor {
|
||||
val functions = scope
|
||||
.getFunctions(Name.guess(name))
|
||||
val functions = (if (name == "<init>") constructorDescriptors.toList() else scope.getFunctions(Name.guess(name)))
|
||||
.filter { descriptor ->
|
||||
RuntimeTypeMapper.mapSignature(descriptor) == signature
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
||||
import kotlin.reflect.KCallable
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
|
||||
class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), KClass<T> {
|
||||
@@ -43,6 +44,15 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
|
||||
descriptor, "KClassImpl scope", descriptor.getDefaultType().getMemberScope(), descriptor.getStaticScope()
|
||||
)
|
||||
|
||||
override val constructorDescriptors: Collection<ConstructorDescriptor>
|
||||
get() {
|
||||
val descriptor = descriptor
|
||||
if (descriptor.getKind() == ClassKind.CLASS || descriptor.getKind() == ClassKind.ENUM_CLASS) {
|
||||
return descriptor.getConstructors()
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override val simpleName: String? get() {
|
||||
if (jClass.isAnonymousClass()) return null
|
||||
|
||||
@@ -77,44 +87,57 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
|
||||
override val members: Collection<KCallable<*>>
|
||||
get() = getMembers(declaredOnly = false, nonExtensions = true, extensions = true).toList()
|
||||
|
||||
fun getMembers(declaredOnly: Boolean, nonExtensions: Boolean, extensions: Boolean): Sequence<KCallable<*>> =
|
||||
scope.getAllDescriptors().asSequence()
|
||||
.filter { descriptor ->
|
||||
descriptor !is MemberDescriptor || descriptor.getVisibility() != Visibilities.INVISIBLE_FAKE
|
||||
}
|
||||
.map { descriptor ->
|
||||
descriptor.accept(object : DeclarationDescriptorVisitorEmptyBodies<KCallable<*>?, Nothing>() {
|
||||
private fun skipCallable(descriptor: CallableMemberDescriptor): Boolean {
|
||||
if (declaredOnly && !descriptor.getKind().isReal()) return true
|
||||
@suppress("UNCHECKED_CAST")
|
||||
override val constructors: Collection<KFunction<T>>
|
||||
get() = constructorDescriptors.map {
|
||||
KFunctionImpl(this, it) as KFunction<T>
|
||||
}
|
||||
|
||||
val isExtension = descriptor.getExtensionReceiverParameter() != null
|
||||
if (isExtension && !extensions) return true
|
||||
if (!isExtension && !nonExtensions) return true
|
||||
fun getMembers(declaredOnly: Boolean, nonExtensions: Boolean, extensions: Boolean): Sequence<KCallable<*>> {
|
||||
val visitor = object : DeclarationDescriptorVisitorEmptyBodies<KCallable<*>?, Nothing>() {
|
||||
private fun skipCallable(descriptor: CallableMemberDescriptor): Boolean {
|
||||
if (declaredOnly && !descriptor.getKind().isReal()) return true
|
||||
|
||||
return false
|
||||
}
|
||||
val isExtension = descriptor.getExtensionReceiverParameter() != null
|
||||
if (isExtension && !extensions) return true
|
||||
if (!isExtension && !nonExtensions) return true
|
||||
|
||||
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Nothing?): KCallable<*>? {
|
||||
if (skipCallable(descriptor)) return null
|
||||
return false
|
||||
}
|
||||
|
||||
return if (descriptor.getExtensionReceiverParameter() == null) {
|
||||
if (descriptor.isVar()) KMutableProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
|
||||
else KProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
|
||||
}
|
||||
else {
|
||||
if (descriptor.isVar()) KMutableProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
|
||||
else KProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
|
||||
}
|
||||
}
|
||||
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Nothing?): KCallable<*>? {
|
||||
if (skipCallable(descriptor)) return null
|
||||
|
||||
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Nothing?): KCallable<*>? {
|
||||
if (skipCallable(descriptor)) return null
|
||||
return if (descriptor.getExtensionReceiverParameter() == null) {
|
||||
if (descriptor.isVar()) KMutableProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
|
||||
else KProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
|
||||
}
|
||||
else {
|
||||
if (descriptor.isVar()) KMutableProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
|
||||
else KProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
return KFunctionImpl(this@KClassImpl, descriptor)
|
||||
}
|
||||
}, null)
|
||||
}
|
||||
.filterNotNull()
|
||||
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Nothing?): KCallable<*>? {
|
||||
if (skipCallable(descriptor)) return null
|
||||
|
||||
return KFunctionImpl(this@KClassImpl, descriptor)
|
||||
}
|
||||
|
||||
override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Nothing?): KCallable<*>? {
|
||||
throw IllegalStateException("No constructors should appear in this scope: $descriptor")
|
||||
}
|
||||
}
|
||||
|
||||
return scope.getAllDescriptors().asSequence()
|
||||
.filter { descriptor ->
|
||||
descriptor !is MemberDescriptor || descriptor.getVisibility() != Visibilities.INVISIBLE_FAKE
|
||||
}
|
||||
.map { descriptor ->
|
||||
descriptor.accept(visitor, null)
|
||||
}
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is KClassImpl<*> && jClass == other.jClass
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import kotlin.jvm.internal.FunctionReference
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
@@ -65,5 +66,8 @@ object EmptyContainerForLocal : KCallableContainerImpl() {
|
||||
override val scope: JetScope
|
||||
get() = fail()
|
||||
|
||||
override val constructorDescriptors: Collection<ConstructorDescriptor>
|
||||
get() = fail()
|
||||
|
||||
private fun fail() = throw KotlinReflectionInternalError("Introspecting local functions is not yet supported in Kotlin reflection")
|
||||
}
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import kotlin.jvm.internal.KotlinPackage
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.KPackage
|
||||
|
||||
class KPackageImpl(override val jClass: Class<*>) : KCallableContainerImpl(), KPackage {
|
||||
val descriptor by ReflectProperties.lazySoft {
|
||||
@@ -31,6 +32,9 @@ class KPackageImpl(override val jClass: Class<*>) : KCallableContainerImpl(), KP
|
||||
|
||||
override val scope: JetScope get() = descriptor.memberScope
|
||||
|
||||
override val constructorDescriptors: Collection<ConstructorDescriptor>
|
||||
get() = emptyList()
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is KPackageImpl && jClass == other.jClass
|
||||
|
||||
|
||||
@@ -31,22 +31,22 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
|
||||
object RuntimeTypeMapper {
|
||||
fun mapSignature(function: FunctionDescriptor): String {
|
||||
if (function is DeserializedSimpleFunctionDescriptor) {
|
||||
val proto = function.getProto()
|
||||
if (function is DeserializedCallableMemberDescriptor) {
|
||||
val proto = function.proto
|
||||
if (!proto.hasExtension(JvmProtoBuf.methodSignature)) {
|
||||
// If it's a deserialized function but has no JVM signature, it must be from built-ins
|
||||
return mapIntrinsicFunctionSignature(function) ?:
|
||||
throw KotlinReflectionInternalError("No metadata found for $function")
|
||||
}
|
||||
val signature = proto.getExtension(JvmProtoBuf.methodSignature)
|
||||
return SignatureDeserializer(function.getNameResolver()).methodSignatureString(signature)
|
||||
return SignatureDeserializer(function.nameResolver).methodSignatureString(signature)
|
||||
}
|
||||
else if (function is JavaMethodDescriptor) {
|
||||
val method = (function.getSource() as? JavaSourceElement)?.javaElement as? JavaMethod ?:
|
||||
@@ -130,7 +130,7 @@ object RuntimeTypeMapper {
|
||||
else throw KotlinReflectionInternalError("Unknown origin of $property (${property.javaClass})")
|
||||
}
|
||||
|
||||
private fun mapIntrinsicFunctionSignature(function: DeserializedSimpleFunctionDescriptor): String? {
|
||||
private fun mapIntrinsicFunctionSignature(function: FunctionDescriptor): String? {
|
||||
val parameters = function.getValueParameters()
|
||||
|
||||
when (function.getName().asString()) {
|
||||
|
||||
Reference in New Issue
Block a user