From e616c38a9fd61b6e06770e64785485a1778f026c Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 30 May 2011 19:55:44 +0400 Subject: [PATCH] pass outer instance when calling base inner class constructor in inner class --- .../jet/codegen/ExpressionCodegen.java | 18 +++++++++++------- .../jet/codegen/ImplementationBodyCodegen.java | 9 +++++++-- .../codegen/classes/inheritedInnerClass.jet | 14 ++++++++++++++ .../jetbrains/jet/codegen/ClassGenTest.java | 4 ++++ 4 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 idea/testData/codegen/classes/inheritedInnerClass.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 7f8234c22e1..c63bb4288d4 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -767,13 +767,17 @@ public class ExpressionCodegen extends JetVisitor { } } else if (!(expression.getParent() instanceof JetSafeQualifiedExpression)) { - v.load(0, JetTypeMapper.TYPE_OBJECT); // TODO hope it works; really need more checks here :) - if (calleeContainingClass != null && contextType instanceof ClassDescriptor && - calleeContainingClass == contextType.getContainingDeclaration()) { - v.getfield(typeMapper.jvmName((ClassDescriptor) contextType, OwnerKind.IMPLEMENTATION), - "this$0", typeMapper.jvmType(calleeContainingClass, OwnerKind.INTERFACE).getDescriptor()); - // TODO handle more levels of class nestng - } + generateThisOrOuter(calleeContainingClass); + } + } + + public void generateThisOrOuter(ClassDescriptor calleeContainingClass) { + v.load(0, JetTypeMapper.TYPE_OBJECT); // TODO hope it works; really need more checks here :) + if (calleeContainingClass != null && contextType instanceof ClassDescriptor && + calleeContainingClass == contextType.getContainingDeclaration()) { + v.getfield(typeMapper.jvmName((ClassDescriptor) contextType, OwnerKind.IMPLEMENTATION), + "this$0", typeMapper.jvmType(calleeContainingClass, OwnerKind.IMPLEMENTATION).getDescriptor()); + // TODO handle more levels of class nestng } } diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 8304d18d9e2..8e3216b8ea5 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -112,7 +112,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { final DeclarationDescriptor outerDescriptor = descriptor.getContainingDeclaration(); if (outerDescriptor instanceof ClassDescriptor) { final ClassDescriptor outerClassDescriptor = (ClassDescriptor) outerDescriptor; - final Type type = JetTypeMapper.jetInterfaceType(outerClassDescriptor); + final Type type = JetTypeMapper.jetImplementationType(outerClassDescriptor); String interfaceDesc = type.getDescriptor(); final String fieldName = "this$0"; v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null); @@ -187,6 +187,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.dup(); } + if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) { + iv.load(1, typeMapper.jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION)); + // TODO handle classes further out + } + Method method1 = typeMapper.mapConstructorSignature(constructorDescriptor1, kind); final Type[] argTypes1 = method1.getArgumentTypes(); List args = superCall.getValueArguments(); @@ -195,7 +200,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { codegen.gen(arg.getArgumentExpression(), argTypes1[i]); } - iv.invokespecial(type.getClassName(), "", method1.getDescriptor()); + iv.invokespecial(type.getInternalName(), "", method1.getDescriptor()); } else if (specifier instanceof JetDelegatorByExpressionSpecifier) { codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression()); diff --git a/idea/testData/codegen/classes/inheritedInnerClass.jet b/idea/testData/codegen/classes/inheritedInnerClass.jet new file mode 100644 index 00000000000..1243ec57d47 --- /dev/null +++ b/idea/testData/codegen/classes/inheritedInnerClass.jet @@ -0,0 +1,14 @@ +class Outer() { + class InnerBase() { + } + + class InnerDerived(): InnerBase() { + } + + public val foo: InnerBase? = new InnerDerived() +} + +fun box() { + val o = new Outer() + return if (o.foo === null) "fail" else "OK" +} diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 7d35d331ea3..5e9815416c3 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -61,6 +61,10 @@ public class ClassGenTest extends CodegenTestCase { blackBoxFile("classes/innerClass.jet"); } + public void testInheritedInnerClass() throws Exception { + blackBoxFile("classes/inheritedInnerClass.jet"); + } + public void testInitializerBlock() throws Exception { blackBoxFile("classes/initializerBlock.jet"); }