Delegated Properties: Code generation for local properties (JVM)
This commit is contained in:
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
@@ -423,11 +424,16 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
|
||||
for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
|
||||
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
||||
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
||||
|
||||
Type type = sharedVarType != null
|
||||
? sharedVarType
|
||||
: typeMapper.mapType((VariableDescriptor) descriptor);
|
||||
Type type = typeMapper.getSharedVarType(descriptor);
|
||||
if (type == null && descriptor instanceof LocalVariableDescriptor) {
|
||||
KotlinType delegateType = JvmCodegenUtil.getPropertyDelegateType((LocalVariableDescriptor) descriptor, bindingContext);
|
||||
if (delegateType != null) {
|
||||
type = typeMapper.mapType(delegateType);
|
||||
}
|
||||
}
|
||||
if (type == null) {
|
||||
type = typeMapper.mapType((VariableDescriptor) descriptor);
|
||||
}
|
||||
args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().asString()));
|
||||
}
|
||||
else if (ExpressionTypingUtils.isLocalFunction(descriptor)) {
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
@@ -58,6 +59,7 @@ 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.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
@@ -74,6 +76,7 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluat
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
@@ -1612,7 +1615,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull
|
||||
private Type getVariableType(@NotNull VariableDescriptor variableDescriptor) {
|
||||
Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
|
||||
return sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType());
|
||||
return sharedVarType != null ? sharedVarType : getVariableTypeNoSharing(variableDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type getVariableTypeNoSharing(@NotNull VariableDescriptor variableDescriptor) {
|
||||
KotlinType varType = isDelegatedLocalVariable(variableDescriptor)
|
||||
? JvmCodegenUtil.getPropertyDelegateType((VariableDescriptorWithAccessors) variableDescriptor, bindingContext)
|
||||
: variableDescriptor.getType();
|
||||
//noinspection ConstantConditions
|
||||
return asmType(varType);
|
||||
}
|
||||
|
||||
private static boolean isDelegatedLocalVariable(@NotNull DeclarationDescriptor descriptor) {
|
||||
return descriptor instanceof LocalVariableDescriptor && ((VariableDescriptorWithAccessors) descriptor).getGetter() != null;
|
||||
}
|
||||
|
||||
private static boolean isSharedVarType(@NotNull Type type) {
|
||||
@@ -1647,6 +1663,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
Type type = getVariableType(variableDescriptor);
|
||||
int index = myFrameMap.enter(variableDescriptor, type);
|
||||
|
||||
if (isDelegatedLocalVariable(variableDescriptor)) {
|
||||
VariableDescriptor metadataVariableDescriptor = bindingContext.get(LOCAL_VARIABLE_PROPERTY_METADATA, variableDescriptor);
|
||||
myFrameMap.enter(metadataVariableDescriptor, AsmTypes.K_PROPERTY0_TYPE);
|
||||
}
|
||||
|
||||
if (isSharedVarType(type)) {
|
||||
markLineNumber(statement, false);
|
||||
v.anew(type);
|
||||
@@ -1693,6 +1714,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
leaveTasks.add(new Function<StackValue, Void>() {
|
||||
@Override
|
||||
public Void fun(StackValue answer) {
|
||||
if (isDelegatedLocalVariable(variableDescriptor)) {
|
||||
VariableDescriptor metadataVariableDescriptor = bindingContext.get(LOCAL_VARIABLE_PROPERTY_METADATA, variableDescriptor);
|
||||
myFrameMap.leave(metadataVariableDescriptor);
|
||||
}
|
||||
|
||||
int index = myFrameMap.leave(variableDescriptor);
|
||||
|
||||
if (isSharedVarType(type)) {
|
||||
@@ -2112,18 +2138,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return StackValue.shared(parameterOffsetInConstructor, parentResult.type);
|
||||
}
|
||||
|
||||
return StackValue.local(parameterOffsetInConstructor, parentResult.type);
|
||||
return adjustVariableValue(StackValue.local(parameterOffsetInConstructor, parentResult.type), descriptor);
|
||||
}
|
||||
|
||||
private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) {
|
||||
if (descriptor instanceof VariableDescriptor) {
|
||||
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
|
||||
|
||||
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
||||
KotlinType outType = ((VariableDescriptor) descriptor).getType();
|
||||
Type varType = getVariableTypeNoSharing(variableDescriptor);
|
||||
if (sharedVarType != null) {
|
||||
return StackValue.shared(index, asmType(outType));
|
||||
return StackValue.shared(index, varType);
|
||||
}
|
||||
else {
|
||||
return StackValue.local(index, asmType(outType));
|
||||
return adjustVariableValue(StackValue.local(index, varType), variableDescriptor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -2140,19 +2168,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return myFrameMap.getIndex(descriptor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static KotlinType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) {
|
||||
PropertyGetterDescriptor getter = descriptor.getGetter();
|
||||
if (getter != null) {
|
||||
Call call = bindingContext.get(DELEGATED_PROPERTY_CALL, getter);
|
||||
if (call != null) {
|
||||
assert call.getExplicitReceiver() != null : "No explicit receiver for call:" + call;
|
||||
return ((ReceiverValue) call.getExplicitReceiver()).getType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue.Property intermediateValueForProperty(
|
||||
@NotNull PropertyDescriptor propertyDescriptor,
|
||||
@@ -2204,7 +2219,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
boolean isSuper = superCallTarget != null;
|
||||
boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null;
|
||||
|
||||
KotlinType delegateType = getPropertyDelegateType(propertyDescriptor, bindingContext);
|
||||
KotlinType delegateType = JvmCodegenUtil.getPropertyDelegateType(propertyDescriptor, bindingContext);
|
||||
boolean isDelegatedProperty = delegateType != null;
|
||||
|
||||
CallableMethod callableGetter = null;
|
||||
@@ -2828,7 +2843,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
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());
|
||||
@@ -2838,7 +2855,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
private StackValue generatePropertyReference(
|
||||
@NotNull KtElement element,
|
||||
@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull ResolvedCall<?> resolvedCall
|
||||
@NotNull VariableDescriptor target,
|
||||
@Nullable ReceiverValue dispatchReceiver
|
||||
) {
|
||||
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
||||
|
||||
@@ -2850,7 +2868,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
PropertyReferenceCodegen codegen = new PropertyReferenceCodegen(
|
||||
state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION),
|
||||
element, classBuilder, resolvedCall
|
||||
element, classBuilder, target, dispatchReceiver
|
||||
);
|
||||
codegen.generate();
|
||||
|
||||
@@ -3371,10 +3389,16 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@Override
|
||||
public StackValue visitProperty(@NotNull KtProperty property, StackValue receiver) {
|
||||
KtExpression initializer = property.getInitializer();
|
||||
if (initializer == null) {
|
||||
return StackValue.none();
|
||||
KtExpression delegateExpression = property.getDelegateExpression();
|
||||
|
||||
if (initializer != null) {
|
||||
assert delegateExpression == null : PsiUtilsKt.getElementTextWithContext(property);
|
||||
initializeLocalVariable(property, gen(initializer));
|
||||
}
|
||||
initializeLocalVariable(property, gen(initializer));
|
||||
else if (delegateExpression != null) {
|
||||
initializeLocalVariable(property, gen(delegateExpression));
|
||||
}
|
||||
|
||||
return StackValue.none();
|
||||
}
|
||||
|
||||
@@ -3412,11 +3436,27 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return StackValue.none();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private StackValue getVariableMetadataValue(VariableDescriptor variableDescriptor) {
|
||||
VariableDescriptor metadataVariableDescriptor = bindingContext.get(LOCAL_VARIABLE_PROPERTY_METADATA, variableDescriptor);
|
||||
return metadataVariableDescriptor != null ? findLocalOrCapturedValue(metadataVariableDescriptor) : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue adjustVariableValue(@NotNull StackValue varValue, DeclarationDescriptor descriptor) {
|
||||
if (!isDelegatedLocalVariable(descriptor)) return varValue;
|
||||
|
||||
VariableDescriptorWithAccessors variableDescriptor = (VariableDescriptorWithAccessors) descriptor;
|
||||
StackValue metadataValue = getVariableMetadataValue(variableDescriptor);
|
||||
assert metadataValue != null : variableDescriptor;
|
||||
return JvmCodegenUtil.delegatedVariableValue(varValue, metadataValue, variableDescriptor, bindingContext, typeMapper);
|
||||
}
|
||||
|
||||
private void initializeLocalVariable(
|
||||
@NotNull KtVariableDeclaration variableDeclaration,
|
||||
@NotNull StackValue initializer
|
||||
) {
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, variableDeclaration);
|
||||
LocalVariableDescriptor variableDescriptor = (LocalVariableDescriptor) bindingContext.get(VARIABLE, variableDeclaration);
|
||||
|
||||
if (KtPsiUtil.isScriptDeclaration(variableDeclaration)) {
|
||||
return;
|
||||
@@ -3430,7 +3470,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
|
||||
assert variableDescriptor != null;
|
||||
|
||||
Type varType = asmType(variableDescriptor.getType());
|
||||
Type varType = getVariableTypeNoSharing(variableDescriptor);
|
||||
|
||||
StackValue storeTo = sharedVarType == null ? StackValue.local(index, varType) : StackValue.shared(index, varType);
|
||||
|
||||
@@ -3440,6 +3480,37 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
markLineNumber(variableDeclaration, false);
|
||||
|
||||
storeTo.storeSelector(initializer.type, v);
|
||||
|
||||
StackValue metadataValue = getVariableMetadataValue(variableDescriptor);
|
||||
if (metadataValue != null) {
|
||||
initializePropertyMetadata((KtProperty) variableDeclaration, variableDescriptor, metadataValue);
|
||||
invokePropertyDelegatedOnLocalVar(variableDescriptor, storeTo, metadataValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void invokePropertyDelegatedOnLocalVar(
|
||||
@NotNull LocalVariableDescriptor variableDescriptor,
|
||||
@NotNull StackValue delegateValue,
|
||||
@NotNull StackValue metadataValue
|
||||
) {
|
||||
ResolvedCall<FunctionDescriptor> pdResolvedCall =
|
||||
bindingContext.get(BindingContext.DELEGATED_PROPERTY_PD_RESOLVED_CALL, variableDescriptor);
|
||||
if (pdResolvedCall == null) return;
|
||||
|
||||
tempVariables.put(pdResolvedCall.getCall().getValueArguments().get(0).asElement(), metadataValue);
|
||||
invokeFunction(pdResolvedCall, delegateValue).put(Type.VOID_TYPE, v);
|
||||
}
|
||||
|
||||
private void initializePropertyMetadata(
|
||||
@NotNull KtProperty variable,
|
||||
@NotNull LocalVariableDescriptor variableDescriptor,
|
||||
@NotNull StackValue metadataVar
|
||||
) {
|
||||
//noinspection ConstantConditions
|
||||
StackValue value =
|
||||
generatePropertyReference(variable.getDelegate(), variableDescriptor, variableDescriptor, null);
|
||||
value.put(K_PROPERTY0_TYPE, v);
|
||||
metadataVar.storeSelector(K_PROPERTY0_TYPE, v);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityUtilsKt;
|
||||
import org.jetbrains.kotlin.psi.Call;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.psi.KtFunction;
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.CodeFragmentUtilKt;
|
||||
@@ -40,14 +41,17 @@ import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.LOCAL_VARIABLE_DELEGATE;
|
||||
import static org.jetbrains.kotlin.descriptors.Modality.ABSTRACT;
|
||||
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.DELEGATED_PROPERTY_CALL;
|
||||
|
||||
public class JvmCodegenUtil {
|
||||
|
||||
@@ -223,4 +227,40 @@ public class JvmCodegenUtil {
|
||||
if (!(descriptor instanceof JavaPropertyDescriptor)) return false;
|
||||
return descriptor.isConst();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static KotlinType getPropertyDelegateType(
|
||||
@NotNull VariableDescriptorWithAccessors descriptor,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
VariableAccessorDescriptor getter = descriptor.getGetter();
|
||||
if (getter != null) {
|
||||
Call call = bindingContext.get(DELEGATED_PROPERTY_CALL, getter);
|
||||
if (call != null) {
|
||||
assert call.getExplicitReceiver() != null : "No explicit receiver for call:" + call;
|
||||
return ((ReceiverValue) call.getExplicitReceiver()).getType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static StackValue.Delegate delegatedVariableValue(
|
||||
@NotNull StackValue delegateValue,
|
||||
@NotNull StackValue metadataValue,
|
||||
VariableDescriptorWithAccessors variableDescriptor,
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull KotlinTypeMapper typeMapper
|
||||
) {
|
||||
VariableDescriptor delegateVariableDescriptor = bindingContext.get(LOCAL_VARIABLE_DELEGATE, variableDescriptor);
|
||||
assert delegateVariableDescriptor != null : variableDescriptor;
|
||||
|
||||
VariableAccessorDescriptor getterDescriptor = variableDescriptor.getGetter();
|
||||
VariableAccessorDescriptor setterDescriptor = variableDescriptor.getSetter();
|
||||
|
||||
//noinspection ConstantConditions
|
||||
CallableMethod getterMethod = typeMapper.mapToCallableMethod(getterDescriptor, false);
|
||||
CallableMethod setterMethod = setterDescriptor != null ? typeMapper.mapToCallableMethod(setterDescriptor, false) : null;
|
||||
return StackValue.delegate(typeMapper.mapType(variableDescriptor.getType()), delegateValue, metadataValue, getterMethod, setterMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
@@ -39,6 +40,8 @@ public class JvmRuntimeTypes {
|
||||
private final ClassDescriptor functionReference;
|
||||
private final List<ClassDescriptor> propertyReferences;
|
||||
private final List<ClassDescriptor> mutablePropertyReferences;
|
||||
private final ClassDescriptor localVariableReference;
|
||||
private final ClassDescriptor mutableLocalVariableReference;
|
||||
|
||||
public JvmRuntimeTypes() {
|
||||
ModuleDescriptorImpl module = TargetPlatformKt.createModule(
|
||||
@@ -47,9 +50,12 @@ public class JvmRuntimeTypes {
|
||||
LockBasedStorageManager.NO_LOCKS,
|
||||
DefaultBuiltIns.getInstance());
|
||||
PackageFragmentDescriptor kotlinJvmInternal = new MutablePackageFragmentDescriptor(module, new FqName("kotlin.jvm.internal"));
|
||||
PackageFragmentDescriptor kotlinReflectJvmInternal = new MutablePackageFragmentDescriptor(module, new FqName("kotlin.reflect.jvm.internal"));
|
||||
|
||||
this.lambda = createClass(kotlinJvmInternal, "Lambda");
|
||||
this.functionReference = createClass(kotlinJvmInternal, "FunctionReference");
|
||||
this.localVariableReference = createClass(kotlinReflectJvmInternal, "LocalVariableReference");
|
||||
this.mutableLocalVariableReference = createClass(kotlinReflectJvmInternal, "MutableLocalVariableReference");
|
||||
this.propertyReferences = new ArrayList<ClassDescriptor>(3);
|
||||
this.mutablePropertyReferences = new ArrayList<ClassDescriptor>(3);
|
||||
|
||||
@@ -110,7 +116,11 @@ public class JvmRuntimeTypes {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KotlinType getSupertypeForPropertyReference(@NotNull PropertyDescriptor descriptor) {
|
||||
public KotlinType getSupertypeForPropertyReference(@NotNull VariableDescriptorWithAccessors descriptor) {
|
||||
if (descriptor instanceof LocalVariableDescriptor) {
|
||||
return (descriptor.isVar() ? mutableLocalVariableReference : localVariableReference).getDefaultType();
|
||||
}
|
||||
|
||||
int arity = (descriptor.getExtensionReceiverParameter() != null ? 1 : 0) +
|
||||
(descriptor.getDispatchReceiverParameter() != null ? 1 : 0);
|
||||
return (descriptor.isVar() ? mutablePropertyReferences : propertyReferences).get(arity).getDefaultType();
|
||||
|
||||
@@ -21,17 +21,18 @@ import org.jetbrains.kotlin.codegen.context.ClassContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
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.KtElement
|
||||
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.utils.sure
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -44,13 +45,13 @@ class PropertyReferenceCodegen(
|
||||
context: ClassContext,
|
||||
expression: KtElement,
|
||||
classBuilder: ClassBuilder,
|
||||
resolvedCall: ResolvedCall<*>
|
||||
private val target: VariableDescriptor,
|
||||
dispatchReceiver: ReceiverValue?
|
||||
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
|
||||
private val classDescriptor = context.contextDescriptor
|
||||
private val asmType = typeMapper.mapClass(classDescriptor)
|
||||
|
||||
private val target = resolvedCall.resultingDescriptor as VariableDescriptor
|
||||
private val dispatchReceiverType = resolvedCall.dispatchReceiver?.type
|
||||
private val dispatchReceiverType = dispatchReceiver?.type
|
||||
private val extensionReceiverType = target.extensionReceiverParameter?.type
|
||||
|
||||
private val receiverCount =
|
||||
@@ -85,8 +86,10 @@ class PropertyReferenceCodegen(
|
||||
invokespecial(superAsmType.internalName, "<init>", "()V", false)
|
||||
}
|
||||
|
||||
generateMethod("property reference getOwner", ACC_PUBLIC, method("getOwner", K_DECLARATION_CONTAINER_TYPE)) {
|
||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(this, target, state)
|
||||
if (target !is LocalVariableDescriptor) {
|
||||
generateMethod("property reference getOwner", ACC_PUBLIC, method("getOwner", K_DECLARATION_CONTAINER_TYPE)) {
|
||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(this, target, state)
|
||||
}
|
||||
}
|
||||
|
||||
generateMethod("property reference getName", ACC_PUBLIC, method("getName", JAVA_STRING_TYPE)) {
|
||||
@@ -94,7 +97,7 @@ class PropertyReferenceCodegen(
|
||||
}
|
||||
|
||||
generateMethod("property reference getSignature", ACC_PUBLIC, method("getSignature", JAVA_STRING_TYPE)) {
|
||||
aconst(getPropertyReferenceSignature(target as PropertyDescriptor, state))
|
||||
aconst(getPropertyReferenceSignature(target as VariableDescriptorWithAccessors, state))
|
||||
}
|
||||
|
||||
generateAccessors()
|
||||
@@ -125,7 +128,10 @@ class PropertyReferenceCodegen(
|
||||
StackValue.local(index + 1, OBJECT_TYPE).put(typeMapper.mapType(type), this)
|
||||
}
|
||||
|
||||
val value = fakeCodegen.intermediateValueForProperty(target as PropertyDescriptor, false, null, StackValue.none())
|
||||
val value = if (target is LocalVariableDescriptor) {
|
||||
fakeCodegen.findLocalOrCapturedValue(target)!!
|
||||
}
|
||||
else fakeCodegen.intermediateValueForProperty(target as PropertyDescriptor, false, null, StackValue.none())
|
||||
|
||||
accessorBody(value)
|
||||
}
|
||||
@@ -168,9 +174,9 @@ class PropertyReferenceCodegen(
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getPropertyReferenceSignature(property: PropertyDescriptor, state: GenerationState): String {
|
||||
fun getPropertyReferenceSignature(property: VariableDescriptorWithAccessors, state: GenerationState): String {
|
||||
val getter =
|
||||
property.getter ?: DescriptorFactory.createDefaultGetter(property, Annotations.EMPTY).apply {
|
||||
property.getter ?: DescriptorFactory.createDefaultGetter(property as PropertyDescriptor, Annotations.EMPTY).apply {
|
||||
initialize(property.type)
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +152,17 @@ public abstract class StackValue {
|
||||
return new Local(index, type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Delegate delegate(
|
||||
Type type,
|
||||
@NotNull StackValue delegateValue,
|
||||
@NotNull StackValue metadataValue,
|
||||
@NotNull CallableMethod getter,
|
||||
@Nullable CallableMethod setter
|
||||
) {
|
||||
return new Delegate(type, delegateValue, metadataValue, getter, setter);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static StackValue shared(int index, @NotNull Type type) {
|
||||
return new Shared(index, type);
|
||||
@@ -245,17 +256,8 @@ public abstract class StackValue {
|
||||
@NotNull
|
||||
public static StackValue changeReceiverForFieldAndSharedVar(@NotNull StackValueWithSimpleReceiver stackValue, @Nullable StackValue newReceiver) {
|
||||
//TODO static check
|
||||
if (newReceiver != null) {
|
||||
if (!stackValue.isStaticPut) {
|
||||
if (stackValue instanceof Field) {
|
||||
return field((Field) stackValue, newReceiver);
|
||||
}
|
||||
else if (stackValue instanceof FieldForSharedVar) {
|
||||
return fieldForSharedVar((FieldForSharedVar) stackValue, newReceiver);
|
||||
}
|
||||
}
|
||||
}
|
||||
return stackValue;
|
||||
if (newReceiver == null || stackValue.isStaticPut) return stackValue;
|
||||
return stackValue.changeReceiver(newReceiver);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -657,6 +659,56 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class Delegate extends StackValueWithSimpleReceiver {
|
||||
@NotNull private final StackValue delegateValue;
|
||||
@NotNull private final StackValue metadataValue;
|
||||
@NotNull private final CallableMethod getter;
|
||||
@Nullable private final CallableMethod setter;
|
||||
|
||||
private Delegate(
|
||||
Type type,
|
||||
@NotNull StackValue delegateValue,
|
||||
@NotNull StackValue metadataValue,
|
||||
@NotNull CallableMethod getter,
|
||||
@Nullable CallableMethod setter
|
||||
) {
|
||||
super(type, false, false, new Receiver(OBJECT_TYPE, delegateValue, constant(null, OBJECT_TYPE), metadataValue), false);
|
||||
this.delegateValue = delegateValue;
|
||||
this.metadataValue = metadataValue;
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue getMetadataValue() {
|
||||
return metadataValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
getter.genInvokeInstruction(v);
|
||||
coerce(getter.getReturnType(), type, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) {
|
||||
assert setter != null : "";
|
||||
coerceFrom(topOfStackType, v);
|
||||
setter.genInvokeInstruction(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StackValueWithSimpleReceiver changeReceiver(@NotNull StackValue newReceiver) {
|
||||
StackValue newDelegateValue = delegateValue instanceof StackValueWithSimpleReceiver
|
||||
? ((StackValueWithSimpleReceiver) delegateValue).changeReceiver(newReceiver)
|
||||
: delegateValue;
|
||||
StackValue newMetadataValue = metadataValue instanceof StackValueWithSimpleReceiver
|
||||
? ((StackValueWithSimpleReceiver) metadataValue).changeReceiver(newReceiver)
|
||||
: metadataValue;
|
||||
return delegate(type, newDelegateValue, newMetadataValue, getter, setter);
|
||||
}
|
||||
}
|
||||
|
||||
public static class OnStack extends StackValue {
|
||||
public OnStack(Type type) {
|
||||
super(type);
|
||||
@@ -1079,6 +1131,11 @@ public abstract class StackValue {
|
||||
coerceFrom(topOfStackType, v);
|
||||
v.visitFieldInsn(isStaticStore ? PUTSTATIC : PUTFIELD, owner.getInternalName(), name, this.type.getDescriptor());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StackValueWithSimpleReceiver changeReceiver(@NotNull StackValue newReceiver) {
|
||||
return field(this, newReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
static class Property extends StackValueWithSimpleReceiver {
|
||||
@@ -1297,6 +1354,11 @@ public abstract class StackValue {
|
||||
coerceFrom(topOfStackType, v);
|
||||
v.visitFieldInsn(PUTFIELD, sharedTypeForType(type).getInternalName(), "element", refType(type).getDescriptor());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StackValueWithSimpleReceiver changeReceiver(@NotNull StackValue newReceiver) {
|
||||
return fieldForSharedVar(this, newReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThisOuter extends StackValue {
|
||||
@@ -1558,6 +1620,10 @@ public abstract class StackValue {
|
||||
rightSide.put(rightSide.type, v);
|
||||
storeSelector(rightSide.type, v);
|
||||
}
|
||||
|
||||
protected StackValueWithSimpleReceiver changeReceiver(@NotNull StackValue newReceiver) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ComplexReceiver extends StackValue {
|
||||
|
||||
+39
-5
@@ -23,6 +23,7 @@ import com.intellij.util.containers.Stack;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes;
|
||||
import org.jetbrains.kotlin.cfg.WhenChecker;
|
||||
import org.jetbrains.kotlin.codegen.*;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
@@ -30,6 +31,8 @@ import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
@@ -46,7 +49,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.NullValue;
|
||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
@@ -317,12 +320,43 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
fileClassesProvider);
|
||||
}
|
||||
|
||||
private void recordLocalVariablePropertyMetadata(LocalVariableDescriptor variableDescriptor) {
|
||||
KotlinType delegateType = JvmCodegenUtil.getPropertyDelegateType(variableDescriptor, bindingContext);
|
||||
if (delegateType == null) return;
|
||||
|
||||
LocalVariableDescriptor delegateVariableDescriptor = new LocalVariableDescriptor(
|
||||
variableDescriptor.getContainingDeclaration(),
|
||||
Annotations.Companion.getEMPTY(),
|
||||
variableDescriptor.getName(),
|
||||
delegateType,
|
||||
false,
|
||||
false,
|
||||
SourceElement.NO_SOURCE
|
||||
);
|
||||
bindingTrace.record(LOCAL_VARIABLE_DELEGATE, variableDescriptor, delegateVariableDescriptor);
|
||||
|
||||
LocalVariableDescriptor metadataVariableDescriptor = new LocalVariableDescriptor(
|
||||
variableDescriptor.getContainingDeclaration(),
|
||||
Annotations.Companion.getEMPTY(),
|
||||
Name.identifier(variableDescriptor.getName().asString() + "$metadata"),
|
||||
ReflectionTypes.Companion.createKPropertyStarType(DescriptorUtilsKt.getModule(variableDescriptor)),
|
||||
false,
|
||||
false,
|
||||
SourceElement.NO_SOURCE
|
||||
);
|
||||
bindingTrace.record(LOCAL_VARIABLE_PROPERTY_METADATA, variableDescriptor, metadataVariableDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProperty(@NotNull KtProperty property) {
|
||||
DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property);
|
||||
// working around a problem with shallow analysis
|
||||
if (descriptor == null) return;
|
||||
|
||||
if (descriptor instanceof LocalVariableDescriptor) {
|
||||
recordLocalVariablePropertyMetadata((LocalVariableDescriptor) descriptor);
|
||||
}
|
||||
|
||||
String nameForClassOrPackageMember = getNameForClassOrPackageMember(descriptor);
|
||||
if (nameForClassOrPackageMember != null) {
|
||||
nameStack.push(nameForClassOrPackageMember);
|
||||
@@ -332,11 +366,11 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
}
|
||||
|
||||
KtPropertyDelegate delegate = property.getDelegate();
|
||||
if (delegate != null && descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
if (delegate != null && descriptor instanceof VariableDescriptorWithAccessors) {
|
||||
VariableDescriptorWithAccessors variableDescriptor = (VariableDescriptorWithAccessors) descriptor;
|
||||
String name = inventAnonymousClassName();
|
||||
KotlinType supertype = runtimeTypes.getSupertypeForPropertyReference(propertyDescriptor);
|
||||
ClassDescriptor classDescriptor = recordClassForCallable(delegate, propertyDescriptor, Collections.singleton(supertype), name);
|
||||
KotlinType supertype = runtimeTypes.getSupertypeForPropertyReference(variableDescriptor);
|
||||
ClassDescriptor classDescriptor = recordClassForCallable(delegate, variableDescriptor, Collections.singleton(supertype), name);
|
||||
recordClosure(classDescriptor, name);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,12 @@ public class CodegenBinding {
|
||||
public static final WritableSlice<String, List<WhenByEnumsMapping>> MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<VariableDescriptor, VariableDescriptor> LOCAL_VARIABLE_DELEGATE =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<VariableDescriptor, VariableDescriptor> LOCAL_VARIABLE_PROPERTY_METADATA =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
static {
|
||||
BasicWritableSlice.initSliceDebugNames(CodegenBinding.class);
|
||||
}
|
||||
|
||||
@@ -51,10 +51,19 @@ public interface LocalLookup {
|
||||
Type classType
|
||||
) {
|
||||
VariableDescriptor vd = (VariableDescriptor) d;
|
||||
VariableDescriptor originalVariableDescriptor = vd;
|
||||
|
||||
boolean idx = localLookup != null && localLookup.lookupLocal(vd);
|
||||
if (!idx) return null;
|
||||
|
||||
boolean delegatedVar = false;
|
||||
VariableDescriptor delegateVariableDescriptor = state.getBindingContext().get(LOCAL_VARIABLE_DELEGATE, vd);
|
||||
VariableDescriptor metadataVariableDescriptor = state.getBindingContext().get(LOCAL_VARIABLE_PROPERTY_METADATA, vd);
|
||||
if (delegateVariableDescriptor != null) {
|
||||
vd = delegateVariableDescriptor;
|
||||
delegatedVar = true;
|
||||
}
|
||||
|
||||
Type sharedVarType = state.getTypeMapper().getSharedVarType(vd);
|
||||
Type localType = state.getTypeMapper().mapType(vd);
|
||||
Type type = sharedVarType != null ? sharedVarType : localType;
|
||||
@@ -71,6 +80,18 @@ public interface LocalLookup {
|
||||
}
|
||||
else {
|
||||
innerValue = StackValue.field(type, classType, fieldName, false, thiz, vd);
|
||||
if (delegatedVar) {
|
||||
StackValue metadataValue = innerValue(metadataVariableDescriptor, localLookup, state, closure, classType);
|
||||
assert metadataValue != null : originalVariableDescriptor;
|
||||
|
||||
innerValue = JvmCodegenUtil.delegatedVariableValue(
|
||||
innerValue,
|
||||
metadataValue,
|
||||
(VariableDescriptorWithAccessors) originalVariableDescriptor,
|
||||
state.getBindingContext(),
|
||||
state.getTypeMapper()
|
||||
);
|
||||
}
|
||||
enclosedValueDescriptor = new EnclosedValueDescriptor(fieldName, d, innerValue, type);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory;
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor;
|
||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||
@@ -630,6 +631,13 @@ public class KotlinTypeMapper {
|
||||
return new CallableMethod(owner, owner, defaultImplDesc, method, INVOKESPECIAL, null, null, null);
|
||||
}
|
||||
|
||||
if (descriptor instanceof LocalVariableAccessorDescriptor) {
|
||||
ResolvedCall<FunctionDescriptor> delegateAccessorResolvedCall =
|
||||
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, (VariableAccessorDescriptor) descriptor);
|
||||
//noinspection ConstantConditions
|
||||
return mapToCallableMethod(delegateAccessorResolvedCall.getResultingDescriptor(), false);
|
||||
}
|
||||
|
||||
DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
|
||||
|
||||
FunctionDescriptor functionDescriptor = unwrapFakeOverride(descriptor.getOriginal());
|
||||
@@ -1354,14 +1362,22 @@ public class KotlinTypeMapper {
|
||||
if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
|
||||
return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
|
||||
}
|
||||
else if (descriptor instanceof PropertyDescriptor || descriptor instanceof FunctionDescriptor) {
|
||||
|
||||
if (descriptor instanceof PropertyDescriptor || descriptor instanceof FunctionDescriptor) {
|
||||
ReceiverParameterDescriptor receiverParameter = ((CallableDescriptor) descriptor).getExtensionReceiverParameter();
|
||||
assert receiverParameter != null : "Callable should have a receiver parameter: " + descriptor;
|
||||
return StackValue.sharedTypeForType(mapType(receiverParameter.getType()));
|
||||
}
|
||||
else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
|
||||
|
||||
if (descriptor instanceof VariableDescriptorWithAccessors) {
|
||||
VariableDescriptorWithAccessors withAccessors = (VariableDescriptorWithAccessors) descriptor;
|
||||
if (withAccessors.getGetter() != null || withAccessors.getSetter() != null) return null;
|
||||
}
|
||||
|
||||
if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
|
||||
return StackValue.sharedTypeForType(mapType(((VariableDescriptor) descriptor).getType()));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package foo
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
inline fun <T> run(f: () -> T) = f()
|
||||
|
||||
class Delegate {
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = 1
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val prop: Int by Delegate()
|
||||
return run { if (prop == 1) "OK" else "fail" }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package foo
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
fun <T> run(f: () -> T) = f()
|
||||
|
||||
class Delegate {
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = 1
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val prop: Int by Delegate()
|
||||
return run { if (prop == 1) "OK" else "fail" }
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package foo
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
inline fun <T> run(f: () -> T) = f()
|
||||
|
||||
class Delegate {
|
||||
var inner = 1
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
|
||||
operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
|
||||
inner = i
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var prop: Int by Delegate()
|
||||
run { prop = 2 }
|
||||
if (prop != 2) return "fail get"
|
||||
return run { if (prop != 2) "fail set" else "OK" }
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package foo
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
fun <T> run(f: () -> T) = f()
|
||||
|
||||
class Delegate {
|
||||
var inner = 1
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
|
||||
operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
|
||||
inner = i
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var prop: Int by Delegate()
|
||||
run { prop = 2 }
|
||||
if (prop != 2) return "fail get"
|
||||
return run { if (prop != 2) "fail set" else "OK" }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package foo
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Delegate {
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = 1
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val prop: Int by Delegate()
|
||||
return if (prop == 1) "OK" else "fail"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package foo
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Delegate {
|
||||
var inner = 1
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
|
||||
operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
|
||||
inner = i
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var prop: Int by Delegate()
|
||||
if (prop != 1) return "fail get"
|
||||
prop = 2
|
||||
if (prop != 2) return "fail set"
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Delegate {
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = 3
|
||||
}
|
||||
|
||||
fun foo(): Int {
|
||||
val prop: Int by Delegate()
|
||||
return prop
|
||||
}
|
||||
|
||||
val x = foo()
|
||||
|
||||
// expected: x: 3
|
||||
@@ -4747,6 +4747,30 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("capturedLocalVal.kt")
|
||||
public void testCapturedLocalVal() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/capturedLocalVal.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("capturedLocalValNoInline.kt")
|
||||
public void testCapturedLocalValNoInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/capturedLocalValNoInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("capturedLocalVar.kt")
|
||||
public void testCapturedLocalVar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/capturedLocalVar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("capturedLocalVarNoInline.kt")
|
||||
public void testCapturedLocalVarNoInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/capturedLocalVarNoInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("castGetReturnType.kt")
|
||||
public void testCastGetReturnType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/castGetReturnType.kt");
|
||||
@@ -4861,6 +4885,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localVal.kt")
|
||||
public void testLocalVal() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/localVal.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localVar.kt")
|
||||
public void testLocalVar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/localVar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateVar.kt")
|
||||
public void testPrivateVar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/privateVar.kt");
|
||||
|
||||
@@ -65,6 +65,12 @@ public class ScriptCodegenTestGenerated extends AbstractScriptCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localDelegatedProperty.kts")
|
||||
public void testLocalDelegatedProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/localDelegatedProperty.kts");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localFunction.kts")
|
||||
public void testLocalFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/localFunction.kts");
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import kotlin.reflect.KCallable
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
|
||||
internal object EmptyContainerForLocal : KDeclarationContainerImpl() {
|
||||
override val jClass: Class<*>
|
||||
get() = fail()
|
||||
|
||||
override val members: Collection<KCallable<*>>
|
||||
get() = fail()
|
||||
|
||||
override val constructorDescriptors: Collection<ConstructorDescriptor>
|
||||
get() = fail()
|
||||
|
||||
override fun getProperties(name: Name): Collection<PropertyDescriptor> = fail()
|
||||
|
||||
override fun getFunctions(name: Name): Collection<FunctionDescriptor> = fail()
|
||||
|
||||
private fun fail(): Nothing = throw KotlinReflectionInternalError("Introspecting local functions, lambdas and anonymous functions " +
|
||||
"is not yet fully supported in Kotlin reflection")
|
||||
}
|
||||
@@ -62,20 +62,3 @@ internal class KFunctionFromReferenceImpl(
|
||||
override fun invoke(p1: Any?, p2: Any?, p3: Any?, p4: Any?, p5: Any?, p6: Any?, p7: Any?, p8: Any?, p9: Any?, p10: Any?, p11: Any?, p12: Any?, p13: Any?, p14: Any?, p15: Any?, p16: Any?, p17: Any?, p18: Any?, p19: Any?, p20: Any?, p21: Any?, p22: Any?): Any? = reference(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22)
|
||||
}
|
||||
|
||||
internal object EmptyContainerForLocal : KDeclarationContainerImpl() {
|
||||
override val jClass: Class<*>
|
||||
get() = fail()
|
||||
|
||||
override val members: Collection<KCallable<*>>
|
||||
get() = fail()
|
||||
|
||||
override val constructorDescriptors: Collection<ConstructorDescriptor>
|
||||
get() = fail()
|
||||
|
||||
override fun getProperties(name: Name): Collection<PropertyDescriptor> = fail()
|
||||
|
||||
override fun getFunctions(name: Name): Collection<FunctionDescriptor> = fail()
|
||||
|
||||
private fun fail(): Nothing = throw KotlinReflectionInternalError("Introspecting local functions, lambdas and anonymous functions " +
|
||||
"is not yet fully supported in Kotlin reflection")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import kotlin.jvm.internal.MutablePropertyReference0
|
||||
import kotlin.jvm.internal.PropertyReference0
|
||||
import kotlin.reflect.KDeclarationContainer
|
||||
|
||||
open class LocalVariableReference : PropertyReference0() {
|
||||
override fun getOwner(): KDeclarationContainer = EmptyContainerForLocal
|
||||
}
|
||||
|
||||
open class MutableLocalVariableReference : MutablePropertyReference0() {
|
||||
override fun getOwner(): KDeclarationContainer = EmptyContainerForLocal
|
||||
}
|
||||
Reference in New Issue
Block a user