From 9ba167ee8dda8b52af699eab7194616b0c8124ea Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sat, 3 Sep 2011 22:52:12 +0200 Subject: [PATCH] fix KT-249/KT-255 --- .../jet/codegen/ExpressionCodegen.java | 29 +++++++++------ .../codegen/ImplementationBodyCodegen.java | 17 +++++---- .../jet/lang/psi/JetObjectDeclaration.java | 2 +- idea/testData/codegen/regressions/kt249.jet | 35 +++++++++++++++++++ .../jetbrains/jet/codegen/ClassGenTest.java | 4 +++ 5 files changed, 67 insertions(+), 20 deletions(-) create mode 100644 idea/testData/codegen/regressions/kt249.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index c75ea5a5549..8ac31b4188a 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -851,7 +851,7 @@ public class ExpressionCodegen extends JetVisitor { DeclarationDescriptor funDescriptor = resolveCalleeDescriptor(expression); if (funDescriptor instanceof ConstructorDescriptor) { - return generateConstructorCall(expression, (JetSimpleNameExpression) callee); + return generateConstructorCall(expression, (JetSimpleNameExpression) callee, receiver); } else if (funDescriptor instanceof FunctionDescriptor) { final FunctionDescriptor fd = (FunctionDescriptor) funDescriptor; @@ -1471,7 +1471,7 @@ public class ExpressionCodegen extends JetVisitor { return StackValue.none(); } - private StackValue generateConstructorCall(JetCallExpression expression, JetSimpleNameExpression constructorReference) { + private StackValue generateConstructorCall(JetCallExpression expression, JetSimpleNameExpression constructorReference, StackValue receiver) { DeclarationDescriptor constructorDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, constructorReference); final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, constructorDescriptor); Type type; @@ -1486,11 +1486,26 @@ public class ExpressionCodegen extends JetVisitor { else { ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration(); + receiver.put(receiver.type, v); v.anew(type); - v.dup(); // TODO typechecker must verify that we're the outer class of the instance being created - pushOuterClassArguments(classDecl); + if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) { + if(!receiver.type.equals(Type.VOID_TYPE)) { + // class object is in receiver + v.dupX1(); + v.swap(); + } + else { + // this$0 need to be put on stack + v.dup(); + v.load(0, JetTypeMapper.jetImplementationType(classDecl)); + } + } + else { + // regular case + v.dup(); + } CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION); invokeMethodWithArguments(method, expression); @@ -1513,12 +1528,6 @@ public class ExpressionCodegen extends JetVisitor { generateTypeInfo(typeArgument); } - private void pushOuterClassArguments(ClassDescriptor classDecl) { - if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) { - v.load(0, JetTypeMapper.jetImplementationType(classDecl)); - } - } - private Type generateJavaConstructorCall(JetCallExpression expression, PsiMethod constructor) { PsiClass javaClass = constructor.getContainingClass(); Type type = JetTypeMapper.psiClassType(javaClass); diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index e97de80ecdc..03e309abad5 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -147,7 +147,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } protected void generatePrimaryConstructor() { - ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, (JetElement) myClass); + ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, myClass); if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration) && !isEnum(myClass)) return; Method method; @@ -193,10 +193,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.invokespecial(superClass, "", /* TODO super constructor descriptor */"()V"); } - final DeclarationDescriptor outerDescriptor = getOuterClassDescriptor(); - if (outerDescriptor instanceof ClassDescriptor) { - final ClassDescriptor outerClassDescriptor = (ClassDescriptor) outerDescriptor; - final Type type = JetTypeMapper.jetImplementationType(outerClassDescriptor); + final ClassDescriptor outerDescriptor = getOuterClassDescriptor(); + if (outerDescriptor != null && !outerDescriptor.isObject()) { + final Type type = JetTypeMapper.jetImplementationType(outerDescriptor); String interfaceDesc = type.getDescriptor(); final String fieldName = "this$0"; v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null); @@ -216,7 +215,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { HashSet overridden = new HashSet(); for (JetDeclaration declaration : myClass.getDeclarations()) { if (declaration instanceof JetFunction) { - overridden.addAll(state.getBindingContext().get(BindingContext.FUNCTION, (JetNamedFunction) declaration).getOverriddenFunctions()); + overridden.addAll(state.getBindingContext().get(BindingContext.FUNCTION, declaration).getOverriddenFunctions()); } } @@ -410,8 +409,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) { for (JetDeclaration declaration : myClass.getDeclarations()) { if (declaration instanceof JetProperty) { - final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, (JetProperty) declaration); - if ((boolean) state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { + final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration); + if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { final JetExpression initializer = ((JetProperty) declaration).getInitializer(); if (initializer != null) { iv.load(0, JetTypeMapper.TYPE_OBJECT); @@ -436,7 +435,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { propertyCodegen.gen((JetProperty) declaration); } else if (declaration instanceof JetFunction) { - if (!overriden.contains(state.getBindingContext().get(BindingContext.FUNCTION, (JetNamedFunction) declaration))) { + if (!overriden.contains(state.getBindingContext().get(BindingContext.FUNCTION, declaration))) { functionCodegen.gen((JetNamedFunction) declaration); } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java b/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java index dc3c76bc5f9..fae5958f7d2 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java @@ -22,7 +22,7 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas @Override public String getName() { JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration(); - return nameAsDeclaration == null ? "" : nameAsDeclaration.getName(); + return nameAsDeclaration == null ? "ClassObj" : nameAsDeclaration.getName(); } @Override diff --git a/idea/testData/codegen/regressions/kt249.jet b/idea/testData/codegen/regressions/kt249.jet new file mode 100644 index 00000000000..d4f61650fd6 --- /dev/null +++ b/idea/testData/codegen/regressions/kt249.jet @@ -0,0 +1,35 @@ +namespace x + +class Outer(val name: String) { + class Inner() { + val me = name + + class object { + fun bar() = "bar" + } + } + + class object { + class StaticInner() { + class object { + fun f() = "oo" + } + } + } +} + +fun box (): String { + val inner = Outer("mama").Inner() //verify error + if(inner.me != "mama") + return "fail" + + val outer = Outer ("papa") + val inner2 = outer.Inner () + if(inner2.me != "papa") + return "fail" + + if(Outer.StaticInner.f() != "oo" ) + return "fail" + + return "OK" +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 2a9fd6c98e7..8a17b3d4887 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -168,4 +168,8 @@ public class ClassGenTest extends CodegenTestCase { final Method rgbMethod = colorClass.getMethod("getRgb"); assertEquals(0xFF0000, rgbMethod.invoke(redValue)); } + + public void testKt249() throws Exception { + blackBoxFile("regressions/kt249.jet"); + } }