From 0a1161f5c185143e99f3ebe364b32d7747cdd676 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 30 May 2011 21:41:15 +0400 Subject: [PATCH] support qualified this --- .../jet/codegen/ExpressionCodegen.java | 29 ++++++++++++++----- idea/testData/codegen/classes/outerThis.jet | 12 ++++++++ .../jetbrains/jet/codegen/ClassGenTest.java | 4 +++ 3 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 idea/testData/codegen/classes/outerThis.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index dc827077875..5344035d15a 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -770,23 +770,30 @@ public class ExpressionCodegen extends JetVisitor { } } else if (!(expression.getParent() instanceof JetSafeQualifiedExpression)) { - generateThisOrOuter(calleeContainingClass); + final StackValue value = generateThisOrOuter(calleeContainingClass); + value.put(value.type, v); } } - public void generateThisOrOuter(ClassDescriptor calleeContainingClass) { + public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) { final StackValue value = outerThisExpressions.get(calleeContainingClass); if (value != null) { - value.put(value.type, v); + return value; } else { - v.load(0, JetTypeMapper.TYPE_OBJECT); // TODO hope it works; really need more checks here :) + // 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()); + v.load(0, JetTypeMapper.TYPE_OBJECT); + return StackValue.field(typeMapper.jvmType(calleeContainingClass, OwnerKind.IMPLEMENTATION), + typeMapper.jvmName((ClassDescriptor) contextType, OwnerKind.IMPLEMENTATION), + "this$0", + false); // TODO handle more levels of class nestng } + else { + return StackValue.local(0, JetTypeMapper.TYPE_OBJECT); + } } } @@ -1418,7 +1425,13 @@ public class ExpressionCodegen extends JetVisitor { @Override public void visitThisExpression(JetThisExpression expression) { - generateThis(); + final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression.getThisReference()); + if (descriptor instanceof ClassDescriptor) { + myStack.push(generateThisOrOuter((ClassDescriptor) descriptor)); + } + else { + generateThis(); + } } public void thisToStack() { @@ -1431,7 +1444,7 @@ public class ExpressionCodegen extends JetVisitor { myStack.push(thisExpression); return; } - if (contextKind == OwnerKind.NAMESPACE) { + if (contextKind != OwnerKind.NAMESPACE) { ClassDescriptor contextClass = (ClassDescriptor) contextType; final Type thisType = typeMapper.jvmType(contextClass, contextKind); if (contextKind == OwnerKind.IMPLEMENTATION) { diff --git a/idea/testData/codegen/classes/outerThis.jet b/idea/testData/codegen/classes/outerThis.jet new file mode 100644 index 00000000000..f907a112775 --- /dev/null +++ b/idea/testData/codegen/classes/outerThis.jet @@ -0,0 +1,12 @@ +class Outer() { + class Inner() { + val outer: Outer get() = this@Outer + } + + public val x = new Inner() +} + +fun box() { + val o = new Outer() + return if (o === o.x.outer) "OK" else "fail" +} diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 281ab85eec5..8022383c3c9 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -91,4 +91,8 @@ public class ClassGenTest extends CodegenTestCase { public void testPropertyInInitializer() throws Exception { blackBoxFile("classes/propertyInInitializer.jet"); } + + public void testOuterThis() throws Exception { + blackBoxFile("classes/outerThis.jet"); + } }