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:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
-23
@@ -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";
|
||||
|
||||
|
||||
-36
@@ -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"
|
||||
}
|
||||
Vendored
+2
-2
@@ -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!!
|
||||
Vendored
+2
-2
@@ -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
|
||||
|
||||
-6
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user