From 3c74f48f913efa5358978df3b22580919a408349 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 12 Oct 2015 12:11:36 +0300 Subject: [PATCH] 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 --- .../kotlin/codegen/ExpressionCodegen.java | 18 ++--- .../kotlin/codegen/MemberCodegen.java | 24 ++++--- .../kotlin/codegen/PropertyCodegen.java | 2 +- .../codegen/PropertyReferenceCodegen.kt | 72 ++++++++++--------- .../binding/CodegenAnnotatingVisitor.java | 43 ++++++----- .../kotlin/resolve/jvm/AsmTypes.java | 5 +- .../propertyMetadataEqualsHashCodeToString.kt | 36 ---------- .../specialNames/propertyMetadataCache.kt | 4 +- .../specialNames/propertyMetadataCache.txt | 4 +- .../BlackBoxCodegenTestGenerated.java | 6 -- core/builtins/src/kotlin/reflect/KProperty.kt | 2 +- .../jetbrains/kotlin/load/java/JvmAbi.java | 2 +- .../reflect/jvm/internal/KProperty2Impl.kt | 33 ++++++++- .../jvm/internal/ReflectionFactoryImpl.java | 6 +- 14 files changed, 128 insertions(+), 129 deletions(-) delete mode 100644 compiler/testData/codegen/box/delegatedProperty/propertyMetadataEqualsHashCodeToString.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 1b700a0f99d..4d01f77f47f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -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 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) resolvedCall + element, classBuilder, classDescriptor, target, dispatchReceiver ); codegen.generate(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index e96e84da161..ed732b4d03a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -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", "(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() { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index 2957f70c7e4..447187b461c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -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); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt index e48d9731cb9..e11694ffa71 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyReferenceCodegen.kt @@ -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 -) : MemberCodegen(state, parentCodegen, context, expression, classBuilder) { - private val target = resolvedCall.getResultingDescriptor() + private val target: VariableDescriptor, + dispatchReceiver: ReceiverValue +) : MemberCodegen(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) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index 174d9323749..0314a69fb54 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -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 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 supertypes = runtimeTypes.getSupertypesForClosure(functionDescriptor); ClassDescriptor classDescriptor = recordClassForCallable(function, functionDescriptor, supertypes, name); recordClosure(classDescriptor, name); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java index 5d44c787686..70657d72a4d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java @@ -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"; diff --git a/compiler/testData/codegen/box/delegatedProperty/propertyMetadataEqualsHashCodeToString.kt b/compiler/testData/codegen/box/delegatedProperty/propertyMetadataEqualsHashCodeToString.kt deleted file mode 100644 index a50b7964f3b..00000000000 --- a/compiler/testData/codegen/box/delegatedProperty/propertyMetadataEqualsHashCodeToString.kt +++ /dev/null @@ -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() - - 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" -} diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/propertyMetadataCache.kt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/propertyMetadataCache.kt index e6f1b8d6405..ccb79288407 100644 --- a/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/propertyMetadataCache.kt +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/propertyMetadataCache.kt @@ -4,8 +4,8 @@ operator fun Any.getValue(x: Any?, y: Any): Any = null!! class C { val x by 1 - val `$propertyMetadata`: Array = null!! + val `$delegatedProperties`: Array = null!! } val x by 1 -val `$propertyMetadata`: Array = null!! \ No newline at end of file +val `$delegatedProperties`: Array = null!! \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/propertyMetadataCache.txt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/propertyMetadataCache.txt index f8986426e5e..a0ae7c7c4d8 100644 --- a/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/propertyMetadataCache.txt +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/propertyMetadataCache.txt @@ -1,12 +1,12 @@ package -public val `$propertyMetadata`: kotlin.Array +public val `$delegatedProperties`: kotlin.Array 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 + public final val `$delegatedProperties`: kotlin.Array 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 diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index 28bb38501d2..41ada4c91d5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/core/builtins/src/kotlin/reflect/KProperty.kt b/core/builtins/src/kotlin/reflect/KProperty.kt index 32cca5e069d..55047d5ca74 100644 --- a/core/builtins/src/kotlin/reflect/KProperty.kt +++ b/core/builtins/src/kotlin/reflect/KProperty.kt @@ -24,7 +24,7 @@ package kotlin.reflect * * @param R the type of the property. */ -public interface KProperty : KCallable { +public interface KProperty : KCallable, PropertyMetadata { /** The getter of this property, used to obtain the value of the property. */ public val getter: Getter diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java index eb636b7dd55..c03ab3b3a8a 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java @@ -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"; diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty2Impl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty2Impl.kt index 79f529b99ae..1ee7e3f43df 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty2Impl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KProperty2Impl.kt @@ -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 : DescriptorBasedProperty, KP } } -internal class KMutableProperty2Impl : KProperty2Impl, KMutableProperty2, KMutablePropertyImpl { +internal open class KMutableProperty2Impl : KProperty2Impl, KMutableProperty2, KMutablePropertyImpl { 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 : KProperty2Impl, KMutabl override fun invoke(receiver1: D, receiver2: E, value: R): Unit = property.set(receiver1, receiver2, value) } } + + +internal class KProperty2FromReferenceImpl( + val reference: PropertyReference2 +) : KProperty2Impl( + 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( + 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) + } +} diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java index 20d1d2dce7d..049a1ccf17f 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java @@ -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