Support :: references to Java instance fields in codegen
#KT-1183 In Progress
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user