Pass KProperty instances to property delegates

Inherit KProperty from PropertyMetadata, cache corresponding KProperty objects
instead of PropertyMetadataImpl objects, add support for properties with 2
receivers
This commit is contained in:
Alexander Udalov
2015-10-12 12:11:36 +03:00
parent 4614e74e3f
commit 3c74f48f91
14 changed files with 128 additions and 129 deletions
@@ -55,7 +55,6 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
import org.jetbrains.kotlin.jvm.bindingContextSlices.BindingContextSlicesPackage;
import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
@@ -2774,30 +2773,31 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
if (variableDescriptor != null) {
return generatePropertyReference(expression, variableDescriptor, resolvedCall);
return generatePropertyReference(expression, variableDescriptor, (VariableDescriptor) resolvedCall.getResultingDescriptor(),
resolvedCall.getDispatchReceiver());
}
throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText());
}
@NotNull
private StackValue generatePropertyReference(
@NotNull JetCallableReferenceExpression expression,
public StackValue generatePropertyReference(
@NotNull JetElement element,
@NotNull VariableDescriptor variableDescriptor,
@NotNull ResolvedCall<?> resolvedCall
@NotNull VariableDescriptor target,
@NotNull ReceiverValue dispatchReceiver
) {
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
ClassBuilder classBuilder = state.getFactory().newVisitor(
OtherOrigin(expression),
OtherOrigin(element),
typeMapper.mapClass(classDescriptor),
expression.getContainingFile()
element.getContainingFile()
);
@SuppressWarnings("unchecked")
PropertyReferenceCodegen codegen = new PropertyReferenceCodegen(
state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION),
expression, classBuilder, classDescriptor, (ResolvedCall<VariableDescriptor>) resolvedCall
element, classBuilder, classDescriptor, target, dispatchReceiver
);
codegen.generate();
@@ -43,6 +43,8 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.kotlin.resolve.source.SourcePackage;
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
import org.jetbrains.kotlin.storage.NotNullLazyValue;
@@ -59,7 +61,6 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.calculateInnerClassAccessFlag
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.PROPERTY_METADATA_IMPL_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.PROPERTY_METADATA_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.OtherOrigin;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
@@ -467,7 +468,7 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
}
if (delegatedProperties.isEmpty()) return;
v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.PROPERTY_METADATA_ARRAY_NAME,
v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
"[" + PROPERTY_METADATA_TYPE, null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
@@ -481,14 +482,21 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
iv.dup();
iv.iconst(i);
iv.anew(PROPERTY_METADATA_IMPL_TYPE);
iv.dup();
iv.visitLdcInsn(property.getName().asString());
iv.invokespecial(PROPERTY_METADATA_IMPL_TYPE.getInternalName(), "<init>", "(Ljava/lang/String;)V", false);
iv.astore(PROPERTY_METADATA_IMPL_TYPE);
ReceiverParameterDescriptor dispatchReceiver = property.getDispatchReceiverParameter();
//noinspection ConstantConditions
StackValue value = createOrGetClInitCodegen().generatePropertyReference(
delegatedProperties.get(i).getDelegate(), property, property,
dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : ReceiverValue.NO_RECEIVER
);
value.put(PROPERTY_METADATA_TYPE, iv);
iv.astore(PROPERTY_METADATA_TYPE);
}
iv.putstatic(thisAsmType.getInternalName(), JvmAbi.PROPERTY_METADATA_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE);
}
public String getClassName() {
@@ -520,7 +520,7 @@ public class PropertyCodegen {
@Override
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
Field array = StackValue
.field(Type.getType("[" + PROPERTY_METADATA_TYPE), owner, JvmAbi.PROPERTY_METADATA_ARRAY_NAME, true,
.field(Type.getType("[" + PROPERTY_METADATA_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true,
StackValue.none());
StackValue.arrayElement(PROPERTY_METADATA_TYPE, array, StackValue.constant(indexInPropertyMetadataArray, Type.INT_TYPE)).put(type, v);
}
@@ -25,14 +25,14 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetCallableReferenceExpression
import org.jetbrains.kotlin.psi.JetElement
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ScriptReceiver
import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_FINAL
@@ -47,14 +47,29 @@ public class PropertyReferenceCodegen(
state: GenerationState,
parentCodegen: MemberCodegen<*>,
context: ClassContext,
expression: JetCallableReferenceExpression,
expression: JetElement,
classBuilder: ClassBuilder,
private val classDescriptor: ClassDescriptor,
private val resolvedCall: ResolvedCall<VariableDescriptor>
) : MemberCodegen<JetCallableReferenceExpression>(state, parentCodegen, context, expression, classBuilder) {
private val target = resolvedCall.getResultingDescriptor()
private val target: VariableDescriptor,
dispatchReceiver: ReceiverValue
) : MemberCodegen<JetElement>(state, parentCodegen, context, expression, classBuilder) {
private val asmType = typeMapper.mapClass(classDescriptor)
private val dispatchReceiverType =
when {
dispatchReceiver is ScriptReceiver -> {
// TODO: fix receiver for scripts, see ScriptReceiver#getType
dispatchReceiver.declarationDescriptor.classDescriptor.defaultType
}
dispatchReceiver.exists() -> dispatchReceiver.type
else -> null
}
private val extensionReceiverType = target.extensionReceiverParameter?.type
private val receiverCount =
(if (dispatchReceiverType != null) 1 else 0) + (if (extensionReceiverType != null) 1 else 0)
// e.g. MutablePropertyReference0
private val superAsmType = typeMapper.mapClass(classDescriptor.getSuperClassNotAny().sure { "No super class for $classDescriptor" })
@@ -62,16 +77,17 @@ public class PropertyReferenceCodegen(
private val wrapperMethod: Method
init {
val hasReceiver = target.getDispatchReceiverParameter() != null || target.getExtensionReceiverParameter() != null
val isMutable = target.isVar()
wrapperMethod = when {
hasReceiver -> when {
isMutable -> method("mutableProperty1", K_MUTABLE_PROPERTY1_TYPE, MUTABLE_PROPERTY_REFERENCE1)
wrapperMethod = when (receiverCount) {
2 -> when {
target.isVar -> method("mutableProperty2", K_MUTABLE_PROPERTY2_TYPE, MUTABLE_PROPERTY_REFERENCE2)
else -> method("property2", K_PROPERTY2_TYPE, PROPERTY_REFERENCE2)
}
1 -> when {
target.isVar -> method("mutableProperty1", K_MUTABLE_PROPERTY1_TYPE, MUTABLE_PROPERTY_REFERENCE1)
else -> method("property1", K_PROPERTY1_TYPE, PROPERTY_REFERENCE1)
}
else -> when {
isMutable -> method("mutableProperty0", K_MUTABLE_PROPERTY0_TYPE, MUTABLE_PROPERTY_REFERENCE0)
target.isVar -> method("mutableProperty0", K_MUTABLE_PROPERTY0_TYPE, MUTABLE_PROPERTY_REFERENCE0)
else -> method("property0", K_PROPERTY0_TYPE, PROPERTY_REFERENCE0)
}
}
@@ -127,19 +143,6 @@ public class PropertyReferenceCodegen(
}
private fun generateAccessors() {
val dispatchReceiver = resolvedCall.getDispatchReceiver()
val extensionReceiver = resolvedCall.getExtensionReceiver()
val receiverType =
when {
dispatchReceiver is ScriptReceiver -> {
// TODO: fix receiver for scripts, see ScriptReceiver#getType
dispatchReceiver.getDeclarationDescriptor().getClassDescriptor().getDefaultType()
}
dispatchReceiver.exists() -> dispatchReceiver.getType()
extensionReceiver.exists() -> extensionReceiver.getType()
else -> null
}
fun generateAccessor(method: Method, accessorBody: InstructionAdapter.(StackValue) -> Unit) {
generateMethod("property reference $method", ACC_PUBLIC, method) {
// Note: this descriptor is an inaccurate representation of the get/set method. In particular, it has incorrect
@@ -160,26 +163,27 @@ public class PropertyReferenceCodegen(
StackValue.singleton(containingObject, typeMapper).put(typeMapper.mapClass(containingObject), this)
}
val receiver =
if (receiverType != null) StackValue.coercion(StackValue.local(1, OBJECT_TYPE), typeMapper.mapType(receiverType))
else StackValue.none()
val value = fakeCodegen.intermediateValueForProperty(target as PropertyDescriptor, false, null, receiver)
for ((index, type) in listOf(dispatchReceiverType, extensionReceiverType).filterNotNull().withIndex()) {
StackValue.local(index + 1, OBJECT_TYPE).put(typeMapper.mapType(type), this)
}
val value = fakeCodegen.intermediateValueForProperty(target as PropertyDescriptor, false, null, StackValue.none())
accessorBody(value)
}
}
val getterParameters = if (receiverType != null) arrayOf(OBJECT_TYPE) else emptyArray()
val getterParameters = (1..receiverCount).map { OBJECT_TYPE }.toTypedArray()
generateAccessor(method("get", OBJECT_TYPE, *getterParameters)) { value ->
value.put(OBJECT_TYPE, this)
}
if (!target.isVar()) return
if (!target.isVar) return
val setterParameters = (getterParameters + arrayOf(OBJECT_TYPE))
generateAccessor(method("set", Type.VOID_TYPE, *setterParameters)) { value ->
// Hard-coded 1 or 2 is safe here because there's only java/lang/Object in the signature, no double/long parameters
value.store(StackValue.local(if (receiverType != null) 2 else 1, OBJECT_TYPE), this)
// Number of receivers (not size) is safe here because there's only java/lang/Object in the signature, no double/long parameters
value.store(StackValue.local(receiverCount + 1, OBJECT_TYPE), this)
}
}
@@ -140,29 +140,16 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
return container;
}
private String inventAnonymousClassName(JetElement declaration) {
@NotNull
private String inventAnonymousClassName() {
String top = peekFromStack(nameStack);
Integer cnt = anonymousSubclassesCount.get(top);
if (cnt == null) {
cnt = 0;
}
String name = top + "$" + (cnt + 1);
ClassDescriptor descriptor = bindingContext.get(CLASS, declaration);
if (descriptor == null) {
if (declaration instanceof JetFunctionLiteralExpression ||
declaration instanceof JetNamedFunction ||
declaration instanceof JetObjectLiteralExpression ||
declaration instanceof JetCallableReferenceExpression) {
}
else {
throw new IllegalStateException(
"Class-less declaration which is not JetFunctionLiteralExpression|JetNamedFunction|JetObjectLiteralExpression|JetCallableReferenceExpression : " +
declaration.getClass().getName());
}
}
anonymousSubclassesCount.put(top, cnt + 1);
return name;
return top + "$" + (cnt + 1);
}
@Override
@@ -261,7 +248,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
return;
}
String name = inventAnonymousClassName(object);
String name = inventAnonymousClassName();
recordClosure(classDescriptor, name);
JetDelegationSpecifierList delegationSpecifierList = object.getDelegationSpecifierList();
@@ -287,7 +274,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
// working around a problem with shallow analysis
if (functionDescriptor == null) return;
String name = inventAnonymousClassName(expression);
String name = inventAnonymousClassName();
Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor);
ClassDescriptor classDescriptor = recordClassForCallable(functionLiteral, functionDescriptor, supertypes, name);
recordClosure(classDescriptor, name);
@@ -324,7 +311,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
return;
}
String name = inventAnonymousClassName(expression);
String name = inventAnonymousClassName();
ClassDescriptor classDescriptor = recordClassForCallable(expression, callableDescriptor, supertypes, name);
recordClosure(classDescriptor, name);
@@ -342,17 +329,27 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
@Override
public void visitProperty(@NotNull JetProperty property) {
DeclarationDescriptor propertyDescriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property);
DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property);
// working around a problem with shallow analysis
if (propertyDescriptor == null) return;
if (descriptor == null) return;
String nameForClassOrPackageMember = getNameForClassOrPackageMember(propertyDescriptor);
String nameForClassOrPackageMember = getNameForClassOrPackageMember(descriptor);
if (nameForClassOrPackageMember != null) {
nameStack.push(nameForClassOrPackageMember);
}
else {
nameStack.push(peekFromStack(nameStack) + '$' + safeIdentifier(property.getNameAsSafeName()).asString());
}
JetPropertyDelegate delegate = property.getDelegate();
if (delegate != null && descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
String name = inventAnonymousClassName();
JetType supertype = runtimeTypes.getSupertypeForPropertyReference(propertyDescriptor);
ClassDescriptor classDescriptor = recordClassForCallable(delegate, propertyDescriptor, Collections.singleton(supertype), name);
recordClosure(classDescriptor, name);
}
super.visitProperty(property);
nameStack.pop();
}
@@ -370,7 +367,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
nameStack.pop();
}
else {
String name = inventAnonymousClassName(function);
String name = inventAnonymousClassName();
Collection<JetType> supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor);
ClassDescriptor classDescriptor = recordClassForCallable(function, functionDescriptor, supertypes, name);
recordClosure(classDescriptor, name);
@@ -32,14 +32,15 @@ public class AsmTypes {
public static final Type UNIT_TYPE = Type.getObjectType("kotlin/Unit");
public static final Type PROPERTY_METADATA_TYPE = Type.getObjectType("kotlin/PropertyMetadata");
public static final Type PROPERTY_METADATA_IMPL_TYPE = Type.getObjectType("kotlin/PropertyMetadataImpl");
public static final Type LAMBDA = Type.getObjectType("kotlin/jvm/internal/Lambda");
public static final Type FUNCTION_REFERENCE = Type.getObjectType("kotlin/jvm/internal/FunctionReference");
public static final Type PROPERTY_REFERENCE0 = Type.getObjectType("kotlin/jvm/internal/PropertyReference0");
public static final Type PROPERTY_REFERENCE1 = Type.getObjectType("kotlin/jvm/internal/PropertyReference1");
public static final Type PROPERTY_REFERENCE2 = Type.getObjectType("kotlin/jvm/internal/PropertyReference2");
public static final Type MUTABLE_PROPERTY_REFERENCE0 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference0");
public static final Type MUTABLE_PROPERTY_REFERENCE1 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference1");
public static final Type MUTABLE_PROPERTY_REFERENCE2 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference2");
public static final Type K_CLASS_TYPE = reflect("KClass");
public static final Type K_CLASS_ARRAY_TYPE = Type.getObjectType("[" + K_CLASS_TYPE.getDescriptor());
@@ -49,8 +50,10 @@ public class AsmTypes {
public static final Type K_PROPERTY0_TYPE = reflect("KProperty0");
public static final Type K_PROPERTY1_TYPE = reflect("KProperty1");
public static final Type K_PROPERTY2_TYPE = reflect("KProperty2");
public static final Type K_MUTABLE_PROPERTY0_TYPE = reflect("KMutableProperty0");
public static final Type K_MUTABLE_PROPERTY1_TYPE = reflect("KMutableProperty1");
public static final Type K_MUTABLE_PROPERTY2_TYPE = reflect("KMutableProperty2");
public static final String REFLECTION = "kotlin/jvm/internal/Reflection";
@@ -1,36 +0,0 @@
import java.util.HashSet
class A {
val foo: String by O
val Int.foo: String by O
fun foo42() = 42.foo
}
val foo: String by O
val Int.foo: String by O
object O {
val metadatas = HashSet<PropertyMetadata>()
fun getValue(t: Any?, p: PropertyMetadata): String {
metadatas.add(p)
return ""
}
}
fun box(): String {
A().foo
A().foo42()
foo
42.foo
if (O.metadatas.size != 1)
return "Too many different PropertyMetadata instances: ${O.metadatas}"
val m = O.metadatas.iterator().next()
if (m.toString() != "PropertyMetadata(name=foo)")
return "Wrong toString(): $m"
return "OK"
}
@@ -4,8 +4,8 @@ operator fun Any.getValue(x: Any?, y: Any): Any = null!!
class <!CONFLICTING_JVM_DECLARATIONS!>C<!> {
val x by 1
<!CONFLICTING_JVM_DECLARATIONS!>val `$propertyMetadata`: Array<PropertyMetadata><!> = null!!
<!CONFLICTING_JVM_DECLARATIONS!>val `$delegatedProperties`: Array<PropertyMetadata><!> = null!!
}
val x by 1
<!CONFLICTING_JVM_DECLARATIONS!>val `$propertyMetadata`: Array<PropertyMetadata><!> = null!!
<!CONFLICTING_JVM_DECLARATIONS!>val `$delegatedProperties`: Array<PropertyMetadata><!> = null!!
@@ -1,12 +1,12 @@
package
public val `$propertyMetadata`: kotlin.Array<kotlin.PropertyMetadata>
public val `$delegatedProperties`: kotlin.Array<kotlin.PropertyMetadata>
public val x: kotlin.Any
public operator fun kotlin.Any.getValue(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any): kotlin.Any
public final class C {
public constructor C()
public final val `$propertyMetadata`: kotlin.Array<kotlin.PropertyMetadata>
public final val `$delegatedProperties`: kotlin.Array<kotlin.PropertyMetadata>
public final val x: kotlin.Any
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
@@ -2935,12 +2935,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("propertyMetadataEqualsHashCodeToString.kt")
public void testPropertyMetadataEqualsHashCodeToString() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/propertyMetadataEqualsHashCodeToString.kt");
doTest(fileName);
}
@TestMetadata("propertyMetadataShouldBeCached.kt")
public void testPropertyMetadataShouldBeCached() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/propertyMetadataShouldBeCached.kt");
@@ -24,7 +24,7 @@ package kotlin.reflect
*
* @param R the type of the property.
*/
public interface KProperty<out R> : KCallable<R> {
public interface KProperty<out R> : KCallable<R>, PropertyMetadata {
/** The getter of this property, used to obtain the value of the property. */
public val getter: Getter<R>
@@ -47,7 +47,7 @@ public final class JvmAbi {
private static final String SET_PREFIX = "set";
public static final String DELEGATED_PROPERTY_NAME_SUFFIX = "$delegate";
public static final String PROPERTY_METADATA_ARRAY_NAME = "$propertyMetadata";
public static final String DELEGATED_PROPERTIES_ARRAY_NAME = "$delegatedProperties";
public static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = "$annotations";
public static final String INSTANCE_FIELD = "INSTANCE";
@@ -17,6 +17,8 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import kotlin.jvm.internal.MutablePropertyReference2
import kotlin.jvm.internal.PropertyReference2
import kotlin.reflect.KMutableProperty2
import kotlin.reflect.KProperty2
@@ -34,7 +36,7 @@ internal open class KProperty2Impl<D, E, out R> : DescriptorBasedProperty<R>, KP
}
}
internal class KMutableProperty2Impl<D, E, R> : KProperty2Impl<D, E, R>, KMutableProperty2<D, E, R>, KMutablePropertyImpl<R> {
internal open class KMutableProperty2Impl<D, E, R> : KProperty2Impl<D, E, R>, KMutableProperty2<D, E, R>, KMutablePropertyImpl<R> {
constructor(container: KDeclarationContainerImpl, name: String, signature: String) : super(container, name, signature)
constructor(container: KDeclarationContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
@@ -47,3 +49,32 @@ internal class KMutableProperty2Impl<D, E, R> : KProperty2Impl<D, E, R>, KMutabl
override fun invoke(receiver1: D, receiver2: E, value: R): Unit = property.set(receiver1, receiver2, value)
}
}
internal class KProperty2FromReferenceImpl(
val reference: PropertyReference2
) : KProperty2Impl<Any?, Any?, Any?>(
reference.owner as KDeclarationContainerImpl,
reference.name,
reference.signature
) {
override val name: String get() = reference.name
override fun get(receiver1: Any?, receiver2: Any?): Any? = reference.get(receiver1, receiver2)
}
internal class KMutableProperty2FromReferenceImpl(
val reference: MutablePropertyReference2
) : KMutableProperty2Impl<Any?, Any?, Any?>(
reference.owner as KDeclarationContainerImpl,
reference.name,
reference.signature
) {
override val name: String get() = reference.name
override fun get(receiver1: Any?, receiver2: Any?): Any? = reference.get(receiver1, receiver2)
override fun set(receiver1: Any?, receiver2: Any?, value: Any?) {
reference.set(receiver1, receiver2, value)
}
}
@@ -70,14 +70,12 @@ public class ReflectionFactoryImpl extends ReflectionFactory {
@Override
public KProperty2 property2(PropertyReference2 p) {
// TODO: support member extension property references
return p;
return new KProperty2FromReferenceImpl(p);
}
@Override
public KMutableProperty2 mutableProperty2(MutablePropertyReference2 p) {
// TODO: support member extension property references
return p;
return new KMutableProperty2FromReferenceImpl(p);
}
// Deprecated