Remove KForeignMemberProperty and KClassOrigin, use KMemberPropertyImpl instead

This commit is contained in:
Alexander Udalov
2015-02-20 19:22:30 +03:00
parent ff0044f66a
commit fdfd808d80
8 changed files with 69 additions and 128 deletions
@@ -9,8 +9,8 @@ fun box(): String {
val s = J::s
// Check that correct reflection objects are created
assert(i.javaClass.getSimpleName() == "KForeignMemberProperty", "Fail i class")
assert(s.javaClass.getSimpleName() == "KMutableForeignMemberProperty", "Fail s class")
assert(i.javaClass.getSimpleName() == "KMemberPropertyImpl", "Fail i class")
assert(s.javaClass.getSimpleName() == "KMutableMemberPropertyImpl", "Fail s class")
// Check that no Method objects are created for such properties
assert(i.javaGetter == null, "Fail i getter")
@@ -0,0 +1,11 @@
package test;
public class equalsHashCodeToString {
public final boolean b;
public char c;
public equalsHashCodeToString() {
this.b = false;
this.c = '0';
}
}
@@ -0,0 +1,17 @@
package test
import kotlin.test.*
import test.equalsHashCodeToString as J
fun box(): String {
assertEquals("val test.equalsHashCodeToString.b", (J::b).toString())
assertEquals("var test.equalsHashCodeToString.c", (J::c).toString())
assertTrue(J::b == J::b)
assertFalse(J::c == J::b)
assertTrue(J::b.hashCode() == J::b.hashCode())
assertFalse(J::b.hashCode() == J::c.hashCode())
return "OK"
}
@@ -332,6 +332,7 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({
Reflection.Mapping.class,
Reflection.Properties.class,
})
@RunWith(JUnit3RunnerWithInners.class)
public static class Reflection extends AbstractBlackBoxCodegenTest {
@@ -359,6 +360,21 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod
doTestAgainstJava(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/reflection/properties")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Properties extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInProperties() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/reflection/properties"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("equalsHashCodeToString.kt")
public void testEqualsHashCodeToString() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/reflection/properties/equalsHashCodeToString.kt");
doTestAgainstJava(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/boxAgainstJava/sam")
@@ -24,44 +24,48 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
import java.lang.reflect.Field
import java.lang.reflect.Method
import kotlin.reflect.KotlinReflectionInternalError
abstract class DescriptorBasedProperty(computeDescriptor: () -> PropertyDescriptor) {
protected abstract val container: KCallableContainerImpl
data class PropertyProtoData(
protected abstract val name: String
private data class PropertyProtoData(
val proto: ProtoBuf.Callable,
val nameResolver: NameResolver,
val signature: JvmProtoBuf.JvmPropertySignature
)
protected val descriptor: PropertyDescriptor by ReflectProperties.lazySoft { computeDescriptor() }
protected val descriptor: PropertyDescriptor by ReflectProperties.lazySoft(computeDescriptor)
protected val protoData: PropertyProtoData by ReflectProperties.lazyWeak {
// null if this is a property declared in a foreign (Java) class
private val protoData: PropertyProtoData? by ReflectProperties.lazyWeak @p {(): PropertyProtoData? ->
val property = DescriptorUtils.unwrapFakeOverride(descriptor) as? DeserializedPropertyDescriptor
?: throw KotlinReflectionInternalError("Member property resolved incorrectly: $descriptor")
val proto = property.proto
if (!proto.hasExtension(JvmProtoBuf.propertySignature)) {
throw KotlinReflectionInternalError("Member property lacks JVM signature: $descriptor")
if (property != null) {
val proto = property.proto
if (proto.hasExtension(JvmProtoBuf.propertySignature)) {
return@p PropertyProtoData(proto, property.nameResolver, proto.getExtension(JvmProtoBuf.propertySignature))
}
}
PropertyProtoData(proto, property.nameResolver, proto.getExtension(JvmProtoBuf.propertySignature))
null
}
val field: Field? by ReflectProperties.lazySoft {
open val field: Field? by ReflectProperties.lazySoft {
val proto = protoData
if (!proto.signature.hasField()) null
if (proto == null) container.jClass.getField(name)
else if (!proto.signature.hasField()) null
else container.findFieldBySignature(proto.proto, proto.signature.getField(), proto.nameResolver)
}
open val getter: Method? by ReflectProperties.lazySoft {
val proto = protoData
if (!proto.signature.hasGetter()) null
if (proto == null || !proto.signature.hasGetter()) null
else container.findMethodBySignature(proto.signature.getGetter(), proto.nameResolver)
}
open val setter: Method? by ReflectProperties.lazySoft {
val proto = protoData
if (!proto.signature.hasSetter()) null
if (proto == null || !proto.signature.hasSetter()) null
else container.findMethodBySignature(proto.signature.getSetter(), proto.nameResolver)
}
}
@@ -16,26 +16,18 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
import kotlin.jvm.internal.KotlinClass
import kotlin.reflect.KClass
import kotlin.reflect.KMemberProperty
import kotlin.reflect.KMutableMemberProperty
import kotlin.reflect.KotlinReflectionInternalError
enum class KClassOrigin {
BUILT_IN
KOTLIN
FOREIGN
}
class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), KClass<T> {
// Don't use kotlin.properties.Delegates here because it's a Kotlin class which will invoke KClassImpl() in <clinit>,
// resulting in infinite recursion
val descriptor by ReflectProperties.lazySoft {(): ClassDescriptor ->
val descriptor by ReflectProperties.lazySoft {
val moduleData = jClass.getOrCreateModule()
val classId = RuntimeTypeMapper.mapJvmClassToKotlinClassId(jClass)
@@ -48,36 +40,12 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
override val scope: JetScope get() = descriptor.getDefaultType().getMemberScope()
private val origin by ReflectProperties.lazy {(): KClassOrigin ->
if (jClass.isAnnotationPresent(javaClass<KotlinClass>())) {
KClassOrigin.KOTLIN
}
else {
KClassOrigin.FOREIGN
// TODO: built-in classes
}
}
fun memberProperty(name: String): KMemberProperty<T, *> {
val computeDescriptor = findPropertyDescriptor(name)
if (origin === KClassOrigin.KOTLIN) {
return KMemberPropertyImpl<T, Any>(this, computeDescriptor)
}
else {
return KForeignMemberProperty<T, Any>(name, this)
}
return KMemberPropertyImpl<T, Any>(this, findPropertyDescriptor(name))
}
fun mutableMemberProperty(name: String): KMutableMemberProperty<T, *> {
val computeDescriptor = findPropertyDescriptor(name)
if (origin === KClassOrigin.KOTLIN) {
return KMutableMemberPropertyImpl<T, Any>(this, computeDescriptor)
}
else {
return KMutableForeignMemberProperty<T, Any>(name, this)
}
return KMutableMemberPropertyImpl<T, Any>(this, findPropertyDescriptor(name))
}
override fun equals(other: Any?): Boolean =
@@ -1,72 +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.*
import kotlin.reflect.*
open class KForeignMemberProperty<T : Any, out R>(
override val name: String,
protected val owner: KClassImpl<T>
) : KMemberProperty<T, R>, KPropertyImpl<R> {
override val field: Field = try {
owner.jClass.getField(name)
}
catch (e: NoSuchFieldException) {
throw NoSuchPropertyException(e)
}
override val getter: Method? get() = null
override fun get(receiver: T): R {
try {
return field.get(receiver) as R
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
}
override fun equals(other: Any?): Boolean =
other is KForeignMemberProperty<*, *> && name == other.name && owner == other.owner
override fun hashCode(): Int =
name.hashCode() * 31 + owner.hashCode()
// TODO: include visibility, return type
override fun toString(): String =
"val ${owner.jClass.getName()}.$name"
}
class KMutableForeignMemberProperty<T : Any, R>(
name: String,
owner: KClassImpl<T>
) : KMutableMemberProperty<T, R>, KMutablePropertyImpl<R>, KForeignMemberProperty<T, R>(name, owner) {
override val setter: Method? get() = null
override fun set(receiver: T, value: R) {
try {
field.set(receiver, value)
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
}
override fun toString(): String =
"var ${owner.jClass.getName()}.$name"
}
@@ -16,8 +16,9 @@
package kotlin.reflect.jvm
import kotlin.reflect.*
import kotlin.reflect.jvm.internal.*
import kotlin.reflect.KProperty
import kotlin.reflect.jvm.internal.KMemberPropertyImpl
import kotlin.reflect.jvm.internal.KMutableMemberPropertyImpl
public var <R> KProperty<R>.accessible: Boolean
get() {
@@ -29,7 +30,6 @@ public var <R> KProperty<R>.accessible: Boolean
is KMemberPropertyImpl<*, R> ->
field?.isAccessible() ?: true &&
getter?.isAccessible() ?: true
is KForeignMemberProperty<*, R> -> field.isAccessible()
else -> {
// Non-member properties always have public visibility on JVM, thus accessible has no effect on them
true
@@ -47,8 +47,5 @@ public var <R> KProperty<R>.accessible: Boolean
field?.setAccessible(value)
getter?.setAccessible(value)
}
is KForeignMemberProperty<*, R> -> {
field.setAccessible(value)
}
}
}