Support KClass.constructors in reflection
This commit is contained in:
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
import kotlin.reflect.*
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
interface Interface
|
||||
annotation class Anno(val x: Int)
|
||||
object Obj
|
||||
|
||||
class C {
|
||||
companion object
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertTrue(Interface::class.constructors.isEmpty())
|
||||
assertTrue(Anno::class.constructors.isEmpty())
|
||||
assertTrue(Obj::class.constructors.isEmpty())
|
||||
assertTrue(C.Companion::class.constructors.isEmpty())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import java.util.Collections
|
||||
import kotlin.reflect.*
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
open class A private constructor(x: Int) {
|
||||
public constructor(s: String): this(s.length())
|
||||
constructor(): this("")
|
||||
}
|
||||
|
||||
class B : A("")
|
||||
|
||||
class C {
|
||||
class Nested
|
||||
inner class Inner
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(3, A::class.constructors.size())
|
||||
assertEquals(1, B::class.constructors.size())
|
||||
|
||||
assertTrue(Collections.disjoint(A::class.members, A::class.constructors))
|
||||
assertTrue(Collections.disjoint(B::class.members, B::class.constructors))
|
||||
|
||||
assertEquals(1, C.Nested::class.constructors.size())
|
||||
assertEquals(1, C.Inner::class.constructors.size())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+12
@@ -2847,11 +2847,23 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/constructors"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("classesWithoutConstructors.kt")
|
||||
public void testClassesWithoutConstructors() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/constructors/classesWithoutConstructors.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("constructorName.kt")
|
||||
public void testConstructorName() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/constructors/constructorName.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleGetConstructors.kt")
|
||||
public void testSimpleGetConstructors() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/constructors/simpleGetConstructors.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/enclosing")
|
||||
|
||||
@@ -39,8 +39,13 @@ public interface KClass<T> : KDeclarationContainer {
|
||||
public val qualifiedName: String?
|
||||
|
||||
/**
|
||||
* All elements accessible in this class, including functions and properties
|
||||
* declared in this class and all of its superclasses.
|
||||
* All functions and properties accessible in this class, including those declared in this class
|
||||
* and all of its superclasses. Does not include constructors.
|
||||
*/
|
||||
public val members: Collection<KCallable<*>>
|
||||
|
||||
/**
|
||||
* All constructors declared in this class.
|
||||
*/
|
||||
public val constructors: Collection<KFunction<T>>
|
||||
}
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected FunctionDescriptorImpl createSubstitutedCopy(
|
||||
protected ConstructorDescriptorImpl createSubstitutedCopy(
|
||||
@NotNull DeclarationDescriptor newOwner,
|
||||
@Nullable FunctionDescriptor original,
|
||||
@NotNull Kind kind
|
||||
|
||||
+4
-8
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.serialization.deserialization
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
@@ -28,10 +27,7 @@ import org.jetbrains.kotlin.serialization.ProtoBuf.Callable
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf.Callable.CallableKind.FUN
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf.Callable.CallableKind.VAL
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf.Callable.CallableKind.VAR
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedAnnotations
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
|
||||
|
||||
public class MemberDeserializer(private val c: DeserializationContext) {
|
||||
public fun loadCallable(proto: Callable): CallableMemberDescriptor {
|
||||
@@ -152,9 +148,9 @@ public class MemberDeserializer(private val c: DeserializationContext) {
|
||||
|
||||
public fun loadConstructor(proto: Callable, isPrimary: Boolean): ConstructorDescriptor {
|
||||
val classDescriptor = c.containingDeclaration as ClassDescriptor
|
||||
val descriptor = ConstructorDescriptorImpl.create(
|
||||
classDescriptor, getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
|
||||
isPrimary, SourceElement.NO_SOURCE
|
||||
val descriptor = DeserializedConstructorDescriptor(
|
||||
classDescriptor, null, getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
|
||||
isPrimary, CallableMemberDescriptor.Kind.DECLARATION, proto, c.nameResolver
|
||||
)
|
||||
val local = c.childContext(descriptor, listOf())
|
||||
descriptor.initialize(
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 org.jetbrains.kotlin.serialization.deserialization.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
|
||||
public class DeserializedConstructorDescriptor(
|
||||
containingDeclaration: ClassDescriptor,
|
||||
original: ConstructorDescriptor?,
|
||||
annotations: Annotations,
|
||||
isPrimary: Boolean,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
override val proto: ProtoBuf.Callable,
|
||||
override val nameResolver: NameResolver
|
||||
) : ConstructorDescriptorImpl(containingDeclaration, original, annotations, isPrimary, kind, SourceElement.NO_SOURCE),
|
||||
DeserializedCallableMemberDescriptor {
|
||||
|
||||
override fun createSubstitutedCopy(
|
||||
newOwner: DeclarationDescriptor,
|
||||
original: FunctionDescriptor?,
|
||||
kind: CallableMemberDescriptor.Kind
|
||||
): DeserializedConstructorDescriptor {
|
||||
return DeserializedConstructorDescriptor(
|
||||
newOwner as ClassDescriptor, original as ConstructorDescriptor?, getAnnotations(), isPrimary, kind, proto, nameResolver
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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