Reflection: add API for declaration modifiers

#KT-10447 Fixed
This commit is contained in:
Alexander Udalov
2016-07-12 19:06:00 +03:00
parent ada81923dc
commit 7e317f7a7c
24 changed files with 681 additions and 1 deletions
@@ -62,4 +62,19 @@ public interface KCallable<out R> : KAnnotatedElement {
* or its type does not match the type of the provided value, an exception is thrown.
*/
public fun callBy(args: Map<KParameter, Any?>): R
/**
* `true` if this callable is `final`.
*/
public val isFinal: Boolean
/**
* `true` if this callable is `open`.
*/
public val isOpen: Boolean
/**
* `true` if this callable is `abstract`.
*/
public val isAbstract: Boolean
}
@@ -73,6 +73,49 @@ public interface KClass<T : Any> : KDeclarationContainer, KAnnotatedElement, KCl
*/
public val supertypes: List<KType>
/**
* `true` if this class is `final`.
*/
public val isFinal: Boolean
/**
* `true` if this class is `open`.
*/
public val isOpen: Boolean
/**
* `true` if this class is `abstract`.
*/
public val isAbstract: Boolean
/**
* `true` if this class is `sealed`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/classes.html#sealed-classes)
* for more information.
*/
public val isSealed: Boolean
/**
* `true` if this class is a data class.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/data-classes.html)
* for more information.
*/
public val isData: Boolean
/**
* `true` if this class is an inner class.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/nested-classes.html#inner-classes)
* for more information.
*/
public val isInner: Boolean
/**
* `true` if this class is a companion object.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects)
* for more information.
*/
public val isCompanion: Boolean
/**
* Returns `true` if [other] is a [KClass] instance representing the same class on a given platform.
*
+41 -1
View File
@@ -19,4 +19,44 @@ package kotlin.reflect
/**
* Represents a function with introspection capabilities.
*/
public interface KFunction<out R> : KCallable<R>, Function<R>
public interface KFunction<out R> : KCallable<R>, Function<R> {
/**
* `true` if this function is `inline`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html)
* for more information.
*/
public val isInline: Boolean
/**
* `true` if this function is `external`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/java-interop.html#using-jni-with-kotlin)
* for more information.
*/
public val isExternal: Boolean
/**
* `true` if this function is `operator`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/operator-overloading.html)
* for more information.
*/
public val isOperator: Boolean
/**
* `true` if this function is `infix`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/functions.html#infix-notation)
* for more information.
*/
public val isInfix: Boolean
/**
* `true` if this function is `tailrec`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/functions.html#tail-recursive-functions)
* for more information.
*/
public val isTailrec: Boolean
/**
* `true` if this is a suspending function.
*/
public val isSuspend: Boolean
}
@@ -69,4 +69,30 @@ public interface KParameter : KAnnotatedElement {
* 2. The parameter is declared in a member function and one of the corresponding parameters in the super functions is optional.
*/
public val isOptional: Boolean
/**
* `true` if this parameter is `vararg`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/functions.html#variable-number-of-arguments-varargs)
* for more information.
*/
public val isVararg: Boolean
/**
* `true` if this parameter is `noinline`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html#noinline)
* for more information.
*/
public val isNoinline: Boolean
/**
* `true` if this parameter is `crossinline`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html#non-local-returns)
* for more information.
*/
public val isCrossinline: Boolean
/**
* `true` if this parameter is `coroutine`.
*/
public val isCoroutine: Boolean
}
@@ -25,6 +25,20 @@ package kotlin.reflect
* @param R the type of the property.
*/
public interface KProperty<out R> : KCallable<R> {
/**
* `true` if this property is `lateinit`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties)
* for more information.
*/
public val isLateinit: Boolean
/**
* `true` if this property is `const`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/properties.html#compile-time-constants)
* for more information.
*/
public val isConst: Boolean
/** The getter of this property, used to obtain the value of the property. */
public val getter: Getter<R>
@@ -40,4 +40,11 @@ public interface KTypeParameter : KClassifier {
* for more information.
*/
public val variance: KVariance
/**
* `true` if this type parameter is `reified`.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters)
* for more information.
*/
public val isReified: Boolean
}
@@ -17,6 +17,7 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import java.lang.reflect.Type
import java.util.*
@@ -62,6 +63,15 @@ internal interface KCallableImpl<out R> : KCallable<R>, KAnnotatedElementImpl {
override val typeParameters: List<KTypeParameter>
get() = descriptor.typeParameters.map(::KTypeParameterImpl)
override val isFinal: Boolean
get() = descriptor.modality == Modality.FINAL
override val isOpen: Boolean
get() = descriptor.modality == Modality.OPEN
override val isAbstract: Boolean
get() = descriptor.modality == Modality.ABSTRACT
@Suppress("UNCHECKED_CAST")
override fun call(vararg args: Any?): R = reflectionCall {
return caller.call(args) as R
@@ -170,6 +170,27 @@ internal class KClassImpl<T : Any>(override val jClass: Class<T>) :
}
}
override val isFinal: Boolean
get() = descriptor.modality == Modality.FINAL
override val isOpen: Boolean
get() = descriptor.modality == Modality.OPEN
override val isAbstract: Boolean
get() = descriptor.modality == Modality.ABSTRACT
override val isSealed: Boolean
get() = descriptor.modality == Modality.SEALED
override val isData: Boolean
get() = descriptor.isData
override val isInner: Boolean
get() = descriptor.isInner
override val isCompanion: Boolean
get() = descriptor.isCompanionObject
override fun equals(other: Any?): Boolean =
other is KClassImpl<*> && jClass == other.jClass
@@ -109,6 +109,24 @@ internal open class KFunctionImpl protected constructor(
(if (descriptor.extensionReceiverParameter != null) 1 else 0)
}
override val isInline: Boolean
get() = descriptor.isInline
override val isExternal: Boolean
get() = descriptor.isExternal
override val isOperator: Boolean
get() = descriptor.isOperator
override val isInfix: Boolean
get() = descriptor.isInfix
override val isTailrec: Boolean
get() = descriptor.isTailrec
override val isSuspend: Boolean
get() = descriptor.isSuspend
override fun equals(other: Any?): Boolean {
val that = other.asKFunctionImpl() ?: return false
return container == that.container && name == that.name && signature == that.signature
@@ -46,6 +46,18 @@ internal class KParameterImpl(
override val isOptional: Boolean
get() = (descriptor as? ValueParameterDescriptor)?.hasDefaultValue() ?: false
override val isVararg: Boolean
get() = descriptor.let { it is ValueParameterDescriptor && it.varargElementType != null }
override val isNoinline: Boolean
get() = descriptor.let { it is ValueParameterDescriptor && it.isNoinline }
override val isCrossinline: Boolean
get() = descriptor.let { it is ValueParameterDescriptor && it.isCrossinline }
override val isCoroutine: Boolean
get() = descriptor.let { it is ValueParameterDescriptor && it.isCoroutine }
override fun equals(other: Any?) =
other is KParameterImpl && callable == other.callable && descriptor == other.descriptor
@@ -42,10 +42,40 @@ internal interface KPropertyImpl<out R> : KProperty<R>, KCallableImpl<R> {
override val defaultCaller: FunctionCaller<*>? get() = getter.defaultCaller
override val isLateinit: Boolean
get() = descriptor.isLateInit
override val isConst: Boolean
get() = descriptor.isConst
abstract class Accessor<out R> : KProperty.Accessor<R> {
abstract override val property: KPropertyImpl<R>
internal abstract val descriptor: PropertyAccessorDescriptor
@Suppress("unused") // Used as an implementation of KFunction#isInline in subclasses
val isInline: Boolean
get() = descriptor.isInline
@Suppress("unused")
val isExternal: Boolean
get() = descriptor.isExternal
@Suppress("unused")
val isOperator: Boolean
get() = descriptor.isOperator
@Suppress("unused")
val isInfix: Boolean
get() = descriptor.isInfix
@Suppress("unused")
val isTailrec: Boolean
get() = descriptor.isTailrec
@Suppress("unused")
val isSuspend: Boolean
get() = descriptor.isSuspend
}
abstract class Getter<out R> : Accessor<R>(), KProperty.Getter<R>, KCallableImpl<R> {
@@ -40,6 +40,9 @@ internal class KTypeParameterImpl(override val descriptor: TypeParameterDescript
Variance.OUT_VARIANCE -> KVariance.OUT
}
override val isReified: Boolean
get() = descriptor.isReified
override fun equals(other: Any?) =
other is KTypeParameterImpl && descriptor == other.descriptor
@@ -99,6 +99,21 @@ public abstract class CallableReference implements KCallable {
return getReflected().callBy(args);
}
@Override
public boolean isFinal() {
return getReflected().isFinal();
}
@Override
public boolean isOpen() {
return getReflected().isOpen();
}
@Override
public boolean isAbstract() {
return getReflected().isAbstract();
}
public KCallable compute() {
if (reflected == null) {
reflected = computeReflected();
@@ -48,6 +48,27 @@ class ClassReference(override val jClass: Class<*>) : KClass<Any>, ClassBasedDec
override val supertypes: List<KType>
get() = error()
override val isFinal: Boolean
get() = error()
override val isOpen: Boolean
get() = error()
override val isAbstract: Boolean
get() = error()
override val isSealed: Boolean
get() = error()
override val isData: Boolean
get() = error()
override val isInner: Boolean
get() = error()
override val isCompanion: Boolean
get() = error()
private fun error(): Nothing = throw KotlinReflectionNotSupportedError()
override fun equals(other: Any?) =
@@ -84,6 +84,51 @@ public class FunctionReference extends FunctionImpl implements KFunction {
return getReflected().callBy(args);
}
@Override
public boolean isFinal() {
return getReflected().isFinal();
}
@Override
public boolean isOpen() {
return getReflected().isOpen();
}
@Override
public boolean isAbstract() {
return getReflected().isAbstract();
}
@Override
public boolean isInline() {
return getReflected().isInline();
}
@Override
public boolean isExternal() {
return getReflected().isExternal();
}
@Override
public boolean isOperator() {
return getReflected().isOperator();
}
@Override
public boolean isInfix() {
return getReflected().isInfix();
}
@Override
public boolean isTailrec() {
return getReflected().isTailrec();
}
@Override
public boolean isSuspend() {
return getReflected().isSuspend();
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
@@ -19,6 +19,21 @@ package kotlin.jvm.internal;
import kotlin.reflect.KProperty;
public abstract class PropertyReference extends CallableReference implements KProperty {
@Override
protected KProperty getReflected() {
return (KProperty) super.getReflected();
}
@Override
public boolean isLateinit() {
return getReflected().isLateinit();
}
@Override
public boolean isConst() {
return getReflected().isConst();
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;