From 593613609fdf245c1143cc48f5ec8a9f57445942 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 17 Mar 2015 22:25:00 +0300 Subject: [PATCH] Document JVM-specific reflection API --- .../src/kotlin/reflect/KClassExtensions.kt | 6 +++ .../src/kotlin/reflect/exceptions.kt | 19 ++++++- .../src/kotlin/reflect/jvm/mapping.kt | 53 ++++++++++++++++++- .../src/kotlin/reflect/jvm/properties.kt | 11 ++++ 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/core/reflection.jvm/src/kotlin/reflect/KClassExtensions.kt b/core/reflection.jvm/src/kotlin/reflect/KClassExtensions.kt index 20fee73fd8e..30d73543926 100644 --- a/core/reflection.jvm/src/kotlin/reflect/KClassExtensions.kt +++ b/core/reflection.jvm/src/kotlin/reflect/KClassExtensions.kt @@ -18,8 +18,14 @@ package kotlin.reflect import kotlin.reflect.jvm.internal.KClassImpl +/** + * Returns non-extension properties declared in this class. + */ public val KClass.declaredProperties: Collection> get() = (this as KClassImpl).getProperties(declared = true) +/** + * Returns extension properties declared in this class. + */ public val KClass.declaredExtensionProperties: Collection> get() = (this as KClassImpl).getExtensionProperties(declared = true) diff --git a/core/reflection.jvm/src/kotlin/reflect/exceptions.kt b/core/reflection.jvm/src/kotlin/reflect/exceptions.kt index 7201f1efe04..b68b17d2009 100644 --- a/core/reflection.jvm/src/kotlin/reflect/exceptions.kt +++ b/core/reflection.jvm/src/kotlin/reflect/exceptions.kt @@ -16,15 +16,27 @@ package kotlin.reflect +/** + * An exception that is thrown when `get` or `set` is called on a property + * and that property is not accessible (in JVM terms) from the calling method. + * + * @param cause the original exception thrown by the JVM. + * + * @see [kotlin.reflect.jvm.accessible] + */ public class IllegalPropertyAccessException(cause: IllegalAccessException) : Exception(cause.getMessage()) { - { + init { [suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")] (this as java.lang.Throwable).initCause(cause) } } +/** + * An exception that is thrown when the code tries to introspect a property of a class or a package + * and that class or the package no longer has that property. + */ public class NoSuchPropertyException(cause: Exception? = null) : Exception() { - { + init { [suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")] if (cause != null) { (this as java.lang.Throwable).initCause(cause) @@ -32,4 +44,7 @@ public class NoSuchPropertyException(cause: Exception? = null) : Exception() { } } +/** + * Signals that Kotlin reflection had reached an inconsistent state from which it cannot recover. + */ public class KotlinReflectionInternalError(message: String) : Error(message) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt index f348e4e39ae..bb683ef81db 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt @@ -25,37 +25,74 @@ import kotlin.reflect.jvm.internal.* // Kotlin reflection -> Java reflection +/** + * Returns a Java [Class] instance corresponding to the given [KClass] instance. + */ public val KClass.java: Class get() = (this as KClassImpl).jClass +/** + * Returns a Java [Class] instance that represents a Kotlin package. + * The methods and fields of this class are generated from top level functions and properties in the Kotlin package. + * See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/java-interop.html#package-level-functions) + * for more information. + */ public val KPackage.javaFacade: Class<*> get() = (this as KPackageImpl).jClass +/** + * Returns a Java [Method] instance corresponding to the getter of the given property, + * or `null` if the property has no getter, for example in case of a simple private `val` in a class. + */ public val KProperty<*>.javaGetter: Method? get() = (this as? KPropertyImpl<*>)?.getter +/** + * Returns a Java [Method] instance corresponding to the setter of the given mutable property, + * or `null` if the property has no setter, for example in case of a simple private `var` in a class. + */ public val KMutableProperty<*>.javaSetter: Method? get() = (this as? KMutablePropertyImpl<*>)?.setter +/** + * Returns a Java [Field] instance corresponding to the backing field of the given top level property, + * or `null` if the property has no backing field. + */ public val KTopLevelVariable<*>.javaField: Field? get() = (this as KPropertyImpl<*>).field +/** + * Returns a Java [Method] instance corresponding to the getter of the given top level property. + */ public val KTopLevelVariable<*>.javaGetter: Method get() = (this as KTopLevelVariableImpl<*>).getter +/** + * Returns a Java [Method] instance corresponding to the setter of the given top level property. + */ public val KMutableTopLevelVariable<*>.javaSetter: Method get() = (this as KMutableTopLevelVariableImpl<*>).setter +/** + * Returns a Java [Method] instance corresponding to the getter of the given top level extension property. + */ public val KTopLevelExtensionProperty<*, *>.javaGetter: Method get() = (this as KTopLevelExtensionPropertyImpl<*, *>).getter +/** + * Returns a Java [Method] instance corresponding to the setter of the given top level extension property. + */ public val KMutableTopLevelExtensionProperty<*, *>.javaSetter: Method get() = (this as KMutableTopLevelExtensionPropertyImpl<*, *>).setter +/** + * Returns a Java [Field] instance corresponding to the backing field of the given member property, + * or `null` if the property has no backing field. + */ public val KMemberProperty<*, *>.javaField: Field? get() = (this as KPropertyImpl<*>).field @@ -63,14 +100,28 @@ public val KMemberProperty<*, *>.javaField: Field? // Java reflection -> Kotlin reflection // TODO: getstatic $kotlinClass or go to foreignKClasses +/** + * Returns a [KClass] instance corresponding to the given Java [Class] instance. + */ public val Class.kotlin: KClass get() = KClassImpl(this) // TODO: getstatic $kotlinPackage +// TODO: make nullable or throw exception +/** + * Returns a [KPackage] instance corresponding to the Java [Class] instance. + * The given class is generated from top level functions and properties in the Kotlin package. + * See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/java-interop.html#package-level-functions) + * for more information. + */ public val Class<*>.kotlinPackage: KPackage get() = KPackageImpl(this) +// TODO: make nullable to filter out synthetic fields (KT-5759) +/** + * Returns a [KProperty] instance corresponding to the given Java [Field] instance. + */ public val Field.kotlin: KProperty<*> get() { val clazz = getDeclaringClass() @@ -83,7 +134,7 @@ public val Field.kotlin: KProperty<*> return if (final) Reflection.topLevelVariable(name, kPackage) else Reflection.mutableTopLevelVariable(name, kPackage) } else { - val kClass = (clazz as Class).kotlin + val kClass = clazz.kotlin return if (final) Reflection.memberProperty(name, kClass) else Reflection.mutableMemberProperty(name, kClass) } } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/properties.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/properties.kt index 7b2256814dc..093aa963fa4 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/properties.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/properties.kt @@ -20,6 +20,17 @@ import kotlin.reflect.KProperty import kotlin.reflect.jvm.internal.KMemberPropertyImpl import kotlin.reflect.jvm.internal.KMutableMemberPropertyImpl +/** + * Provides a way to suppress JVM access checks for a property. + * + * @getter returns `true` if JVM access checks are suppressed for this property object. + * In case of a `var` property, that means that both getter and setter are accessible. + * + * @setter if set to `true`, suppresses JVM access checks for this property object. + * In case of a `var` property, both getter and setter are made accessible. + * + * @see [java.lang.reflect.AccessibleObject] + */ public var KProperty.accessible: Boolean get() { return when (this) {