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 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),
|
||||
Kind.DECLARATION);
|
||||
|
||||
@@ -41,7 +41,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
|
||||
|
||||
public static class Getter extends PropertyGetterDescriptorImpl {
|
||||
public Getter(AccessorForPropertyDescriptor property) {
|
||||
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC,
|
||||
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.LOCAL,
|
||||
false,
|
||||
false, Kind.DECLARATION);
|
||||
initialize(property.getType());
|
||||
@@ -50,7 +50,7 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
|
||||
|
||||
public static class Setter extends PropertySetterDescriptorImpl {
|
||||
public Setter(AccessorForPropertyDescriptor property) {
|
||||
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC,
|
||||
super(property, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.LOCAL,
|
||||
false,
|
||||
false, Kind.DECLARATION);
|
||||
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
|
||||
|| isInterface(functionDescriptor.getContainingDeclaration()))
|
||||
&& !isStatic(kind)
|
||||
&& kind != OwnerKind.TRAIT_IMPL;
|
||||
&& !isStaticMethod(kind, functionDescriptor);
|
||||
}
|
||||
|
||||
public static boolean isStaticMethod(OwnerKind kind, FunctionDescriptor functionDescriptor) {
|
||||
return isStatic(kind) || kind == OwnerKind.TRAIT_IMPL || JetTypeMapper.isAccessor(functionDescriptor);
|
||||
}
|
||||
|
||||
public static boolean isStatic(OwnerKind kind) {
|
||||
@@ -142,9 +145,6 @@ public class AsmUtil {
|
||||
}
|
||||
|
||||
public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||
boolean isStatic = isStatic(kind);
|
||||
boolean isAbstract = isAbstract(functionDescriptor, kind);
|
||||
|
||||
int flags = getCommonCallableFlags(functionDescriptor);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (isAbstract) flags |= ACC_ABSTRACT;
|
||||
if (isAbstractMethod(functionDescriptor, kind)) {
|
||||
flags |= ACC_ABSTRACT;
|
||||
}
|
||||
|
||||
if (JetTypeMapper.isAccessor(functionDescriptor)) {
|
||||
flags |= ACC_SYNTHETIC;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public static int getConstructorAsmFlags(FunctionDescriptor functionDescriptor) {
|
||||
return getCommonCallableFlags(functionDescriptor);
|
||||
}
|
||||
|
||||
private static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) {
|
||||
int flags = getVisibilityAccessFlag(functionDescriptor);
|
||||
flags |= getVarargsFlag(functionDescriptor);
|
||||
|
||||
@@ -262,4 +262,14 @@ public class CodegenUtil {
|
||||
}
|
||||
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) {
|
||||
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());
|
||||
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, labelPsi);
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
||||
@@ -305,7 +310,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
return labelTarget;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1552,12 +1557,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
|
||||
boolean isStatic = container instanceof NamespaceDescriptor;
|
||||
boolean directToField =
|
||||
expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL;
|
||||
JetExpression r = getReceiverForSelector(expression);
|
||||
boolean isSuper = r instanceof JetSuperExpression;
|
||||
propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor);
|
||||
propertyDescriptor = accessablePropertyDescriptor(context, propertyDescriptor);
|
||||
StackValue.Property iValue =
|
||||
intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null);
|
||||
if (directToField) {
|
||||
@@ -1662,6 +1666,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
boolean forceField,
|
||||
@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();
|
||||
assert containingDeclaration != null;
|
||||
@@ -1670,23 +1687,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
boolean isSuper = superExpression != null;
|
||||
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
|
||||
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
|
||||
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
||||
|
||||
CallableMethod callableGetter = null;
|
||||
CallableMethod callableSetter = null;
|
||||
|
||||
if (!forceField) {
|
||||
//noinspection ConstantConditions
|
||||
if (isInsideClass &&
|
||||
!isExtensionProperty &&
|
||||
(propertyDescriptor.getGetter() == null ||
|
||||
!DescriptorUtils.isExternallyAccessible(propertyDescriptor) ||
|
||||
propertyDescriptor.getGetter().isDefault() && propertyDescriptor.getGetter().getModality() == Modality.FINAL)) {
|
||||
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass)) {
|
||||
callableGetter = null;
|
||||
}
|
||||
else {
|
||||
if (isSuper && !isInterface(containingDeclaration)) {
|
||||
ClassDescriptor owner = getSuperCallLabelTarget(superExpression);
|
||||
ClassDescriptor owner = getSuperCallLabelTarget(superExpression, state.getBindingContext(), context);
|
||||
CodegenContext c = context.findParentContextWithDescriptor(owner);
|
||||
assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor;
|
||||
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) {
|
||||
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.getSetter() != null) {
|
||||
if (isInsideClass && !isExtensionProperty &&
|
||||
(!DescriptorUtils.isExternallyAccessible(propertyDescriptor) ||
|
||||
propertyDescriptor.getSetter().isDefault() &&
|
||||
propertyDescriptor.getSetter().getModality() == Modality.FINAL)) {
|
||||
if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass)) {
|
||||
callableSetter = null;
|
||||
}
|
||||
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);
|
||||
if (callableMethod == null) {
|
||||
owner = typeMapper.getOwner(propertyDescriptor, contextKind(), isInsideModule);
|
||||
owner = typeMapper.getOwner(propertyDescriptor, context.getContextKind(), isInsideModule);
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
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
|
||||
private CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor) {
|
||||
@NotNull
|
||||
private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) {
|
||||
CodegenContext c = context;
|
||||
while (true) {
|
||||
if ((c instanceof ClassContext || c instanceof AnonymousClassContext) &&
|
||||
|
||||
@@ -127,7 +127,7 @@ public class FunctionCodegen extends GenerationStateAware {
|
||||
genJetAnnotations(mv, functionDescriptor, jvmSignature);
|
||||
}
|
||||
|
||||
if (isAbstract(functionDescriptor, methodContext.getContextKind())) return;
|
||||
if (isAbstractMethod(functionDescriptor, methodContext.getContextKind())) return;
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||
genStubCode(mv);
|
||||
@@ -227,13 +227,13 @@ public class FunctionCodegen extends GenerationStateAware {
|
||||
List<JvmMethodParameterSignature> params = jvmMethodSignature.getKotlinParameterTypes();
|
||||
int shift = 0;
|
||||
|
||||
boolean isStatic = isStatic(ownerKind) || ownerKind == OwnerKind.TRAIT_IMPL;
|
||||
boolean isStatic = AsmUtil.isStaticMethod(ownerKind, functionDescriptor);
|
||||
if (!isStatic) {
|
||||
//add this
|
||||
if (thisType != null) {
|
||||
mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift);
|
||||
} else {
|
||||
//sometimes there is no thisType for callable reference
|
||||
//TODO: provide thisType for callable reference
|
||||
}
|
||||
shift++;
|
||||
}
|
||||
@@ -334,14 +334,13 @@ public class FunctionCodegen extends GenerationStateAware {
|
||||
) {
|
||||
|
||||
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
|
||||
assert jvmSignature instanceof JvmPropertyAccessorSignature;
|
||||
assert jvmSignature instanceof JvmPropertyAccessorSignature : "jvmSignature for property should have JvmPropertyAccessorSignature type";
|
||||
PropertyCodegen.generateJetPropertyAnnotation(mv, (JvmPropertyAccessorSignature) jvmSignature,
|
||||
((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty(), functionDescriptor.getVisibility());
|
||||
}
|
||||
else if (functionDescriptor instanceof SimpleFunctionDescriptor) {
|
||||
if (jvmSignature instanceof JvmPropertyAccessorSignature) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
assert !(jvmSignature instanceof JvmPropertyAccessorSignature) : "jvmSignature for function shouldn't have JvmPropertyAccessorSignature type";
|
||||
|
||||
Modality modality = functionDescriptor.getModality();
|
||||
JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv);
|
||||
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> {
|
||||
|
||||
private final GenerationState state;
|
||||
|
||||
protected final 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.signature.*;
|
||||
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.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
|
||||
@@ -79,9 +78,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private JetType superClassType;
|
||||
private final Type classAsmType;
|
||||
|
||||
private final FunctionCodegen functionCodegen;
|
||||
private final PropertyCodegen propertyCodegen;
|
||||
|
||||
public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState 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
|
||||
@@ -440,7 +444,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateTraitMethods();
|
||||
|
||||
generateAccessors();
|
||||
generateSyntheticAccessors();
|
||||
|
||||
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()) {
|
||||
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) {
|
||||
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
|
||||
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
|
||||
@@ -817,7 +821,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
Type[] argTypes = method.getArgumentTypes();
|
||||
|
||||
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);
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||
genStubCode(mv);
|
||||
@@ -850,86 +854,46 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
else if (entry.getValue() instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
||||
PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
||||
|
||||
{
|
||||
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);
|
||||
final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
||||
final StackValue.Property property = ExpressionCodegen.intermediateValueForProperty(original, false, null, state, context, true);
|
||||
|
||||
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);
|
||||
boolean hasBackingField = Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, original));
|
||||
boolean isInsideModule = isCallInsideSameModuleAsDeclared(original, context);
|
||||
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);
|
||||
property.put(property.type, iv);
|
||||
iv.areturn(signature.getAsmMethod().getReturnType());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
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();
|
||||
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);
|
||||
Type[] argTypes = method.getArgumentTypes();
|
||||
for (int i = 1, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
boolean isInsideModule = isCallInsideSameModuleAsDeclared(original, context);
|
||||
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.load(0, OBJECT_TYPE);
|
||||
Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
|
||||
for (int i = 1, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
property.store(property.type, iv);
|
||||
|
||||
iv.areturn(method.getReturnType());
|
||||
FunctionCodegen.endVisit(iv, "accessor", null);
|
||||
}
|
||||
iv.areturn(signature.getAsmMethod().getReturnType());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -979,26 +943,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
assert constructorDescriptor != null;
|
||||
|
||||
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
||||
|
||||
functionCodegen.generateMethod(null, constructorMethod, true, constructorDescriptor, constructorContext,
|
||||
new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
|
||||
new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected FrameMap createFrameMap(
|
||||
@NotNull JetTypeMapper typeMapper, @NotNull CodegenContext context
|
||||
) {
|
||||
return new ConstructorFrameMap(callableMethod, callableDescriptor);
|
||||
}
|
||||
@NotNull
|
||||
@Override
|
||||
protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull CodegenContext context) {
|
||||
return new ConstructorFrameMap(callableMethod, callableDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGenerateBody(
|
||||
ExpressionCodegen codegen, JvmMethodSignature signature
|
||||
) {
|
||||
generatePrimaryConstructorImpl(callableDescriptor, codegen, closure);
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
||||
generatePrimaryConstructorImpl(callableDescriptor, codegen, closure);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod.getAsmMethod(), constructorDescriptor,
|
||||
OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT);
|
||||
@@ -1642,9 +1601,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
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()) {
|
||||
if (declaration instanceof CallableMemberDescriptor) {
|
||||
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
|
||||
|
||||
@@ -550,7 +550,7 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
thisClass, receiverParameterType, null);
|
||||
}
|
||||
|
||||
private static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
|
||||
public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
|
||||
return descriptor instanceof AccessorForFunctionDescriptor ||
|
||||
descriptor instanceof AccessorForPropertyDescriptor ||
|
||||
descriptor instanceof AccessorForPropertyDescriptor.Getter ||
|
||||
|
||||
@@ -33,7 +33,7 @@ class C {
|
||||
class D {
|
||||
private var foo = 1
|
||||
set(i: Int) {
|
||||
foo = i + 1
|
||||
$foo = i + 1
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@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")
|
||||
public void testKt613() throws Exception {
|
||||
doTest("compiler/testData/codegen/box/properties/kt613.kt");
|
||||
|
||||
Reference in New Issue
Block a user