Support :: references to Java instance fields in codegen

#KT-1183 In Progress
This commit is contained in:
Alexander Udalov
2014-05-30 21:21:03 +04:00
parent 5ab83aad8a
commit a8e1de48b8
9 changed files with 98 additions and 9 deletions
@@ -16,6 +16,21 @@
package kotlin.reflect.jvm.internal
enum class KClassOrigin {
BUILT_IN
KOTLIN
FOREIGN
}
class KClassImpl<out T>(
val jClass: Class<T>
) : KClass<T>
) : KClass<T> {
val origin: KClassOrigin =
if (K_OBJECT_CLASS.isAssignableFrom(jClass)) {
KClassOrigin.KOTLIN
}
else {
KClassOrigin.FOREIGN
// TODO: built-in classes
}
}
@@ -16,17 +16,32 @@
package kotlin.reflect.jvm.internal
import java.lang.reflect.Field
import java.lang.reflect.Method
open class KMemberPropertyImpl<T, out R>(
name: String,
protected val owner: KClassImpl<T>
) : KMemberProperty<T, R>, KPropertyImpl<R>(name) {
// TODO: extract, make lazy (weak?), use our descriptors knowledge, support Java fields
protected val getter: Method = owner.jClass.getMethod(getterName(name))
protected val field: Field? =
if (owner.origin == KClassOrigin.FOREIGN) {
owner.jClass.getField(name)
}
else null
// TODO: extract, make lazy (weak?), use our descriptors knowledge
protected val getter: Method? =
if (owner.origin == KClassOrigin.KOTLIN) {
owner.jClass.getMethod(getterName(name))
}
else null
// TODO: built-in classes
override fun get(receiver: T): R {
return getter(receiver) as R
if (getter != null) {
return getter!!(receiver) as R
}
return field!!.get(receiver) as R
}
}
@@ -34,9 +49,17 @@ class KMutableMemberPropertyImpl<T, R>(
name: String,
owner: KClassImpl<T>
) : KMutableMemberProperty<T, R>, KMemberPropertyImpl<T, R>(name, owner) {
private val setter = owner.jClass.getMethod(setterName(name), getter.getReturnType()!!)
private val setter: Method? =
if (owner.origin == KClassOrigin.KOTLIN) {
owner.jClass.getMethod(setterName(name), getter!!.getReturnType()!!)
}
else null
override fun set(receiver: T, value: R) {
setter.invoke(receiver, value)
if (setter != null) {
setter!!(receiver, value)
return
}
field!!.set(receiver, value)
}
}
@@ -16,6 +16,8 @@
package kotlin.reflect.jvm.internal
import java.util.concurrent.ConcurrentHashMap
// TODO: use stdlib?
suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
private fun String.capitalizeWithJavaBeanConvention(): String {
@@ -32,13 +34,24 @@ private fun getterName(propertyName: String): String = "get" + propertyName.capi
private fun setterName(propertyName: String): String = "set" + propertyName.capitalizeWithJavaBeanConvention()
// TODO: should use weak references
private val foreignKClasses: MutableMap<Class<*>, KClassImpl<*>> = ConcurrentHashMap()
fun <T> foreignKotlinClass(jClass: Class<T>): KClassImpl<T> {
val cached = foreignKClasses[jClass] as? KClassImpl<T>
if (cached != null) return cached
val result = KClassImpl<T>(jClass)
foreignKClasses.put(jClass, result)
return result
}
private val K_OBJECT_CLASS = Class.forName("kotlin.jvm.internal.KObject")
// TODO
fun <T> kotlinClass(jClass: Class<T>): KClassImpl<T> {
if (K_OBJECT_CLASS.isAssignableFrom(jClass)) {
val field = jClass.getDeclaredField("\$kotlinClass")
return field.get(null) as KClassImpl<T>
}
throw UnsupportedOperationException("Unsupported class: $jClass")
// TODO: built-in classes
return foreignKotlinClass(jClass)
}