Introduce KProperty{0,1,2}.getDelegate

#KT-8384 In Progress
This commit is contained in:
Alexander Udalov
2016-12-22 18:30:38 +03:00
parent f1cd2ee6fd
commit 78f2515e95
47 changed files with 1398 additions and 0 deletions
@@ -88,6 +88,14 @@ public interface KProperty0<out R> : KProperty<R>, () -> R {
*/
public fun get(): R
/**
* Returns the value of the delegate if this is a delegated property, or `null` if this property is not delegated.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/delegated-properties.html)
* for more information.
*/
@SinceKotlin("1.1")
public fun getDelegate(): Any?
override val getter: Getter<R>
public interface Getter<out R> : KProperty.Getter<R>, () -> R
@@ -126,6 +134,21 @@ public interface KProperty1<T, out R> : KProperty<R>, (T) -> R {
*/
public fun get(receiver: T): R
/**
* Returns the value of the delegate if this is a delegated property, or `null` if this property is not delegated.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/delegated-properties.html)
* for more information.
*
* Note that for a top level **extension** property, the delegate is the same for all extension receivers,
* so the actual [receiver] instance passed in is not going to make any difference, it must only be a value of [T].
*
* @param receiver the receiver which is used to obtain the value of the property delegate.
* For example, it should be a class instance if this is a member property of that class,
* or an extension receiver if this is a top level extension property.
*/
@SinceKotlin("1.1")
public fun getDelegate(receiver: T): Any?
override val getter: Getter<T, R>
public interface Getter<T, out R> : KProperty.Getter<R>, (T) -> R
@@ -171,6 +194,20 @@ public interface KProperty2<D, E, out R> : KProperty<R>, (D, E) -> R {
*/
public fun get(receiver1: D, receiver2: E): R
/**
* Returns the value of the delegate if this is a delegated property, or `null` if this property is not delegated.
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/delegated-properties.html)
* for more information.
*
* In case of the extension property in a class, the instance of the class should be passed first
* and the instance of the extension receiver second.
*
* @param receiver1 the instance of the first receiver.
* @param receiver2 the instance of the second receiver.
*/
@SinceKotlin("1.1")
public fun getDelegate(receiver1: D, receiver2: E): Any?
override val getter: Getter<D, E, R>
public interface Getter<D, E, out R> : KProperty.Getter<R>, (D, E) -> R
@@ -16,6 +16,8 @@
package kotlin.reflect.full
import kotlin.reflect.KProperty
import kotlin.reflect.jvm.isAccessible
/**
* An exception that is thrown when `call` is invoked on a callable or `get` or `set` is invoked on a property
@@ -27,6 +29,20 @@ package kotlin.reflect.full
*/
class IllegalCallableAccessException(cause: IllegalAccessException) : kotlin.reflect.IllegalCallableAccessException(cause)
/**
* An exception that is thrown when `getDelegate` is invoked on a [KProperty] object that was not made accessible
* with [isAccessible].
*
* @see [kotlin.reflect.KProperty0.getDelegate]
* @see [kotlin.reflect.KProperty1.getDelegate]
* @see [kotlin.reflect.KProperty2.getDelegate]
* @see [kotlin.reflect.jvm.isAccessible]
*/
class IllegalPropertyDelegateAccessException(cause: IllegalAccessException) : Exception(
"Cannot obtain the delegate of a non-accessible property. Use \"isAccessible = true\" to make the property accessible",
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.
@@ -17,6 +17,7 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KProperty0
@@ -31,6 +32,10 @@ internal open class KProperty0Impl<out R> : KProperty0<R>, KPropertyImpl<R> {
override fun get(): R = getter.call()
private val delegateFieldValue = lazy(PUBLICATION) { getDelegate(computeDelegateField(), boundReceiver) }
override fun getDelegate(): Any? = delegateFieldValue.value
override fun invoke(): R = get()
class Getter<out R>(override val property: KProperty0Impl<R>) : KPropertyImpl.Getter<R>(), KProperty0.Getter<R> {
@@ -17,6 +17,7 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty1
@@ -31,6 +32,10 @@ internal open class KProperty1Impl<T, out R> : KProperty1<T, R>, KPropertyImpl<R
override fun get(receiver: T): R = getter.call(receiver)
private val delegateField = lazy(PUBLICATION) { computeDelegateField() }
override fun getDelegate(receiver: T): Any? = getDelegate(delegateField.value, receiver)
override fun invoke(receiver: T): R = get(receiver)
class Getter<T, out R>(override val property: KProperty1Impl<T, R>) : KPropertyImpl.Getter<R>(), KProperty1.Getter<T, R> {
@@ -17,6 +17,7 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlin.jvm.internal.CallableReference
import kotlin.reflect.KMutableProperty2
import kotlin.reflect.KProperty2
@@ -32,6 +33,10 @@ internal open class KProperty2Impl<D, E, out R> : KProperty2<D, E, R>, KProperty
override fun get(receiver1: D, receiver2: E): R = getter.call(receiver1, receiver2)
private val delegateField = lazy(PUBLICATION) { computeDelegateField() }
override fun getDelegate(receiver1: D, receiver2: E): Any? = getDelegate(delegateField.value, receiver1)
override fun invoke(receiver1: D, receiver2: E): R = get(receiver1, receiver2)
class Getter<D, E, out R>(override val property: KProperty2Impl<D, E, R>) : KPropertyImpl.Getter<R>(), KProperty2.Getter<D, E, R> {
@@ -29,6 +29,7 @@ import kotlin.jvm.internal.CallableReference
import kotlin.reflect.KFunction
import kotlin.reflect.KMutableProperty
import kotlin.reflect.KProperty
import kotlin.reflect.full.IllegalPropertyDelegateAccessException
import kotlin.reflect.jvm.internal.JvmPropertySignature.*
internal abstract class KPropertyImpl<out R> private constructor(
@@ -81,6 +82,17 @@ internal abstract class KPropertyImpl<out R> private constructor(
val javaField: Field? get() = javaField_()
protected fun computeDelegateField(): Field? =
if (@Suppress("DEPRECATION") descriptor.isDelegated) javaField else null
protected fun getDelegate(field: Field?, receiver: Any?): Any? =
try {
field?.get(receiver)
}
catch (e: IllegalAccessException) {
throw IllegalPropertyDelegateAccessException(e)
}
override abstract val getter: Getter<R>
private val descriptor_ = ReflectProperties.lazySoft(descriptorInitialValue) {
@@ -47,4 +47,9 @@ public abstract class MutablePropertyReference0 extends MutablePropertyReference
public KMutableProperty0.Setter getSetter() {
return ((KMutableProperty0) getReflected()).getSetter();
}
@Override
public Object getDelegate() {
return ((KMutableProperty0) getReflected()).getDelegate();
}
}
@@ -47,4 +47,9 @@ public abstract class MutablePropertyReference1 extends MutablePropertyReference
public KMutableProperty1.Setter getSetter() {
return ((KMutableProperty1) getReflected()).getSetter();
}
@Override
public Object getDelegate(Object receiver) {
return ((KMutableProperty1) getReflected()).getDelegate(receiver);
}
}
@@ -40,4 +40,9 @@ public abstract class MutablePropertyReference2 extends MutablePropertyReference
public KMutableProperty2.Setter getSetter() {
return ((KMutableProperty2) getReflected()).getSetter();
}
@Override
public Object getDelegate(Object receiver1, Object receiver2) {
return ((KMutableProperty2) getReflected()).getDelegate(receiver1, receiver2);
}
}
@@ -42,4 +42,9 @@ public abstract class PropertyReference0 extends PropertyReference implements KP
public KProperty0.Getter getGetter() {
return ((KProperty0) getReflected()).getGetter();
}
@Override
public Object getDelegate() {
return ((KProperty0) getReflected()).getDelegate();
}
}
@@ -41,4 +41,9 @@ public abstract class PropertyReference1 extends PropertyReference implements KP
public KProperty1.Getter getGetter() {
return ((KProperty1) getReflected()).getGetter();
}
@Override
public Object getDelegate(Object receiver) {
return ((KProperty1) getReflected()).getDelegate(receiver);
}
}
@@ -34,4 +34,9 @@ public abstract class PropertyReference2 extends PropertyReference implements KP
public KProperty2.Getter getGetter() {
return ((KProperty2) getReflected()).getGetter();
}
@Override
public Object getDelegate(Object receiver1, Object receiver2) {
return ((KProperty2) getReflected()).getDelegate(receiver1, receiver2);
}
}