Implement getter and setter for KPropertyProxy

This commit is contained in:
Ivan Kylchik
2020-09-21 21:48:33 +03:00
committed by TeamCityServer
parent f89b75e387
commit 64d5cea337
9 changed files with 191 additions and 101 deletions
@@ -888,8 +888,8 @@ class IrInterpreter(val irBuiltIns: IrBuiltIns, private val bodyMap: Map<IdSigna
private fun interpretPropertyReference(propertyReference: IrPropertyReference): ExecutionResult {
val dispatchReceiver = propertyReference.dispatchReceiver?.interpret()?.check { return it }?.let { stack.popReturnValue() }
val extensionReceiver = propertyReference.extensionReceiver?.interpret()?.check { return it }?.let { stack.popReturnValue() }
val propertyState = KPropertyState(propertyReference, dispatchReceiver, extensionReceiver)
// it is impossible to get KProperty2 through ::, so extension receiver is always null
val propertyState = KPropertyState(propertyReference, dispatchReceiver)
stack.pushReturnValue(propertyState)
return Next
}
@@ -6,17 +6,16 @@
package org.jetbrains.kotlin.ir.interpreter.proxy.reflection
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState
import org.jetbrains.kotlin.ir.types.IrType
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.KVisibility
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
import kotlin.reflect.*
internal abstract class AbstractKPropertyProxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : ReflectionProxy, KProperty<Any?> {
protected val propertyType: IrType
get() = state.property.getter!!.returnType
@@ -36,12 +35,76 @@ internal abstract class AbstractKPropertyProxy(
get() = state.property.name.asString()
override val annotations: List<Annotation>
get() = TODO("Not yet implemented")
get() = TODO("not implemented")
override val parameters: List<KParameter>
get() = state.getParameters(interpreter)
override val returnType: KType
get() = state.getReturnType(interpreter)
override val typeParameters: List<KTypeParameter>
get() = listOf()
override val visibility: KVisibility?
get() = state.property.visibility.toKVisibility()
override fun call(vararg args: Any?): Any? = getter.call(*args)
override fun callBy(args: Map<KParameter, Any?>): Any? = getter.callBy(args)
protected fun checkArguments(expected: Int, actual: Int) {
if (expected != actual) {
throw IllegalArgumentException("Callable expects $expected arguments, but $actual were provided.")
}
}
abstract inner class Getter(val getter: IrSimpleFunction) : KProperty.Getter<Any?> {
override val property: KProperty<Any?> = this@AbstractKPropertyProxy
override val name: String = "<get-${this@AbstractKPropertyProxy.name.capitalizeAsciiOnly()}>"
override val annotations: List<Annotation>
get() = this@AbstractKPropertyProxy.annotations
override val parameters: List<KParameter>
get() = this@AbstractKPropertyProxy.parameters
override val returnType: KType
get() = this@AbstractKPropertyProxy.returnType
override val typeParameters: List<KTypeParameter>
get() = this@AbstractKPropertyProxy.typeParameters
override val isInline: Boolean = getter.isInline
override val isExternal: Boolean = getter.isExternal
override val isOperator: Boolean = getter.isOperator
override val isInfix: Boolean = getter.isInfix
override val isSuspend: Boolean = getter.isSuspend
override val visibility: KVisibility? = getter.visibility.toKVisibility()
override val isFinal: Boolean = getter.modality == Modality.FINAL
override val isOpen: Boolean = getter.modality == Modality.OPEN
override val isAbstract: Boolean = getter.modality == Modality.ABSTRACT
}
abstract inner class Setter(val setter: IrSimpleFunction) : KMutableProperty.Setter<Any?> {
override val property: KProperty<Any?> = this@AbstractKPropertyProxy
override val name: String = "<set-${this@AbstractKPropertyProxy.name.capitalizeAsciiOnly()}>"
override val annotations: List<Annotation>
get() = this@AbstractKPropertyProxy.annotations
override val parameters: List<KParameter>
get() = this@AbstractKPropertyProxy.parameters
override val returnType: KType
get() = this@AbstractKPropertyProxy.returnType
override val typeParameters: List<KTypeParameter>
get() = this@AbstractKPropertyProxy.typeParameters
override val isInline: Boolean = setter.isInline
override val isExternal: Boolean = setter.isExternal
override val isOperator: Boolean = setter.isOperator
override val isInfix: Boolean = setter.isInfix
override val isSuspend: Boolean = setter.isSuspend
override val visibility: KVisibility? = setter.visibility.toKVisibility()
override val isFinal: Boolean = setter.modality == Modality.FINAL
override val isOpen: Boolean = setter.modality == Modality.OPEN
override val isAbstract: Boolean = setter.modality == Modality.ABSTRACT
}
override fun equals(other: Any?): Boolean {
if (other !is AbstractKPropertyProxy) return false
return state == other.state
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState
import org.jetbrains.kotlin.ir.interpreter.toState
import org.jetbrains.kotlin.ir.util.isSuspend
import kotlin.reflect.*
@@ -43,6 +42,7 @@ internal class KFunctionProxy(
get() = state.getTypeParameters(interpreter)
override fun call(vararg args: Any?): Any? {
// TODO check arity
var index = 0
val dispatchReceiver = state.irFunction.dispatchReceiverParameter?.let { Variable(it.symbol, args[index++].toState(it.type)) }
val extensionReceiver = state.irFunction.extensionReceiverParameter?.let { Variable(it.symbol, args[index++].toState(it.type)) }
@@ -10,49 +10,50 @@ import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState
import org.jetbrains.kotlin.ir.interpreter.state.State
import org.jetbrains.kotlin.ir.interpreter.toState
import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KParameter
import kotlin.reflect.KProperty0
import kotlin.reflect.KTypeParameter
import kotlin.reflect.*
internal open class KProperty0Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : AbstractKPropertyProxy(state, interpreter), KProperty0<Any?> {
override val getter: KProperty0.Getter<Any?>
get() = object : Getter(state.property.getter!!), KProperty0.Getter<Any?> {
override fun invoke(): Any? = call()
override val getter: KProperty0.Getter<State>
get() = TODO("Not yet implemented")
override val parameters: List<KParameter>
get() = TODO("Not yet implemented")
override val typeParameters: List<KTypeParameter>
get() = TODO("Not yet implemented")
override fun call(vararg args: Any?): Any? {
checkArguments(0, args.size)
return state.dispatchReceiver!!.getState(state.property.symbol)!!
}
override fun call(vararg args: Any?): Any? {
TODO("Not yet implemented")
}
override fun callBy(args: Map<KParameter, Any?>): Any? {
TODO("Not yet implemented")
}
}
override fun callBy(args: Map<KParameter, Any?>): Any? {
TODO("Not yet implemented")
}
override fun get(): Any? {
return state.dispatchReceiver!!.getState(state.property.symbol)!!
}
override fun get(): Any? = getter.call()
override fun getDelegate(): Any? {
TODO("Not yet implemented")
}
override fun invoke(): Any? = get()
override fun invoke(): Any? = getter.call()
}
internal class KMutableProperty0Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : KProperty0Proxy(state, interpreter), KMutableProperty0<Any?> {
override val setter: KMutableProperty0.Setter<Any?> =
object : Setter(state.property.setter!!), KMutableProperty0.Setter<Any?> {
override fun invoke(p1: Any?) = call(p1)
override val setter: KMutableProperty0.Setter<Any?>
get() = TODO("Not yet implemented")
override fun call(vararg args: Any?) {
checkArguments(1, args.size)
state.dispatchReceiver!!.setField(Variable(state.property.symbol, args.single().toState(propertyType)))
}
override fun set(value: Any?) {
state.dispatchReceiver!!.setField(Variable(state.property.symbol, value.toState(propertyType)))
}
override fun callBy(args: Map<KParameter, Any?>) {
TODO("Not yet implemented")
}
}
override fun set(value: Any?) = setter.call(value)
}
@@ -11,49 +11,53 @@ import org.jetbrains.kotlin.ir.interpreter.proxy.wrap
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState
import org.jetbrains.kotlin.ir.interpreter.toState
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KParameter
import kotlin.reflect.KProperty1
import kotlin.reflect.KTypeParameter
import kotlin.reflect.*
internal open class KProperty1Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : AbstractKPropertyProxy(state, interpreter), KProperty1<Proxy, Any?> {
override val getter: KProperty1.Getter<Proxy, Any?>
get() = TODO("Not yet implemented")
override val parameters: List<KParameter>
get() = TODO("Not yet implemented")
override val typeParameters: List<KTypeParameter>
get() = TODO("Not yet implemented")
get() = object : Getter(state.property.getter!!), KProperty1.Getter<Proxy, Any?> {
override fun invoke(p1: Proxy): Any? = call(p1)
override fun call(vararg args: Any?): Any? {
TODO("Not yet implemented")
}
override fun call(vararg args: Any?): Any? {
checkArguments(1, args.size)
val receiver = args.single() as Proxy
return receiver.state.getState(state.property.symbol)!!.wrap(interpreter)
}
override fun callBy(args: Map<KParameter, Any?>): Any? {
TODO("Not yet implemented")
}
override fun callBy(args: Map<KParameter, Any?>): Any? {
TODO("Not yet implemented")
}
}
override fun get(receiver: Proxy): Any? {
return receiver.state.getState(state.property.symbol)!!.wrap(interpreter)
}
override fun get(receiver: Proxy): Any? = getter.call(receiver)
override fun getDelegate(receiver: Proxy): Any? {
TODO("Not yet implemented")
}
override fun invoke(p1: Proxy): Any? = get(p1)
override fun invoke(p1: Proxy): Any? = getter.call(p1)
}
internal class KMutableProperty1Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : KProperty1Proxy(state, interpreter), KMutableProperty1<Proxy, Any?> {
override val setter: KMutableProperty1.Setter<Proxy, Any?> =
object : Setter(state.property.setter!!), KMutableProperty1.Setter<Proxy, Any?> {
override fun invoke(p1: Proxy, p2: Any?) = call(p1, p2)
override val setter: KMutableProperty1.Setter<Proxy, Any?>
get() = TODO("Not yet implemented")
override fun call(vararg args: Any?) {
checkArguments(2, args.size)
val receiver = args[0] as Proxy
val value = args[1]
receiver.state.setField(Variable(state.property.symbol, value.toState(propertyType)))
}
override fun set(receiver: Proxy, value: Any?) {
receiver.state.setField(Variable(state.property.symbol, value.toState(propertyType)))
}
override fun callBy(args: Map<KParameter, Any?>) {
TODO("Not yet implemented")
}
}
override fun set(receiver: Proxy, value: Any?) = setter.call(receiver, value)
}
@@ -6,51 +6,58 @@
package org.jetbrains.kotlin.ir.interpreter.proxy.reflection
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState
import kotlin.reflect.KMutableProperty2
import kotlin.reflect.KParameter
import kotlin.reflect.KProperty2
import kotlin.reflect.KTypeParameter
import org.jetbrains.kotlin.ir.interpreter.toState
import kotlin.reflect.*
internal open class KProperty2Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : AbstractKPropertyProxy(state, interpreter), KProperty2<Proxy, Proxy, Any?> {
) : AbstractKPropertyProxy(state, interpreter), KProperty2<Any?, Any?, Any?> {
override val getter: KProperty2.Getter<Any?, Any?, Any?> =
object : Getter(state.property.getter!!), KProperty2.Getter<Any?, Any?, Any?> {
override fun invoke(p1: Any?, p2: Any?): Any? = call(p1, p2)
override val getter: KProperty2.Getter<Proxy, Proxy, Any?>
get() = TODO("Not yet implemented")
override val parameters: List<KParameter>
get() = TODO("Not yet implemented")
override val typeParameters: List<KTypeParameter>
get() = TODO("Not yet implemented")
override fun call(vararg args: Any?): Any? {
checkArguments(2, args.size)
val dispatch = Variable(getter.dispatchReceiverParameter!!.symbol, args[0].toState(getter.dispatchReceiverParameter!!.type))
val extension = Variable(getter.extensionReceiverParameter!!.symbol, args[1].toState(getter.extensionReceiverParameter!!.type))
return with(this@KProperty2Proxy.interpreter) { getter.interpret(listOf(dispatch, extension)) }
}
override fun call(vararg args: Any?): Any? {
override fun callBy(args: Map<KParameter, Any?>): Any? {
TODO("Not yet implemented")
}
}
override fun get(receiver1: Any?, receiver2: Any?): Any? = getter.call(receiver1, receiver2)
override fun getDelegate(receiver1: Any?, receiver2: Any?): Any? {
TODO("Not yet implemented")
}
override fun callBy(args: Map<KParameter, Any?>): Any? {
TODO("Not yet implemented")
}
override fun get(receiver1: Proxy, receiver2: Proxy): Any? {
TODO("Not yet implemented")
}
override fun getDelegate(receiver1: Proxy, receiver2: Proxy): Any? {
TODO("Not yet implemented")
}
override fun invoke(p1: Proxy, p2: Proxy): Any? = get(p1, p2)
override fun invoke(p1: Any?, p2: Any?): Any? = getter.call(p1, p2)
}
internal class KMutableProperty2Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : KProperty2Proxy(state, interpreter), KMutableProperty2<Proxy, Proxy, Any?> {
) : KProperty2Proxy(state, interpreter), KMutableProperty2<Any?, Any?, Any?> {
override val setter: KMutableProperty2.Setter<Any?, Any?, Any?>
get() = object : Setter(state.property.setter!!), KMutableProperty2.Setter<Any?, Any?, Any?> {
override fun invoke(p1: Any?, p2: Any?, p3: Any?) = call(p1, p2, p3)
override val setter: KMutableProperty2.Setter<Proxy, Proxy, Any?>
get() = TODO("Not yet implemented")
override fun call(vararg args: Any?) {
checkArguments(3, args.size)
val receiver1 = args[0]
val receiver2 = args[1]
val value = args[2]
TODO("Not yet implemented, receiver1 = $receiver1, receiver2 = $receiver2, value = $value")
}
override fun set(receiver1: Proxy, receiver2: Proxy, value: Any?) {
TODO("Not yet implemented")
}
override fun callBy(args: Map<KParameter, Any?>) {
TODO("Not yet implemented")
}
}
override fun set(receiver1: Any?, receiver2: Any?, value: Any?) = setter.call(receiver1, receiver2, value)
}
@@ -144,7 +144,10 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex
notNullType.isPrimitiveType() || notNullType.isString() -> getPrimitiveClass(notNullType, asObject)!!
notNullType.isArray() -> {
val argumentFqName = (this as IrSimpleType).arguments.single().typeOrNull?.classOrNull?.owner?.fqNameWhenAvailable
argumentFqName?.let { Class.forName("[L$it;") } ?: Array<Any?>::class.java
when {
argumentFqName != null && argumentFqName.asString() != "kotlin.Any" -> argumentFqName.let { Class.forName("[L$it;") }
else -> Array<Any?>::class.java
}
}
notNullType.isNothing() -> Nothing::class.java
notNullType.isAny() -> Any::class.java
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.ir.interpreter.state.reflection
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy
import kotlin.reflect.KParameter
@@ -51,6 +48,8 @@ internal class KParameterState(
append(" of ")
when (val parent = irParameter.parent) {
is IrSimpleFunction -> parent.correspondingPropertySymbol?.owner?.let { append(renderProperty(it)) }
?: append(renderFunction(parent))
is IrFunction -> append(renderFunction(parent))
is IrProperty -> append(renderProperty(parent))
else -> TODO()
@@ -9,20 +9,35 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KParameterProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy
import org.jetbrains.kotlin.ir.interpreter.state.State
import org.jetbrains.kotlin.ir.types.classOrNull
import kotlin.reflect.KParameter
import kotlin.reflect.KType
internal class KPropertyState(
val property: IrProperty, override val irClass: IrClass, val dispatchReceiver: State? = null, val extensionReceiver: State? = null
val property: IrProperty, override val irClass: IrClass, val dispatchReceiver: State? = null
) : ReflectionState() {
constructor(propertyReference: IrPropertyReference, dispatchReceiver: State?, extensionReceiver: State?)
: this(propertyReference.symbol.owner, propertyReference.type.classOrNull!!.owner, dispatchReceiver, extensionReceiver)
constructor(propertyReference: IrPropertyReference, dispatchReceiver: State?)
: this(propertyReference.symbol.owner, propertyReference.type.classOrNull!!.owner, dispatchReceiver)
private var _parameters: List<KParameter>? = null
private var _returnType: KType? = null
fun getParameters(interpreter: IrInterpreter): List<KParameter> {
if (_parameters != null) return _parameters!!
val kParameterIrClass = irClass.getIrClassOfReflectionFromList("parameters")
var index = 0
val instanceParameter = property.getter?.dispatchReceiverParameter?.takeIf { dispatchReceiver == null }
?.let { KParameterProxy(KParameterState(kParameterIrClass, it, index++, KParameter.Kind.INSTANCE), interpreter) }
val extensionParameter = property.getter?.extensionReceiverParameter
?.let { KParameterProxy(KParameterState(kParameterIrClass, it, index++, KParameter.Kind.EXTENSION_RECEIVER), interpreter) }
_parameters = listOfNotNull(instanceParameter, extensionParameter)
return _parameters!!
}
fun getReturnType(interpreter: IrInterpreter): KType {
if (_returnType != null) return _returnType!!
val kTypeIrClass = irClass.getIrClassOfReflection("returnType")
@@ -50,7 +65,6 @@ internal class KPropertyState(
if (property != other.property) return false
if (dispatchReceiver != other.dispatchReceiver) return false
if (extensionReceiver != other.extensionReceiver) return false
return true
}
@@ -58,7 +72,6 @@ internal class KPropertyState(
override fun hashCode(): Int {
var result = property.hashCode()
result = 31 * result + (dispatchReceiver?.hashCode() ?: 0)
result = 31 * result + (extensionReceiver?.hashCode() ?: 0)
return result
}