KT-3118 NoSuchFieldError on private property without backing field &&
KT-3551 Wrong synthetic accessor implementation
This commit is contained in:
@@ -30,7 +30,7 @@ import java.util.Collections;
|
|||||||
|
|
||||||
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
|
public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
|
||||||
public AccessorForPropertyDescriptor(PropertyDescriptor pd, DeclarationDescriptor containingDeclaration, int index) {
|
public AccessorForPropertyDescriptor(PropertyDescriptor pd, DeclarationDescriptor containingDeclaration, int index) {
|
||||||
super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC,
|
super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.LOCAL,
|
||||||
pd.isVar(), Name.identifier(pd.getName() + "$b$" + index),
|
pd.isVar(), Name.identifier(pd.getName() + "$b$" + index),
|
||||||
Kind.DECLARATION);
|
Kind.DECLARATION);
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
|
|||||||
|
|
||||||
public static class Getter extends PropertyGetterDescriptorImpl {
|
public static class Getter extends PropertyGetterDescriptorImpl {
|
||||||
public Getter(AccessorForPropertyDescriptor property) {
|
public Getter(AccessorForPropertyDescriptor property) {
|
||||||
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC,
|
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.LOCAL,
|
||||||
false,
|
false,
|
||||||
false, Kind.DECLARATION);
|
false, Kind.DECLARATION);
|
||||||
initialize(property.getType());
|
initialize(property.getType());
|
||||||
@@ -50,7 +50,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
|
|||||||
|
|
||||||
public static class Setter extends PropertySetterDescriptorImpl {
|
public static class Setter extends PropertySetterDescriptorImpl {
|
||||||
public Setter(AccessorForPropertyDescriptor property) {
|
public Setter(AccessorForPropertyDescriptor property) {
|
||||||
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC,
|
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.LOCAL,
|
||||||
false,
|
false,
|
||||||
false, Kind.DECLARATION);
|
false, Kind.DECLARATION);
|
||||||
initializeDefault();
|
initializeDefault();
|
||||||
|
|||||||
@@ -130,11 +130,14 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isAbstract(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||||
return (functionDescriptor.getModality() == Modality.ABSTRACT
|
return (functionDescriptor.getModality() == Modality.ABSTRACT
|
||||||
|| isInterface(functionDescriptor.getContainingDeclaration()))
|
|| isInterface(functionDescriptor.getContainingDeclaration()))
|
||||||
&& !isStatic(kind)
|
&& !isStaticMethod(kind, functionDescriptor);
|
||||||
&& kind != OwnerKind.TRAIT_IMPL;
|
}
|
||||||
|
|
||||||
|
public static boolean isStaticMethod(OwnerKind kind, FunctionDescriptor functionDescriptor) {
|
||||||
|
return isStatic(kind) || kind == OwnerKind.TRAIT_IMPL || JetTypeMapper.isAccessor(functionDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isStatic(OwnerKind kind) {
|
public static boolean isStatic(OwnerKind kind) {
|
||||||
@@ -142,9 +145,6 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||||
boolean isStatic = isStatic(kind);
|
|
||||||
boolean isAbstract = isAbstract(functionDescriptor, kind);
|
|
||||||
|
|
||||||
int flags = getCommonCallableFlags(functionDescriptor);
|
int flags = getCommonCallableFlags(functionDescriptor);
|
||||||
|
|
||||||
if (functionDescriptor.getModality() == Modality.FINAL && !(functionDescriptor instanceof ConstructorDescriptor)) {
|
if (functionDescriptor.getModality() == Modality.FINAL && !(functionDescriptor instanceof ConstructorDescriptor)) {
|
||||||
@@ -155,19 +155,21 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStatic || kind == OwnerKind.TRAIT_IMPL) {
|
if (isStaticMethod(kind, functionDescriptor)) {
|
||||||
flags |= ACC_STATIC;
|
flags |= ACC_STATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAbstract) flags |= ACC_ABSTRACT;
|
if (isAbstractMethod(functionDescriptor, kind)) {
|
||||||
|
flags |= ACC_ABSTRACT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JetTypeMapper.isAccessor(functionDescriptor)) {
|
||||||
|
flags |= ACC_SYNTHETIC;
|
||||||
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getConstructorAsmFlags(FunctionDescriptor functionDescriptor) {
|
|
||||||
return getCommonCallableFlags(functionDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) {
|
private static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) {
|
||||||
int flags = getVisibilityAccessFlag(functionDescriptor);
|
int flags = getVisibilityAccessFlag(functionDescriptor);
|
||||||
flags |= getVarargsFlag(functionDescriptor);
|
flags |= getVarargsFlag(functionDescriptor);
|
||||||
|
|||||||
@@ -262,4 +262,14 @@ public class CodegenUtil {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean couldUseDirectAccessToProperty(PropertyDescriptor propertyDescriptor, boolean forGetter, boolean isInsideClass) {
|
||||||
|
PropertyAccessorDescriptor accessorDescriptor = forGetter ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
||||||
|
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
||||||
|
return isInsideClass &&
|
||||||
|
!isExtensionProperty &&
|
||||||
|
(accessorDescriptor == null ||
|
||||||
|
accessorDescriptor.isDefault() &&
|
||||||
|
(!DescriptorUtils.isExternallyAccessible(propertyDescriptor) || accessorDescriptor.getModality() == Modality.FINAL));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,6 +297,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) {
|
private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) {
|
||||||
|
return getSuperCallLabelTarget(expression, bindingContext, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression, BindingContext bindingContext, CodegenContext context) {
|
||||||
PsiElement labelPsi = bindingContext.get(BindingContext.LABEL_TARGET, expression.getTargetLabel());
|
PsiElement labelPsi = bindingContext.get(BindingContext.LABEL_TARGET, expression.getTargetLabel());
|
||||||
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, labelPsi);
|
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, labelPsi);
|
||||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
||||||
@@ -305,7 +310,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return labelTarget;
|
return labelTarget;
|
||||||
}
|
}
|
||||||
assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class";
|
assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class";
|
||||||
ClassDescriptor target = getParentContextSubclassOf((ClassDescriptor) descriptor).getThisDescriptor();
|
ClassDescriptor target = getParentContextSubclassOf((ClassDescriptor) descriptor, context).getThisDescriptor();
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1552,12 +1557,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
|
|
||||||
boolean isStatic = container instanceof NamespaceDescriptor;
|
|
||||||
boolean directToField =
|
boolean directToField =
|
||||||
expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL;
|
expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL;
|
||||||
JetExpression r = getReceiverForSelector(expression);
|
JetExpression r = getReceiverForSelector(expression);
|
||||||
boolean isSuper = r instanceof JetSuperExpression;
|
boolean isSuper = r instanceof JetSuperExpression;
|
||||||
propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor);
|
propertyDescriptor = accessablePropertyDescriptor(context, propertyDescriptor);
|
||||||
StackValue.Property iValue =
|
StackValue.Property iValue =
|
||||||
intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null);
|
intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null);
|
||||||
if (directToField) {
|
if (directToField) {
|
||||||
@@ -1662,6 +1666,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
boolean forceField,
|
boolean forceField,
|
||||||
@Nullable JetSuperExpression superExpression
|
@Nullable JetSuperExpression superExpression
|
||||||
) {
|
) {
|
||||||
|
return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, state, context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static StackValue.Property intermediateValueForProperty(
|
||||||
|
PropertyDescriptor propertyDescriptor,
|
||||||
|
boolean forceField,
|
||||||
|
@Nullable JetSuperExpression superExpression,
|
||||||
|
@NotNull GenerationState state,
|
||||||
|
@NotNull CodegenContext context,
|
||||||
|
@NotNull boolean forceSpecialFlag
|
||||||
|
) {
|
||||||
|
JetTypeMapper typeMapper = state.getTypeMapper();
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||||
assert containingDeclaration != null;
|
assert containingDeclaration != null;
|
||||||
@@ -1670,23 +1687,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
boolean isSuper = superExpression != null;
|
boolean isSuper = superExpression != null;
|
||||||
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
|
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
|
||||||
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
|
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
|
||||||
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
|
||||||
|
|
||||||
CallableMethod callableGetter = null;
|
CallableMethod callableGetter = null;
|
||||||
CallableMethod callableSetter = null;
|
CallableMethod callableSetter = null;
|
||||||
|
|
||||||
if (!forceField) {
|
if (!forceField) {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
if (isInsideClass &&
|
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass)) {
|
||||||
!isExtensionProperty &&
|
|
||||||
(propertyDescriptor.getGetter() == null ||
|
|
||||||
!DescriptorUtils.isExternallyAccessible(propertyDescriptor) ||
|
|
||||||
propertyDescriptor.getGetter().isDefault() && propertyDescriptor.getGetter().getModality() == Modality.FINAL)) {
|
|
||||||
callableGetter = null;
|
callableGetter = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isSuper && !isInterface(containingDeclaration)) {
|
if (isSuper && !isInterface(containingDeclaration)) {
|
||||||
ClassDescriptor owner = getSuperCallLabelTarget(superExpression);
|
ClassDescriptor owner = getSuperCallLabelTarget(superExpression, state.getBindingContext(), context);
|
||||||
CodegenContext c = context.findParentContextWithDescriptor(owner);
|
CodegenContext c = context.findParentContextWithDescriptor(owner);
|
||||||
assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor;
|
assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor;
|
||||||
if (c != context.getParentContext()) {
|
if (c != context.getParentContext()) {
|
||||||
@@ -1694,23 +1706,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor);
|
propertyDescriptor = accessablePropertyDescriptor(context, propertyDescriptor);
|
||||||
|
|
||||||
if (propertyDescriptor.getGetter() != null) {
|
if (propertyDescriptor.getGetter() != null) {
|
||||||
callableGetter = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
callableGetter = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper || forceSpecialFlag, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propertyDescriptor.isVar()) {
|
if (propertyDescriptor.isVar()) {
|
||||||
if (propertyDescriptor.getSetter() != null) {
|
if (propertyDescriptor.getSetter() != null) {
|
||||||
if (isInsideClass && !isExtensionProperty &&
|
if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass)) {
|
||||||
(!DescriptorUtils.isExternallyAccessible(propertyDescriptor) ||
|
|
||||||
propertyDescriptor.getSetter().isDefault() &&
|
|
||||||
propertyDescriptor.getSetter().getModality() == Modality.FINAL)) {
|
|
||||||
callableSetter = null;
|
callableSetter = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
callableSetter = typeMapper.mapToCallableMethod(propertyDescriptor.getSetter(), isSuper, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
callableSetter = typeMapper.mapToCallableMethod(propertyDescriptor.getSetter(), isSuper || forceSpecialFlag, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1721,13 +1730,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
propertyDescriptor = unwrapFakeOverride(propertyDescriptor);
|
propertyDescriptor = unwrapFakeOverride(propertyDescriptor);
|
||||||
if (callableMethod == null) {
|
if (callableMethod == null) {
|
||||||
owner = typeMapper.getOwner(propertyDescriptor, contextKind(), isInsideModule);
|
owner = typeMapper.getOwner(propertyDescriptor, context.getContextKind(), isInsideModule);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
owner = callableMethod.getOwner();
|
owner = callableMethod.getOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
return StackValue.property(propertyDescriptor, owner, asmType(propertyDescriptor.getOriginal().getType()),
|
return StackValue.property(propertyDescriptor, owner, typeMapper.mapType(propertyDescriptor.getOriginal().getType()),
|
||||||
isStatic, callableGetter, callableSetter, state);
|
isStatic, callableGetter, callableSetter, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1814,7 +1823,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PropertyDescriptor accessablePropertyDescriptor(PropertyDescriptor propertyDescriptor) {
|
private static PropertyDescriptor accessablePropertyDescriptor(CodegenContext context, PropertyDescriptor propertyDescriptor) {
|
||||||
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
|
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
|
||||||
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
|
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
|
||||||
|
|
||||||
@@ -1919,7 +1928,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the first parent of the current context which corresponds to a subclass of a given class
|
// Find the first parent of the current context which corresponds to a subclass of a given class
|
||||||
private CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor) {
|
@NotNull
|
||||||
|
private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) {
|
||||||
CodegenContext c = context;
|
CodegenContext c = context;
|
||||||
while (true) {
|
while (true) {
|
||||||
if ((c instanceof ClassContext || c instanceof AnonymousClassContext) &&
|
if ((c instanceof ClassContext || c instanceof AnonymousClassContext) &&
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ public class FunctionCodegen extends GenerationStateAware {
|
|||||||
genJetAnnotations(mv, functionDescriptor, jvmSignature);
|
genJetAnnotations(mv, functionDescriptor, jvmSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAbstract(functionDescriptor, methodContext.getContextKind())) return;
|
if (isAbstractMethod(functionDescriptor, methodContext.getContextKind())) return;
|
||||||
|
|
||||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||||
genStubCode(mv);
|
genStubCode(mv);
|
||||||
@@ -227,13 +227,13 @@ public class FunctionCodegen extends GenerationStateAware {
|
|||||||
List<JvmMethodParameterSignature> params = jvmMethodSignature.getKotlinParameterTypes();
|
List<JvmMethodParameterSignature> params = jvmMethodSignature.getKotlinParameterTypes();
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
|
|
||||||
boolean isStatic = isStatic(ownerKind) || ownerKind == OwnerKind.TRAIT_IMPL;
|
boolean isStatic = AsmUtil.isStaticMethod(ownerKind, functionDescriptor);
|
||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
//add this
|
//add this
|
||||||
if (thisType != null) {
|
if (thisType != null) {
|
||||||
mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift);
|
mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift);
|
||||||
} else {
|
} else {
|
||||||
//sometimes there is no thisType for callable reference
|
//TODO: provide thisType for callable reference
|
||||||
}
|
}
|
||||||
shift++;
|
shift++;
|
||||||
}
|
}
|
||||||
@@ -334,14 +334,13 @@ public class FunctionCodegen extends GenerationStateAware {
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
|
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
|
||||||
assert jvmSignature instanceof JvmPropertyAccessorSignature;
|
assert jvmSignature instanceof JvmPropertyAccessorSignature : "jvmSignature for property should have JvmPropertyAccessorSignature type";
|
||||||
PropertyCodegen.generateJetPropertyAnnotation(mv, (JvmPropertyAccessorSignature) jvmSignature,
|
PropertyCodegen.generateJetPropertyAnnotation(mv, (JvmPropertyAccessorSignature) jvmSignature,
|
||||||
((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty(), functionDescriptor.getVisibility());
|
((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty(), functionDescriptor.getVisibility());
|
||||||
}
|
}
|
||||||
else if (functionDescriptor instanceof SimpleFunctionDescriptor) {
|
else if (functionDescriptor instanceof SimpleFunctionDescriptor) {
|
||||||
if (jvmSignature instanceof JvmPropertyAccessorSignature) {
|
assert !(jvmSignature instanceof JvmPropertyAccessorSignature) : "jvmSignature for function shouldn't have JvmPropertyAccessorSignature type";
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
Modality modality = functionDescriptor.getModality();
|
Modality modality = functionDescriptor.getModality();
|
||||||
JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv);
|
JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv);
|
||||||
int kotlinFlags = getFlagsForVisibility(functionDescriptor.getVisibility());
|
int kotlinFlags = getFlagsForVisibility(functionDescriptor.getVisibility());
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ public abstract class FunctionGenerationStrategy<T extends CallableDescriptor> {
|
|||||||
public abstract static class CodegenBased<T extends CallableDescriptor> extends FunctionGenerationStrategy<T> {
|
public abstract static class CodegenBased<T extends CallableDescriptor> extends FunctionGenerationStrategy<T> {
|
||||||
|
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
|
|
||||||
protected final T callableDescriptor;
|
protected final T callableDescriptor;
|
||||||
|
|
||||||
public CodegenBased(@NotNull GenerationState state, T callableDescriptor) {
|
public CodegenBased(@NotNull GenerationState state, T callableDescriptor) {
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import org.jetbrains.jet.codegen.context.ConstructorContext;
|
|||||||
import org.jetbrains.jet.codegen.context.MethodContext;
|
import org.jetbrains.jet.codegen.context.MethodContext;
|
||||||
import org.jetbrains.jet.codegen.signature.*;
|
import org.jetbrains.jet.codegen.signature.*;
|
||||||
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
||||||
import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter;
|
|
||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
|
import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
|
||||||
@@ -79,9 +78,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
private JetType superClassType;
|
private JetType superClassType;
|
||||||
private final Type classAsmType;
|
private final Type classAsmType;
|
||||||
|
|
||||||
|
private final FunctionCodegen functionCodegen;
|
||||||
|
private final PropertyCodegen propertyCodegen;
|
||||||
|
|
||||||
public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
||||||
super(aClass, context, v, state);
|
super(aClass, context, v, state);
|
||||||
classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL);
|
this.classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL);
|
||||||
|
this.functionCodegen = new FunctionCodegen(context, v, state);
|
||||||
|
this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -440,7 +444,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
generateTraitMethods();
|
generateTraitMethods();
|
||||||
|
|
||||||
generateAccessors();
|
generateSyntheticAccessors();
|
||||||
|
|
||||||
generateEnumMethods();
|
generateEnumMethods();
|
||||||
|
|
||||||
@@ -798,13 +802,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateAccessors() {
|
private void generateSyntheticAccessors() {
|
||||||
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : context.getAccessors().entrySet()) {
|
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : context.getAccessors().entrySet()) {
|
||||||
genAccessor(entry);
|
generateSyntheticAccessor(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void genAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) {
|
private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) {
|
||||||
if (entry.getValue() instanceof FunctionDescriptor) {
|
if (entry.getValue() instanceof FunctionDescriptor) {
|
||||||
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
|
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
|
||||||
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
|
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
|
||||||
@@ -817,7 +821,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
Type[] argTypes = method.getArgumentTypes();
|
Type[] argTypes = method.getArgumentTypes();
|
||||||
|
|
||||||
String owner = typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isCallInsideSameModuleAsDeclared(original, context)).getInternalName();
|
String owner = typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isCallInsideSameModuleAsDeclared(original, context)).getInternalName();
|
||||||
MethodVisitor mv = v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, bridge.getName().getName(),
|
MethodVisitor mv = v.newMethod(null, ACC_SYNTHETIC | ACC_STATIC, bridge.getName().getName(),
|
||||||
method.getDescriptor(), null, null);
|
method.getDescriptor(), null, null);
|
||||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||||
genStubCode(mv);
|
genStubCode(mv);
|
||||||
@@ -850,86 +854,46 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
else if (entry.getValue() instanceof PropertyDescriptor) {
|
else if (entry.getValue() instanceof PropertyDescriptor) {
|
||||||
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
||||||
PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
||||||
|
final StackValue.Property property = ExpressionCodegen.intermediateValueForProperty(original, false, null, state, context, true);
|
||||||
{
|
|
||||||
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
|
|
||||||
JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
|
|
||||||
Method originalMethod = originalSignature.getAsmMethod();
|
|
||||||
MethodVisitor mv =
|
|
||||||
v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, method.getName(), method.getDescriptor(), null, null);
|
|
||||||
PropertyGetterDescriptor getter = bridge.getGetter();
|
|
||||||
assert getter != null;
|
|
||||||
PropertyCodegen.generateJetPropertyAnnotation(mv,
|
|
||||||
originalSignature,
|
|
||||||
original,
|
|
||||||
getter.getVisibility());
|
|
||||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
|
||||||
genStubCode(mv);
|
|
||||||
}
|
|
||||||
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
|
||||||
mv.visitCode();
|
|
||||||
|
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
|
||||||
|
|
||||||
|
PropertyGetterDescriptor getter = bridge.getGetter();
|
||||||
|
assert getter != null;
|
||||||
|
functionCodegen.generateMethod(null, typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION), false, getter,
|
||||||
|
new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) {
|
||||||
|
@Override
|
||||||
|
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
||||||
|
InstructionAdapter iv = codegen.v;
|
||||||
iv.load(0, OBJECT_TYPE);
|
iv.load(0, OBJECT_TYPE);
|
||||||
boolean hasBackingField = Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, original));
|
property.put(property.type, iv);
|
||||||
boolean isInsideModule = isCallInsideSameModuleAsDeclared(original, context);
|
iv.areturn(signature.getAsmMethod().getReturnType());
|
||||||
if (original.getVisibility() == Visibilities.PRIVATE && hasBackingField) {
|
|
||||||
iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isInsideModule).getInternalName(), original.getName().getName(),
|
|
||||||
originalMethod.getReturnType().getDescriptor());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isInsideModule).getInternalName(),
|
|
||||||
originalMethod.getName(), originalMethod.getDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
iv.areturn(method.getReturnType());
|
|
||||||
FunctionCodegen.endVisit(iv, "accessor", null);
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
|
||||||
if (bridge.isVar()) {
|
if (bridge.isVar()) {
|
||||||
Method method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
|
|
||||||
JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
|
|
||||||
Method originalMethod = originalSignature2.getAsmMethod();
|
|
||||||
MethodVisitor mv =
|
|
||||||
v.newMethod(null, ACC_STATIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
|
||||||
PropertySetterDescriptor setter = bridge.getSetter();
|
PropertySetterDescriptor setter = bridge.getSetter();
|
||||||
assert setter != null;
|
assert setter != null;
|
||||||
PropertyCodegen.generateJetPropertyAnnotation(mv,
|
|
||||||
originalSignature2,
|
|
||||||
original,
|
|
||||||
setter.getVisibility());
|
|
||||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
|
||||||
genStubCode(mv);
|
|
||||||
}
|
|
||||||
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
|
||||||
mv.visitCode();
|
|
||||||
|
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
functionCodegen.generateMethod(null, typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION), false, setter,
|
||||||
|
new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) {
|
||||||
|
@Override
|
||||||
|
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
||||||
|
InstructionAdapter iv = codegen.v;
|
||||||
|
|
||||||
iv.load(0, OBJECT_TYPE);
|
iv.load(0, OBJECT_TYPE);
|
||||||
Type[] argTypes = method.getArgumentTypes();
|
Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
|
||||||
for (int i = 1, reg = 1; i < argTypes.length; i++) {
|
for (int i = 1, reg = 1; i < argTypes.length; i++) {
|
||||||
Type argType = argTypes[i];
|
Type argType = argTypes[i];
|
||||||
iv.load(reg, argType);
|
iv.load(reg, argType);
|
||||||
//noinspection AssignmentToForLoopParameter
|
//noinspection AssignmentToForLoopParameter
|
||||||
reg += argType.getSize();
|
reg += argType.getSize();
|
||||||
}
|
}
|
||||||
boolean isInsideModule = isCallInsideSameModuleAsDeclared(original, context);
|
property.store(property.type, iv);
|
||||||
if (original.getVisibility() == Visibilities.PRIVATE && original.getModality() == Modality.FINAL) {
|
|
||||||
iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isInsideModule).getInternalName(), original.getName().getName(),
|
|
||||||
originalMethod.getArgumentTypes()[0].getDescriptor());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION, isInsideModule).getInternalName(),
|
|
||||||
originalMethod.getName(), originalMethod.getDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
iv.areturn(method.getReturnType());
|
iv.areturn(signature.getAsmMethod().getReturnType());
|
||||||
FunctionCodegen.endVisit(iv, "accessor", null);
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -979,26 +943,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
assert constructorDescriptor != null;
|
assert constructorDescriptor != null;
|
||||||
|
|
||||||
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
|
||||||
|
|
||||||
functionCodegen.generateMethod(null, constructorMethod, true, constructorDescriptor, constructorContext,
|
functionCodegen.generateMethod(null, constructorMethod, true, constructorDescriptor, constructorContext,
|
||||||
new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
|
new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
protected FrameMap createFrameMap(
|
protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull CodegenContext context) {
|
||||||
@NotNull JetTypeMapper typeMapper, @NotNull CodegenContext context
|
return new ConstructorFrameMap(callableMethod, callableDescriptor);
|
||||||
) {
|
}
|
||||||
return new ConstructorFrameMap(callableMethod, callableDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doGenerateBody(
|
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
||||||
ExpressionCodegen codegen, JvmMethodSignature signature
|
generatePrimaryConstructorImpl(callableDescriptor, codegen, closure);
|
||||||
) {
|
}
|
||||||
generatePrimaryConstructorImpl(callableDescriptor, codegen, closure);
|
}
|
||||||
}
|
);
|
||||||
});
|
|
||||||
|
|
||||||
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod.getAsmMethod(), constructorDescriptor,
|
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod.getAsmMethod(), constructorDescriptor,
|
||||||
OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT);
|
OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT);
|
||||||
@@ -1642,9 +1601,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void generateDelegates(ClassDescriptor toClass, StackValue field) {
|
protected void generateDelegates(ClassDescriptor toClass, StackValue field) {
|
||||||
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
|
||||||
PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen);
|
|
||||||
|
|
||||||
for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
|
for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
|
||||||
if (declaration instanceof CallableMemberDescriptor) {
|
if (declaration instanceof CallableMemberDescriptor) {
|
||||||
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
|
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
|
||||||
|
|||||||
@@ -550,7 +550,7 @@ public class JetTypeMapper extends BindingTraceAware {
|
|||||||
thisClass, receiverParameterType, null);
|
thisClass, receiverParameterType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
|
public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
|
||||||
return descriptor instanceof AccessorForFunctionDescriptor ||
|
return descriptor instanceof AccessorForFunctionDescriptor ||
|
||||||
descriptor instanceof AccessorForPropertyDescriptor ||
|
descriptor instanceof AccessorForPropertyDescriptor ||
|
||||||
descriptor instanceof AccessorForPropertyDescriptor.Getter ||
|
descriptor instanceof AccessorForPropertyDescriptor.Getter ||
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class C {
|
|||||||
class D {
|
class D {
|
||||||
private var foo = 1
|
private var foo = 1
|
||||||
set(i: Int) {
|
set(i: Int) {
|
||||||
foo = i + 1
|
$foo = i + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package testing
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
private val hello: String
|
||||||
|
get() { return "hello" }
|
||||||
|
|
||||||
|
fun sayHello() : String = hello
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return if (Test().sayHello() == "hello") "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
class Identifier() {
|
||||||
|
private var myNullable : Boolean = false
|
||||||
|
set(l : Boolean) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getValue() : Boolean {
|
||||||
|
return myNullable
|
||||||
|
}
|
||||||
|
|
||||||
|
class object {
|
||||||
|
fun init(isNullable : Boolean) : Identifier {
|
||||||
|
val id = Identifier()
|
||||||
|
id.myNullable = isNullable
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val id = Identifier.init(true)
|
||||||
|
return if (id.getValue() == false) return "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
class Test {
|
||||||
|
val a : String = "1"
|
||||||
|
private val b : String get() = a
|
||||||
|
|
||||||
|
fun outer() : Int {
|
||||||
|
return b.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = if (Test().outer() == 1) "OK" else "fail"
|
||||||
@@ -3386,6 +3386,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest("compiler/testData/codegen/box/properties/kt2892.kt");
|
doTest("compiler/testData/codegen/box/properties/kt2892.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt3118.kt")
|
||||||
|
public void testKt3118() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/properties/kt3118.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt3551.kt")
|
||||||
|
public void testKt3551() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/properties/kt3551.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt3556.kt")
|
||||||
|
public void testKt3556() throws Exception {
|
||||||
|
doTest("compiler/testData/codegen/box/properties/kt3556.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt613.kt")
|
@TestMetadata("kt613.kt")
|
||||||
public void testKt613() throws Exception {
|
public void testKt613() throws Exception {
|
||||||
doTest("compiler/testData/codegen/box/properties/kt613.kt");
|
doTest("compiler/testData/codegen/box/properties/kt613.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user