Support KClass.objectInstance for objects and companion objects
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
object Obj {
|
||||
fun foo() = 1
|
||||
}
|
||||
|
||||
class A {
|
||||
companion object {
|
||||
fun foo() = 2
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
companion object Factory {
|
||||
fun foo() = 3
|
||||
}
|
||||
}
|
||||
|
||||
class C
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(1, Obj::class.objectInstance!!.foo())
|
||||
assertEquals(2, A.Companion::class.objectInstance!!.foo())
|
||||
assertEquals(3, B.Factory::class.objectInstance!!.foo())
|
||||
|
||||
assertEquals(null, C::class.objectInstance)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -2994,6 +2994,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("objectInstance.kt")
|
||||
public void testObjectInstance() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classes/objectInstance.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("qualifiedName.kt")
|
||||
public void testQualifiedName() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classes/qualifiedName.kt");
|
||||
|
||||
@@ -24,7 +24,7 @@ package kotlin.reflect
|
||||
*
|
||||
* @param T the type of the class.
|
||||
*/
|
||||
public interface KClass<T> : KDeclarationContainer, KAnnotatedElement {
|
||||
public interface KClass<T : Any> : KDeclarationContainer, KAnnotatedElement {
|
||||
/**
|
||||
* The simple name of the class as it was declared in the source code,
|
||||
* or `null` if the class has no name (if, for example, it is an anonymous object literal).
|
||||
@@ -48,4 +48,9 @@ public interface KClass<T> : KDeclarationContainer, KAnnotatedElement {
|
||||
* All constructors declared in this class.
|
||||
*/
|
||||
public val constructors: Collection<KFunction<T>>
|
||||
|
||||
/**
|
||||
* The instance of the object declaration, or `null` if this class is not an object declaration.
|
||||
*/
|
||||
public val objectInstance: T?
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package kotlin.reflect.jvm.internal
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
@@ -27,7 +28,7 @@ import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
|
||||
class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), KClass<T>, KAnnotatedElementImpl {
|
||||
class KClassImpl<T : Any>(override val jClass: Class<T>) : KCallableContainerImpl(), KClass<T>, KAnnotatedElementImpl {
|
||||
val descriptor by ReflectProperties.lazySoft {
|
||||
val classId = classId
|
||||
|
||||
@@ -92,6 +93,20 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
|
||||
KFunctionImpl(this, it) as KFunction<T>
|
||||
}
|
||||
|
||||
@suppress("UNCHECKED_CAST")
|
||||
override val objectInstance: T? by ReflectProperties.lazy {
|
||||
val descriptor = descriptor
|
||||
if (descriptor.kind != ClassKind.OBJECT) return@lazy null
|
||||
|
||||
val field = if (descriptor.isCompanionObject) {
|
||||
jClass.enclosingClass.getDeclaredField(descriptor.name.asString())
|
||||
}
|
||||
else {
|
||||
jClass.getDeclaredField(JvmAbi.INSTANCE_FIELD)
|
||||
}
|
||||
field.get(null) as T
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is KClassImpl<*> && jClass == other.jClass
|
||||
|
||||
|
||||
@@ -36,5 +36,8 @@ public class ClassReference(override val jClass: Class<*>) : KClass<Any>, Declar
|
||||
override val annotations: List<Annotation>
|
||||
get() = error()
|
||||
|
||||
override val objectInstance: Any?
|
||||
get() = error()
|
||||
|
||||
private fun error(): Nothing = throw KotlinReflectionNotSupportedError()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user