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.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||||
@@ -423,11 +424,16 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
|||||||
|
|
||||||
for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
|
for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
|
||||||
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
||||||
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
Type type = typeMapper.getSharedVarType(descriptor);
|
||||||
|
if (type == null && descriptor instanceof LocalVariableDescriptor) {
|
||||||
Type type = sharedVarType != null
|
KotlinType delegateType = JvmCodegenUtil.getPropertyDelegateType((LocalVariableDescriptor) descriptor, bindingContext);
|
||||||
? sharedVarType
|
if (delegateType != null) {
|
||||||
: typeMapper.mapType((VariableDescriptor) descriptor);
|
type = typeMapper.mapType(delegateType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == null) {
|
||||||
|
type = typeMapper.mapType((VariableDescriptor) descriptor);
|
||||||
|
}
|
||||||
args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().asString()));
|
args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().asString()));
|
||||||
}
|
}
|
||||||
else if (ExpressionTypingUtils.isLocalFunction(descriptor)) {
|
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.SwitchCodegen;
|
||||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
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.load.java.descriptors.SamConstructorDescriptor;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
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.constants.evaluate.ConstantExpressionEvaluatorKt;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
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.diagnostics.JvmDeclarationOriginKt;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||||
@@ -1612,7 +1615,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
@NotNull
|
@NotNull
|
||||||
private Type getVariableType(@NotNull VariableDescriptor variableDescriptor) {
|
private Type getVariableType(@NotNull VariableDescriptor variableDescriptor) {
|
||||||
Type sharedVarType = typeMapper.getSharedVarType(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) {
|
private static boolean isSharedVarType(@NotNull Type type) {
|
||||||
@@ -1647,6 +1663,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
Type type = getVariableType(variableDescriptor);
|
Type type = getVariableType(variableDescriptor);
|
||||||
int index = myFrameMap.enter(variableDescriptor, type);
|
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)) {
|
if (isSharedVarType(type)) {
|
||||||
markLineNumber(statement, false);
|
markLineNumber(statement, false);
|
||||||
v.anew(type);
|
v.anew(type);
|
||||||
@@ -1693,6 +1714,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
leaveTasks.add(new Function<StackValue, Void>() {
|
leaveTasks.add(new Function<StackValue, Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Void fun(StackValue answer) {
|
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);
|
int index = myFrameMap.leave(variableDescriptor);
|
||||||
|
|
||||||
if (isSharedVarType(type)) {
|
if (isSharedVarType(type)) {
|
||||||
@@ -2112,18 +2138,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
return StackValue.shared(parameterOffsetInConstructor, parentResult.type);
|
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) {
|
private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) {
|
||||||
if (descriptor instanceof VariableDescriptor) {
|
if (descriptor instanceof VariableDescriptor) {
|
||||||
|
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
|
||||||
|
|
||||||
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
|
||||||
KotlinType outType = ((VariableDescriptor) descriptor).getType();
|
Type varType = getVariableTypeNoSharing(variableDescriptor);
|
||||||
if (sharedVarType != null) {
|
if (sharedVarType != null) {
|
||||||
return StackValue.shared(index, asmType(outType));
|
return StackValue.shared(index, varType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return StackValue.local(index, asmType(outType));
|
return adjustVariableValue(StackValue.local(index, varType), variableDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -2140,19 +2168,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
return myFrameMap.getIndex(descriptor);
|
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
|
@NotNull
|
||||||
public StackValue.Property intermediateValueForProperty(
|
public StackValue.Property intermediateValueForProperty(
|
||||||
@NotNull PropertyDescriptor propertyDescriptor,
|
@NotNull PropertyDescriptor propertyDescriptor,
|
||||||
@@ -2204,7 +2219,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
boolean isSuper = superCallTarget != null;
|
boolean isSuper = superCallTarget != null;
|
||||||
boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null;
|
boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null;
|
||||||
|
|
||||||
KotlinType delegateType = getPropertyDelegateType(propertyDescriptor, bindingContext);
|
KotlinType delegateType = JvmCodegenUtil.getPropertyDelegateType(propertyDescriptor, bindingContext);
|
||||||
boolean isDelegatedProperty = delegateType != null;
|
boolean isDelegatedProperty = delegateType != null;
|
||||||
|
|
||||||
CallableMethod callableGetter = null;
|
CallableMethod callableGetter = null;
|
||||||
@@ -2828,7 +2843,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
||||||
if (variableDescriptor != null) {
|
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());
|
throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText());
|
||||||
@@ -2838,7 +2855,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
private StackValue generatePropertyReference(
|
private StackValue generatePropertyReference(
|
||||||
@NotNull KtElement element,
|
@NotNull KtElement element,
|
||||||
@NotNull VariableDescriptor variableDescriptor,
|
@NotNull VariableDescriptor variableDescriptor,
|
||||||
@NotNull ResolvedCall<?> resolvedCall
|
@NotNull VariableDescriptor target,
|
||||||
|
@Nullable ReceiverValue dispatchReceiver
|
||||||
) {
|
) {
|
||||||
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
||||||
|
|
||||||
@@ -2850,7 +2868,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
PropertyReferenceCodegen codegen = new PropertyReferenceCodegen(
|
PropertyReferenceCodegen codegen = new PropertyReferenceCodegen(
|
||||||
state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION),
|
state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION),
|
||||||
element, classBuilder, resolvedCall
|
element, classBuilder, target, dispatchReceiver
|
||||||
);
|
);
|
||||||
codegen.generate();
|
codegen.generate();
|
||||||
|
|
||||||
@@ -3371,10 +3389,16 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
@Override
|
@Override
|
||||||
public StackValue visitProperty(@NotNull KtProperty property, StackValue receiver) {
|
public StackValue visitProperty(@NotNull KtProperty property, StackValue receiver) {
|
||||||
KtExpression initializer = property.getInitializer();
|
KtExpression initializer = property.getInitializer();
|
||||||
if (initializer == null) {
|
KtExpression delegateExpression = property.getDelegateExpression();
|
||||||
return StackValue.none();
|
|
||||||
|
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();
|
return StackValue.none();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3412,11 +3436,27 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
return StackValue.none();
|
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(
|
private void initializeLocalVariable(
|
||||||
@NotNull KtVariableDeclaration variableDeclaration,
|
@NotNull KtVariableDeclaration variableDeclaration,
|
||||||
@NotNull StackValue initializer
|
@NotNull StackValue initializer
|
||||||
) {
|
) {
|
||||||
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, variableDeclaration);
|
LocalVariableDescriptor variableDescriptor = (LocalVariableDescriptor) bindingContext.get(VARIABLE, variableDeclaration);
|
||||||
|
|
||||||
if (KtPsiUtil.isScriptDeclaration(variableDeclaration)) {
|
if (KtPsiUtil.isScriptDeclaration(variableDeclaration)) {
|
||||||
return;
|
return;
|
||||||
@@ -3430,7 +3470,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
|
Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
|
||||||
assert variableDescriptor != null;
|
assert variableDescriptor != null;
|
||||||
|
|
||||||
Type varType = asmType(variableDescriptor.getType());
|
Type varType = getVariableTypeNoSharing(variableDescriptor);
|
||||||
|
|
||||||
StackValue storeTo = sharedVarType == null ? StackValue.local(index, varType) : StackValue.shared(index, varType);
|
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);
|
markLineNumber(variableDeclaration, false);
|
||||||
|
|
||||||
storeTo.storeSelector(initializer.type, v);
|
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
|
@NotNull
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.descriptors.*;
|
|||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
|
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
|
||||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityUtilsKt;
|
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityUtilsKt;
|
||||||
|
import org.jetbrains.kotlin.psi.Call;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.psi.KtFunction;
|
import org.jetbrains.kotlin.psi.KtFunction;
|
||||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.CodeFragmentUtilKt;
|
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.DescriptorToSourceUtils;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
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.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
|
||||||
import java.io.File;
|
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.ABSTRACT;
|
||||||
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
|
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
|
||||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||||
|
import static org.jetbrains.kotlin.resolve.BindingContext.DELEGATED_PROPERTY_CALL;
|
||||||
|
|
||||||
public class JvmCodegenUtil {
|
public class JvmCodegenUtil {
|
||||||
|
|
||||||
@@ -223,4 +227,40 @@ public class JvmCodegenUtil {
|
|||||||
if (!(descriptor instanceof JavaPropertyDescriptor)) return false;
|
if (!(descriptor instanceof JavaPropertyDescriptor)) return false;
|
||||||
return descriptor.isConst();
|
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.builtins.DefaultBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
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.ModuleDescriptorImpl;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor;
|
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
@@ -39,6 +40,8 @@ public class JvmRuntimeTypes {
|
|||||||
private final ClassDescriptor functionReference;
|
private final ClassDescriptor functionReference;
|
||||||
private final List<ClassDescriptor> propertyReferences;
|
private final List<ClassDescriptor> propertyReferences;
|
||||||
private final List<ClassDescriptor> mutablePropertyReferences;
|
private final List<ClassDescriptor> mutablePropertyReferences;
|
||||||
|
private final ClassDescriptor localVariableReference;
|
||||||
|
private final ClassDescriptor mutableLocalVariableReference;
|
||||||
|
|
||||||
public JvmRuntimeTypes() {
|
public JvmRuntimeTypes() {
|
||||||
ModuleDescriptorImpl module = TargetPlatformKt.createModule(
|
ModuleDescriptorImpl module = TargetPlatformKt.createModule(
|
||||||
@@ -47,9 +50,12 @@ public class JvmRuntimeTypes {
|
|||||||
LockBasedStorageManager.NO_LOCKS,
|
LockBasedStorageManager.NO_LOCKS,
|
||||||
DefaultBuiltIns.getInstance());
|
DefaultBuiltIns.getInstance());
|
||||||
PackageFragmentDescriptor kotlinJvmInternal = new MutablePackageFragmentDescriptor(module, new FqName("kotlin.jvm.internal"));
|
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.lambda = createClass(kotlinJvmInternal, "Lambda");
|
||||||
this.functionReference = createClass(kotlinJvmInternal, "FunctionReference");
|
this.functionReference = createClass(kotlinJvmInternal, "FunctionReference");
|
||||||
|
this.localVariableReference = createClass(kotlinReflectJvmInternal, "LocalVariableReference");
|
||||||
|
this.mutableLocalVariableReference = createClass(kotlinReflectJvmInternal, "MutableLocalVariableReference");
|
||||||
this.propertyReferences = new ArrayList<ClassDescriptor>(3);
|
this.propertyReferences = new ArrayList<ClassDescriptor>(3);
|
||||||
this.mutablePropertyReferences = new ArrayList<ClassDescriptor>(3);
|
this.mutablePropertyReferences = new ArrayList<ClassDescriptor>(3);
|
||||||
|
|
||||||
@@ -110,7 +116,11 @@ public class JvmRuntimeTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@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) +
|
int arity = (descriptor.getExtensionReceiverParameter() != null ? 1 : 0) +
|
||||||
(descriptor.getDispatchReceiverParameter() != null ? 1 : 0);
|
(descriptor.getDispatchReceiverParameter() != null ? 1 : 0);
|
||||||
return (descriptor.isVar() ? mutablePropertyReferences : propertyReferences).get(arity).getDefaultType();
|
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.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
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.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||||
import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
|
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.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
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.kotlin.utils.sure
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
@@ -44,13 +45,13 @@ class PropertyReferenceCodegen(
|
|||||||
context: ClassContext,
|
context: ClassContext,
|
||||||
expression: KtElement,
|
expression: KtElement,
|
||||||
classBuilder: ClassBuilder,
|
classBuilder: ClassBuilder,
|
||||||
resolvedCall: ResolvedCall<*>
|
private val target: VariableDescriptor,
|
||||||
|
dispatchReceiver: ReceiverValue?
|
||||||
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
|
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
|
||||||
private val classDescriptor = context.contextDescriptor
|
private val classDescriptor = context.contextDescriptor
|
||||||
private val asmType = typeMapper.mapClass(classDescriptor)
|
private val asmType = typeMapper.mapClass(classDescriptor)
|
||||||
|
|
||||||
private val target = resolvedCall.resultingDescriptor as VariableDescriptor
|
private val dispatchReceiverType = dispatchReceiver?.type
|
||||||
private val dispatchReceiverType = resolvedCall.dispatchReceiver?.type
|
|
||||||
private val extensionReceiverType = target.extensionReceiverParameter?.type
|
private val extensionReceiverType = target.extensionReceiverParameter?.type
|
||||||
|
|
||||||
private val receiverCount =
|
private val receiverCount =
|
||||||
@@ -85,8 +86,10 @@ class PropertyReferenceCodegen(
|
|||||||
invokespecial(superAsmType.internalName, "<init>", "()V", false)
|
invokespecial(superAsmType.internalName, "<init>", "()V", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
generateMethod("property reference getOwner", ACC_PUBLIC, method("getOwner", K_DECLARATION_CONTAINER_TYPE)) {
|
if (target !is LocalVariableDescriptor) {
|
||||||
ClosureCodegen.generateCallableReferenceDeclarationContainer(this, target, state)
|
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)) {
|
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)) {
|
generateMethod("property reference getSignature", ACC_PUBLIC, method("getSignature", JAVA_STRING_TYPE)) {
|
||||||
aconst(getPropertyReferenceSignature(target as PropertyDescriptor, state))
|
aconst(getPropertyReferenceSignature(target as VariableDescriptorWithAccessors, state))
|
||||||
}
|
}
|
||||||
|
|
||||||
generateAccessors()
|
generateAccessors()
|
||||||
@@ -125,7 +128,10 @@ class PropertyReferenceCodegen(
|
|||||||
StackValue.local(index + 1, OBJECT_TYPE).put(typeMapper.mapType(type), this)
|
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)
|
accessorBody(value)
|
||||||
}
|
}
|
||||||
@@ -168,9 +174,9 @@ class PropertyReferenceCodegen(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getPropertyReferenceSignature(property: PropertyDescriptor, state: GenerationState): String {
|
fun getPropertyReferenceSignature(property: VariableDescriptorWithAccessors, state: GenerationState): String {
|
||||||
val getter =
|
val getter =
|
||||||
property.getter ?: DescriptorFactory.createDefaultGetter(property, Annotations.EMPTY).apply {
|
property.getter ?: DescriptorFactory.createDefaultGetter(property as PropertyDescriptor, Annotations.EMPTY).apply {
|
||||||
initialize(property.type)
|
initialize(property.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -152,6 +152,17 @@ public abstract class StackValue {
|
|||||||
return new Local(index, type);
|
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
|
@NotNull
|
||||||
public static StackValue shared(int index, @NotNull Type type) {
|
public static StackValue shared(int index, @NotNull Type type) {
|
||||||
return new Shared(index, type);
|
return new Shared(index, type);
|
||||||
@@ -245,17 +256,8 @@ public abstract class StackValue {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static StackValue changeReceiverForFieldAndSharedVar(@NotNull StackValueWithSimpleReceiver stackValue, @Nullable StackValue newReceiver) {
|
public static StackValue changeReceiverForFieldAndSharedVar(@NotNull StackValueWithSimpleReceiver stackValue, @Nullable StackValue newReceiver) {
|
||||||
//TODO static check
|
//TODO static check
|
||||||
if (newReceiver != null) {
|
if (newReceiver == null || stackValue.isStaticPut) return stackValue;
|
||||||
if (!stackValue.isStaticPut) {
|
return stackValue.changeReceiver(newReceiver);
|
||||||
if (stackValue instanceof Field) {
|
|
||||||
return field((Field) stackValue, newReceiver);
|
|
||||||
}
|
|
||||||
else if (stackValue instanceof FieldForSharedVar) {
|
|
||||||
return fieldForSharedVar((FieldForSharedVar) stackValue, newReceiver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return stackValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@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 static class OnStack extends StackValue {
|
||||||
public OnStack(Type type) {
|
public OnStack(Type type) {
|
||||||
super(type);
|
super(type);
|
||||||
@@ -1079,6 +1131,11 @@ public abstract class StackValue {
|
|||||||
coerceFrom(topOfStackType, v);
|
coerceFrom(topOfStackType, v);
|
||||||
v.visitFieldInsn(isStaticStore ? PUTSTATIC : PUTFIELD, owner.getInternalName(), name, this.type.getDescriptor());
|
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 {
|
static class Property extends StackValueWithSimpleReceiver {
|
||||||
@@ -1297,6 +1354,11 @@ public abstract class StackValue {
|
|||||||
coerceFrom(topOfStackType, v);
|
coerceFrom(topOfStackType, v);
|
||||||
v.visitFieldInsn(PUTFIELD, sharedTypeForType(type).getInternalName(), "element", refType(type).getDescriptor());
|
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 {
|
private static class ThisOuter extends StackValue {
|
||||||
@@ -1558,6 +1620,10 @@ public abstract class StackValue {
|
|||||||
rightSide.put(rightSide.type, v);
|
rightSide.put(rightSide.type, v);
|
||||||
storeSelector(rightSide.type, v);
|
storeSelector(rightSide.type, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected StackValueWithSimpleReceiver changeReceiver(@NotNull StackValue newReceiver) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ComplexReceiver extends StackValue {
|
private static class ComplexReceiver extends StackValue {
|
||||||
|
|||||||
+39
-5
@@ -23,6 +23,7 @@ import com.intellij.util.containers.Stack;
|
|||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.builtins.ReflectionTypes;
|
||||||
import org.jetbrains.kotlin.cfg.WhenChecker;
|
import org.jetbrains.kotlin.cfg.WhenChecker;
|
||||||
import org.jetbrains.kotlin.codegen.*;
|
import org.jetbrains.kotlin.codegen.*;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
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.SwitchCodegenUtil;
|
||||||
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
|
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
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.FileClasses;
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
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.ConstantValue;
|
||||||
import org.jetbrains.kotlin.resolve.constants.EnumValue;
|
import org.jetbrains.kotlin.resolve.constants.EnumValue;
|
||||||
import org.jetbrains.kotlin.resolve.constants.NullValue;
|
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.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
|
|
||||||
@@ -317,12 +320,43 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
fileClassesProvider);
|
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
|
@Override
|
||||||
public void visitProperty(@NotNull KtProperty property) {
|
public void visitProperty(@NotNull KtProperty property) {
|
||||||
DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property);
|
DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property);
|
||||||
// working around a problem with shallow analysis
|
// working around a problem with shallow analysis
|
||||||
if (descriptor == null) return;
|
if (descriptor == null) return;
|
||||||
|
|
||||||
|
if (descriptor instanceof LocalVariableDescriptor) {
|
||||||
|
recordLocalVariablePropertyMetadata((LocalVariableDescriptor) descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
String nameForClassOrPackageMember = getNameForClassOrPackageMember(descriptor);
|
String nameForClassOrPackageMember = getNameForClassOrPackageMember(descriptor);
|
||||||
if (nameForClassOrPackageMember != null) {
|
if (nameForClassOrPackageMember != null) {
|
||||||
nameStack.push(nameForClassOrPackageMember);
|
nameStack.push(nameForClassOrPackageMember);
|
||||||
@@ -332,11 +366,11 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KtPropertyDelegate delegate = property.getDelegate();
|
KtPropertyDelegate delegate = property.getDelegate();
|
||||||
if (delegate != null && descriptor instanceof PropertyDescriptor) {
|
if (delegate != null && descriptor instanceof VariableDescriptorWithAccessors) {
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
VariableDescriptorWithAccessors variableDescriptor = (VariableDescriptorWithAccessors) descriptor;
|
||||||
String name = inventAnonymousClassName();
|
String name = inventAnonymousClassName();
|
||||||
KotlinType supertype = runtimeTypes.getSupertypeForPropertyReference(propertyDescriptor);
|
KotlinType supertype = runtimeTypes.getSupertypeForPropertyReference(variableDescriptor);
|
||||||
ClassDescriptor classDescriptor = recordClassForCallable(delegate, propertyDescriptor, Collections.singleton(supertype), name);
|
ClassDescriptor classDescriptor = recordClassForCallable(delegate, variableDescriptor, Collections.singleton(supertype), name);
|
||||||
recordClosure(classDescriptor, 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 =
|
public static final WritableSlice<String, List<WhenByEnumsMapping>> MAPPINGS_FOR_WHENS_BY_ENUM_IN_CLASS_FILE =
|
||||||
Slices.createSimpleSlice();
|
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 {
|
static {
|
||||||
BasicWritableSlice.initSliceDebugNames(CodegenBinding.class);
|
BasicWritableSlice.initSliceDebugNames(CodegenBinding.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,10 +51,19 @@ public interface LocalLookup {
|
|||||||
Type classType
|
Type classType
|
||||||
) {
|
) {
|
||||||
VariableDescriptor vd = (VariableDescriptor) d;
|
VariableDescriptor vd = (VariableDescriptor) d;
|
||||||
|
VariableDescriptor originalVariableDescriptor = vd;
|
||||||
|
|
||||||
boolean idx = localLookup != null && localLookup.lookupLocal(vd);
|
boolean idx = localLookup != null && localLookup.lookupLocal(vd);
|
||||||
if (!idx) return null;
|
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 sharedVarType = state.getTypeMapper().getSharedVarType(vd);
|
||||||
Type localType = state.getTypeMapper().mapType(vd);
|
Type localType = state.getTypeMapper().mapType(vd);
|
||||||
Type type = sharedVarType != null ? sharedVarType : localType;
|
Type type = sharedVarType != null ? sharedVarType : localType;
|
||||||
@@ -71,6 +80,18 @@ public interface LocalLookup {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
innerValue = StackValue.field(type, classType, fieldName, false, thiz, vd);
|
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);
|
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.BothSignatureWriter;
|
||||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor;
|
||||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||||
@@ -630,6 +631,13 @@ public class KotlinTypeMapper {
|
|||||||
return new CallableMethod(owner, owner, defaultImplDesc, method, INVOKESPECIAL, null, null, null);
|
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();
|
DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
|
||||||
|
|
||||||
FunctionDescriptor functionDescriptor = unwrapFakeOverride(descriptor.getOriginal());
|
FunctionDescriptor functionDescriptor = unwrapFakeOverride(descriptor.getOriginal());
|
||||||
@@ -1354,14 +1362,22 @@ public class KotlinTypeMapper {
|
|||||||
if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
|
if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
|
||||||
return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
|
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();
|
ReceiverParameterDescriptor receiverParameter = ((CallableDescriptor) descriptor).getExtensionReceiverParameter();
|
||||||
assert receiverParameter != null : "Callable should have a receiver parameter: " + descriptor;
|
assert receiverParameter != null : "Callable should have a receiver parameter: " + descriptor;
|
||||||
return StackValue.sharedTypeForType(mapType(receiverParameter.getType()));
|
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 StackValue.sharedTypeForType(mapType(((VariableDescriptor) descriptor).getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
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);
|
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")
|
@TestMetadata("castGetReturnType.kt")
|
||||||
public void testCastGetReturnType() throws Exception {
|
public void testCastGetReturnType() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/castGetReturnType.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/castGetReturnType.kt");
|
||||||
@@ -4861,6 +4885,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("privateVar.kt")
|
||||||
public void testPrivateVar() throws Exception {
|
public void testPrivateVar() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/privateVar.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/privateVar.kt");
|
||||||
|
|||||||
@@ -65,6 +65,12 @@ public class ScriptCodegenTestGenerated extends AbstractScriptCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("localFunction.kts")
|
||||||
public void testLocalFunction() throws Exception {
|
public void testLocalFunction() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/localFunction.kts");
|
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)
|
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