KT-3118 NoSuchFieldError on private property without backing field &&

KT-3551 Wrong synthetic accessor implementation
This commit is contained in:
Mikhael Bogdanov
2013-04-30 11:40:27 +04:00
parent b1c2d9035a
commit b0b6728c7e
13 changed files with 180 additions and 142 deletions
@@ -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");