From 3b2fb0da8f4fe3e3af439e47d3a6e4e38d488bba Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 14 Nov 2011 19:34:00 +0200 Subject: [PATCH] KT-508 accessors for enclosed private fields --- .../org/jetbrains/jet/codegen/ClassCodegen.java | 3 +++ .../jetbrains/jet/codegen/CodegenContext.java | 13 +++++++++++++ .../jet/codegen/ExpressionCodegen.java | 12 +++++++++++- .../jet/codegen/ImplementationBodyCodegen.java | 16 +++++++++------- compiler/testData/codegen/regressions/kt508.jet | 17 +++++++++++++++++ .../org/jetbrains/jet/codegen/ClassGenTest.java | 6 ++++++ 6 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt508.jet diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index 8d4602e83c7..148b3f825f7 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -28,6 +28,9 @@ public class ClassCodegen { if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) { generate(contextForInners, (JetClass) declaration); } + if(declaration instanceof JetClassObject) { + state.forClass().generate(contextForInners, ((JetClassObject)declaration).getObjectDeclaration()); + } } generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index 06b16f8b80f..0b39bc09343 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -47,6 +47,19 @@ public abstract class CodegenContext { } protected abstract ClassDescriptor getThisDescriptor (); + + public DeclarationDescriptor getClassOrNamespaceDescriptor() { + CodegenContext c = this; + while(true) { + DeclarationDescriptor contextDescriptor = c.getContextDescriptor(); + if(!(contextDescriptor instanceof ClassDescriptor) && !(contextDescriptor instanceof NamespaceDescriptor)) { + c = c.getParentContext(); + } + else { + return contextDescriptor; + } + } + } protected CallableDescriptor getReceiverDescriptor() { return null; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 6e1f3011986..1af84253265 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -797,7 +797,7 @@ public class ExpressionCodegen extends JetVisitor { } } else if (descriptor instanceof PropertyDescriptor) { - final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; //TODO: hack, will not need if resolve goes to right descriptor itself if (declaration instanceof JetParameter) { @@ -828,6 +828,16 @@ public class ExpressionCodegen extends JetVisitor { final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ; JetExpression r = getReceiverForSelector(expression); final boolean isSuper = r instanceof JetSuperExpression; + if(propertyDescriptor.getVisibility() == Visibility.PRIVATE && context.getClassOrNamespaceDescriptor() != propertyDescriptor.getContainingDeclaration()) { + DeclarationDescriptor enclosed = propertyDescriptor.getContainingDeclaration(); + if(enclosed != null && enclosed != context.getThisDescriptor()) { + CodegenContext c = context; + while(c.getContextDescriptor() != enclosed) { + c = c.getParentContext(); + } + propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); + } + } final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression)r : null); if(!directToField && resolvedCall != null && !isSuper) { if (resolvedCall.getThisObject().exists()) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 49bae261d18..22567a68d40 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -218,7 +218,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv = new InstructionAdapter(mv); iv.load(0, JetTypeMapper.TYPE_OBJECT); - iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); + if(original.getVisibility() == Visibility.PRIVATE) + iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getReturnType().getDescriptor()); + else + iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); iv.areturn(method.getReturnType()); mv.visitMaxs(0,0); @@ -241,7 +244,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { //noinspection AssignmentToForLoopParameter reg += argType.getSize(); } - iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); + if(original.getVisibility() == Visibility.PRIVATE) + iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getArgumentTypes()[0].getDescriptor()); + else + iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); iv.areturn(method.getReturnType()); mv.visitMaxs(0,0); @@ -572,7 +578,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateSecondaryConstructor((JetSecondaryConstructor) declaration); } else if (declaration instanceof JetClassObject) { - generateClassObject((JetClassObject) declaration); + // done earlier in order to have accessors } else if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) { String name = declaration.getName(); @@ -874,8 +880,4 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } }); } - - private void generateClassObject(JetClassObject declaration) { - state.forClass().generate(context, declaration.getObjectDeclaration()); - } } diff --git a/compiler/testData/codegen/regressions/kt508.jet b/compiler/testData/codegen/regressions/kt508.jet new file mode 100644 index 00000000000..088bd1fd6bd --- /dev/null +++ b/compiler/testData/codegen/regressions/kt508.jet @@ -0,0 +1,17 @@ +namespace mult_constructors_3_bug + +public open class Identifier() { + private var myNullable : Boolean = true + class object { + open public fun init(isNullable : Boolean) : Identifier { + val __ = Identifier() + __.myNullable = isNullable + return __ + } + } +} + +fun box() : String { + Identifier.init(true) + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 97e4098243d..e9f04db1845 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -196,4 +196,10 @@ public class ClassGenTest extends CodegenTestCase { System.out.println(generateToText()); blackBox(); } + + public void testKt508 () throws Exception { + loadFile("regressions/kt508.jet"); + System.out.println(generateToText()); + blackBox(); + } }