Simplify property hierarchy in reflection

Leave only 3*2 = 6 classes: KProperty0, KProperty1, KProperty2 and their
mutable analogs, depending on the number of receivers a property takes
This commit is contained in:
Alexander Udalov
2015-06-26 16:40:39 +03:00
parent c3b97e0668
commit 30794060a9
58 changed files with 374 additions and 653 deletions
@@ -21,11 +21,11 @@ import kotlin.reflect.jvm.internal.KClassImpl
/**
* Returns non-extension properties declared in this class.
*/
public val <T> KClass<T>.declaredProperties: Collection<KMemberProperty<T, *>>
public val <T> KClass<T>.declaredProperties: Collection<KProperty1<T, *>>
get() = (this as KClassImpl<T>).getProperties(declared = true)
/**
* Returns extension properties declared in this class.
*/
public val <T> KClass<T>.declaredExtensionProperties: Collection<KMemberExtensionProperty<T, *, *>>
public val <T> KClass<T>.declaredExtensionProperties: Collection<KProperty2<T, *, *>>
get() = (this as KClassImpl<T>).getExtensionProperties(declared = true)
@@ -18,4 +18,4 @@ package kotlin.reflect.jvm.internal
import kotlin.reflect.KCallable
trait KCallableImpl<out R> : KCallable<R>
interface KCallableImpl<out R> : KCallable<R>
@@ -75,22 +75,22 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
}
}
override val properties: Collection<KMemberProperty<T, *>>
override val properties: Collection<KProperty1<T, *>>
get() = getProperties(declared = false)
override val extensionProperties: Collection<KMemberExtensionProperty<T, *, *>>
override val extensionProperties: Collection<KProperty2<T, *, *>>
get() = getExtensionProperties(declared = false)
fun getProperties(declared: Boolean): Collection<KMemberProperty<T, *>> =
fun getProperties(declared: Boolean): Collection<KProperty1<T, *>> =
getProperties(extension = false, declared = declared) { descriptor ->
if (descriptor.isVar()) KMutableMemberPropertyImpl<T, Any?>(this, descriptor)
else KMemberPropertyImpl<T, Any?>(this, descriptor)
if (descriptor.isVar()) KMutableProperty1Impl<T, Any?>(this, descriptor)
else KProperty1Impl<T, Any?>(this, descriptor)
}
fun getExtensionProperties(declared: Boolean): Collection<KMemberExtensionProperty<T, *, *>> =
fun getExtensionProperties(declared: Boolean): Collection<KProperty2<T, *, *>> =
getProperties(extension = true, declared = declared) { descriptor ->
if (descriptor.isVar()) KMutableMemberExtensionPropertyImpl<T, Any?, Any?>(this, descriptor)
else KMemberExtensionPropertyImpl<T, Any?, Any?>(this, descriptor)
if (descriptor.isVar()) KMutableProperty2Impl<T, Any?, Any?>(this, descriptor)
else KProperty2Impl<T, Any?, Any?>(this, descriptor)
}
private fun <P : KProperty<*>> getProperties(extension: Boolean, declared: Boolean, create: (PropertyDescriptor) -> P): Collection<P> =
@@ -104,11 +104,11 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
.map(create)
.toList()
fun memberProperty(name: String): KMemberProperty<T, *> =
KMemberPropertyImpl<T, Any>(this, name)
fun memberProperty(name: String): KProperty1<T, *> =
KProperty1Impl<T, Any>(this, name, null)
fun mutableMemberProperty(name: String): KMutableMemberProperty<T, *> =
KMutableMemberPropertyImpl<T, Any>(this, name)
fun mutableMemberProperty(name: String): KMutableProperty1<T, *> =
KMutableProperty1Impl<T, Any>(this, name, null)
override fun equals(other: Any?): Boolean =
other is KClassImpl<*> && jClass == other.jClass
@@ -1,58 +0,0 @@
/*
* 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 kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import kotlin.reflect.IllegalPropertyAccessException
import kotlin.reflect.KMemberProperty
import kotlin.reflect.KMutableMemberProperty
open class KMemberPropertyImpl<T : Any, out R> : DescriptorBasedProperty, KMemberProperty<T, R>, KPropertyImpl<R> {
constructor(container: KClassImpl<T>, name: String) : super(container, name, null)
constructor(container: KClassImpl<T>, descriptor: PropertyDescriptor) : super(container, descriptor)
override val name: String get() = descriptor.getName().asString()
override fun get(instance: T): R {
try {
val getter = getter
@suppress("UNCHECKED_CAST")
return if (getter != null) getter(instance) as R else field!!.get(instance) as R
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
}
}
class KMutableMemberPropertyImpl<T : Any, R> : KMemberPropertyImpl<T, R>, KMutableMemberProperty<T, R>, KMutablePropertyImpl<R> {
constructor(container: KClassImpl<T>, name: String) : super(container, name)
constructor(container: KClassImpl<T>, descriptor: PropertyDescriptor) : super(container, descriptor)
override fun set(instance: T, value: R) {
try {
val setter = setter
if (setter != null) setter(instance, value) else field!!.set(instance, value)
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
}
}
@@ -31,17 +31,17 @@ class KPackageImpl(override val jClass: Class<*>) : KCallableContainerImpl(), KP
override val scope: JetScope get() = descriptor.memberScope
fun topLevelVariable(name: String): KTopLevelVariable<*> =
KTopLevelVariableImpl<Any?>(this, name)
fun topLevelVariable(name: String): KProperty0<*> =
KProperty0Impl<Any?>(this, name)
fun mutableTopLevelVariable(name: String): KMutableTopLevelVariable<*> =
KMutableTopLevelVariableImpl<Any?>(this, name)
fun mutableTopLevelVariable(name: String): KMutableProperty0<*> =
KMutableProperty0Impl<Any?>(this, name)
fun <T> topLevelExtensionProperty(name: String, receiver: Class<T>): KTopLevelExtensionProperty<T, *> =
KTopLevelExtensionPropertyImpl<T, Any?>(this, name, receiver)
fun <T> topLevelExtensionProperty(name: String, receiver: Class<T>): KProperty1<T, *> =
KProperty1Impl<T, Any?>(this, name, receiver)
fun <T> mutableTopLevelExtensionProperty(name: String, receiver: Class<T>): KMutableTopLevelExtensionProperty<T, *> =
KMutableTopLevelExtensionPropertyImpl<T, Any?>(this, name, receiver)
fun <T> mutableTopLevelExtensionProperty(name: String, receiver: Class<T>): KMutableProperty1<T, *> =
KMutableProperty1Impl<T, Any?>(this, name, receiver)
override fun equals(other: Any?): Boolean =
other is KPackageImpl && jClass == other.jClass
@@ -18,10 +18,10 @@ package kotlin.reflect.jvm.internal
import java.lang.reflect.Method
import kotlin.reflect.IllegalPropertyAccessException
import kotlin.reflect.KMutableTopLevelVariable
import kotlin.reflect.KTopLevelVariable
import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KProperty0
open class KTopLevelVariableImpl<out R> : DescriptorBasedProperty, KTopLevelVariable<R>, KVariableImpl<R> {
open class KProperty0Impl<out R> : DescriptorBasedProperty, KProperty0<R>, KPropertyImpl<R> {
constructor(container: KPackageImpl, name: String) : super(container, name, null)
override val name: String get() = descriptor.getName().asString()
@@ -39,10 +39,10 @@ open class KTopLevelVariableImpl<out R> : DescriptorBasedProperty, KTopLevelVari
}
}
class KMutableTopLevelVariableImpl<R> : KTopLevelVariableImpl<R>, KMutableTopLevelVariable<R>, KMutableVariableImpl<R> {
class KMutableProperty0Impl<R> : KProperty0Impl<R>, KMutableProperty0<R>, KMutablePropertyImpl<R> {
constructor(container: KPackageImpl, name: String) : super(container, name)
override val setter: Method get() = super<KTopLevelVariableImpl>.setter!!
override val setter: Method get() = super<KProperty0Impl>.setter!!
override fun set(value: R) {
try {
@@ -0,0 +1,88 @@
/*
* 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 kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import java.lang.reflect.Modifier
import kotlin.reflect.IllegalPropertyAccessException
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty1
open class KProperty1Impl<T, out R> : DescriptorBasedProperty, KProperty1<T, R>, KPropertyImpl<R> {
constructor(container: KCallableContainerImpl, name: String, receiverParameterClass: Class<*>?) : super(
container, name, receiverParameterClass
)
constructor(container: KCallableContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
override val name: String get() = descriptor.getName().asString()
// TODO: consider optimizing this, not to do complex checks on every access
@suppress("UNCHECKED_CAST")
override fun get(receiver: T): R {
try {
val getter = getter ?:
return field!!.get(receiver) as R
if (Modifier.isStatic(getter.getModifiers())) {
// Workaround the case of platformStatic property in object, getter of which doesn't take a receiver
if (getter.getParameterTypes().isEmpty()) {
return getter.invoke(null) as R
}
return getter.invoke(null, receiver) as R
}
return getter.invoke(receiver) as R
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
}
}
class KMutableProperty1Impl<T, R> : KProperty1Impl<T, R>, KMutableProperty1<T, R>, KMutablePropertyImpl<R> {
constructor(container: KCallableContainerImpl, name: String, receiverParameterClass: Class<*>?) : super(
container, name, receiverParameterClass
)
constructor(container: KCallableContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
override fun set(receiver: T, value: R) {
try {
val setter = setter ?:
return field!!.set(receiver, value)
if (Modifier.isStatic(setter.getModifiers())) {
// Workaround the case of platformStatic property in object, setter of which doesn't take a receiver
if (setter.getParameterTypes().size() == 1) {
setter.invoke(null, value)
}
else {
setter.invoke(null, receiver, value)
}
}
else {
setter.invoke(receiver, value)
}
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
}
}
@@ -20,10 +20,10 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import java.lang.reflect.Field
import java.lang.reflect.Method
import kotlin.reflect.IllegalPropertyAccessException
import kotlin.reflect.KMemberExtensionProperty
import kotlin.reflect.KMutableMemberExtensionProperty
import kotlin.reflect.KMutableProperty2
import kotlin.reflect.KProperty2
open class KMemberExtensionPropertyImpl<D : Any, E, out R> : DescriptorBasedProperty, KMemberExtensionProperty<D, E, R>, KPropertyImpl<R> {
open class KProperty2Impl<D, E, out R> : DescriptorBasedProperty, KProperty2<D, E, R>, KPropertyImpl<R> {
constructor(container: KClassImpl<D>, name: String, receiverParameterClass: Class<E>) : super(container, name, receiverParameterClass)
constructor(container: KClassImpl<D>, descriptor: PropertyDescriptor) : super(container, descriptor)
@@ -34,10 +34,10 @@ open class KMemberExtensionPropertyImpl<D : Any, E, out R> : DescriptorBasedProp
override val field: Field? get() = null
override fun get(instance: D, extensionReceiver: E): R {
override fun get(receiver1: D, receiver2: E): R {
try {
@suppress("UNCHECKED_CAST")
return getter.invoke(instance, extensionReceiver) as R
return getter.invoke(receiver1, receiver2) as R
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
@@ -46,19 +46,16 @@ open class KMemberExtensionPropertyImpl<D : Any, E, out R> : DescriptorBasedProp
}
class KMutableMemberExtensionPropertyImpl<D : Any, E, R> :
KMemberExtensionPropertyImpl<D, E, R>,
KMutableMemberExtensionProperty<D, E, R>,
KMutablePropertyImpl<R> {
class KMutableProperty2Impl<D, E, R> : KProperty2Impl<D, E, R>, KMutableProperty2<D, E, R>, KMutablePropertyImpl<R> {
constructor(container: KClassImpl<D>, name: String, receiverParameterClass: Class<E>) : super(container, name, receiverParameterClass)
constructor(container: KClassImpl<D>, descriptor: PropertyDescriptor) : super(container, descriptor)
override val setter: Method get() = super<KMemberExtensionPropertyImpl>.setter!!
override val setter: Method get() = super<KProperty2Impl>.setter!!
override fun set(instance: D, extensionReceiver: E, value: R) {
override fun set(receiver1: D, receiver2: E, value: R) {
try {
setter.invoke(instance, extensionReceiver, value)
setter.invoke(receiver1, receiver2, value)
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
@@ -19,13 +19,13 @@ package kotlin.reflect.jvm.internal
import java.lang.reflect.*
import kotlin.reflect.*
trait KPropertyImpl<out R> : KProperty<R>, KCallableImpl<R> {
interface KPropertyImpl<out R> : KProperty<R>, KCallableImpl<R> {
val field: Field?
val getter: Method?
}
trait KMutablePropertyImpl<R> : KMutableProperty<R>, KPropertyImpl<R> {
interface KMutablePropertyImpl<R> : KMutableProperty<R>, KPropertyImpl<R> {
val setter: Method?
}
@@ -1,58 +0,0 @@
/*
* 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 kotlin.reflect.jvm.internal
import java.lang.reflect.Method
import kotlin.reflect.IllegalPropertyAccessException
import kotlin.reflect.KMutableTopLevelExtensionProperty
import kotlin.reflect.KTopLevelExtensionProperty
open class KTopLevelExtensionPropertyImpl<T, out R> : DescriptorBasedProperty, KTopLevelExtensionProperty<T, R>, KPropertyImpl<R> {
constructor(container: KPackageImpl, name: String, receiverParameterClass: Class<T>) : super(container, name, receiverParameterClass)
override val name: String get() = descriptor.getName().asString()
override val getter: Method get() = super<DescriptorBasedProperty>.getter!!
override fun get(receiver: T): R {
try {
@suppress("UNCHECKED_CAST")
return getter.invoke(null, receiver) as R
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
}
}
class KMutableTopLevelExtensionPropertyImpl<T, R> :
KTopLevelExtensionPropertyImpl<T, R>,
KMutableTopLevelExtensionProperty<T, R>,
KMutablePropertyImpl<R> {
constructor(container: KPackageImpl, name: String, receiverParameterClass: Class<T>) : super(container, name, receiverParameterClass)
override val setter: Method get() = super<KTopLevelExtensionPropertyImpl>.setter!!
override fun set(receiver: T, value: R) {
try {
setter.invoke(null, receiver, value)
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
}
}
@@ -1,23 +0,0 @@
/*
* 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 kotlin.reflect.jvm.internal
import kotlin.reflect.*
trait KVariableImpl<out R> : KVariable<R>, KPropertyImpl<R>
trait KMutableVariableImpl<R> : KMutableVariable<R>, KVariableImpl<R>, KMutablePropertyImpl<R>
@@ -50,32 +50,32 @@ public class ReflectionFactoryImpl extends ReflectionFactory {
// Properties
@Override
public KMemberProperty memberProperty(String name, KClass owner) {
public KProperty1 memberProperty(String name, KClass owner) {
return ((KClassImpl) owner).memberProperty(name);
}
@Override
public KMutableMemberProperty mutableMemberProperty(String name, KClass owner) {
public KMutableProperty1 mutableMemberProperty(String name, KClass owner) {
return ((KClassImpl) owner).mutableMemberProperty(name);
}
@Override
public KTopLevelVariable topLevelVariable(String name, KPackage owner) {
public KProperty0 topLevelVariable(String name, KPackage owner) {
return ((KPackageImpl) owner).topLevelVariable(name);
}
@Override
public KMutableTopLevelVariable mutableTopLevelVariable(String name, KPackage owner) {
public KMutableProperty0 mutableTopLevelVariable(String name, KPackage owner) {
return ((KPackageImpl) owner).mutableTopLevelVariable(name);
}
@Override
public KTopLevelExtensionProperty topLevelExtensionProperty(String name, KPackage owner, Class receiver) {
public KProperty1 topLevelExtensionProperty(String name, KPackage owner, Class receiver) {
return ((KPackageImpl) owner).topLevelExtensionProperty(name, receiver);
}
@Override
public KMutableTopLevelExtensionProperty mutableTopLevelExtensionProperty(String name, KPackage owner, Class receiver) {
public KMutableProperty1 mutableTopLevelExtensionProperty(String name, KPackage owner, Class receiver) {
return ((KPackageImpl) owner).mutableTopLevelExtensionProperty(name, receiver);
}
}
@@ -41,6 +41,13 @@ public val KPackage.javaFacade: Class<*>
get() = (this as KPackageImpl).jClass
/**
* Returns a Java [Field] instance corresponding to the backing field of the given property,
* or `null` if the property has no backing field.
*/
public val KProperty<*>.javaField: Field?
get() = (this as KPropertyImpl<*>).field
/**
* 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.
@@ -56,45 +63,6 @@ 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
// Java reflection -> Kotlin reflection
@@ -17,8 +17,8 @@
package kotlin.reflect.jvm
import kotlin.reflect.KProperty
import kotlin.reflect.jvm.internal.KMemberPropertyImpl
import kotlin.reflect.jvm.internal.KMutableMemberPropertyImpl
import kotlin.reflect.jvm.internal.KProperty1Impl
import kotlin.reflect.jvm.internal.KMutableProperty1Impl
/**
* Provides a way to suppress JVM access checks for a property.
@@ -34,11 +34,11 @@ import kotlin.reflect.jvm.internal.KMutableMemberPropertyImpl
public var <R> KProperty<R>.accessible: Boolean
get() {
return when (this) {
is KMutableMemberPropertyImpl<*, R> ->
is KMutableProperty1Impl<*, R> ->
field?.isAccessible() ?: true &&
getter?.isAccessible() ?: true &&
setter?.isAccessible() ?: true
is KMemberPropertyImpl<*, R> ->
is KProperty1Impl<*, R> ->
field?.isAccessible() ?: true &&
getter?.isAccessible() ?: true
else -> {
@@ -49,12 +49,12 @@ public var <R> KProperty<R>.accessible: Boolean
}
set(value) {
when (this) {
is KMutableMemberPropertyImpl<*, R> -> {
is KMutableProperty1Impl<*, R> -> {
field?.setAccessible(value)
getter?.setAccessible(value)
setter?.setAccessible(value)
}
is KMemberPropertyImpl<*, R> -> {
is KProperty1Impl<*, R> -> {
field?.setAccessible(value)
getter?.setAccessible(value)
}