From 0bc65321c278d51f4cbd0f055123aeaa9c038ca3 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 28 Mar 2013 15:54:11 +0400 Subject: [PATCH] KT-1547 Wrong layout of closure classes #KT-1547 fixed --- .../binding/CodegenAnnotatingVisitor.java | 55 +++++++++++++------ .../box/closures/closureOnTopLevel1.kt | 21 +++++++ .../box/closures/closureOnTopLevel2.kt | 19 +++++++ .../jet/codegen/OuterClassGenTest.java | 2 +- .../BlackBoxCodegenTestGenerated.java | 10 ++++ 5 files changed, 88 insertions(+), 19 deletions(-) create mode 100644 compiler/testData/codegen/box/closures/closureOnTopLevel1.kt create mode 100644 compiler/testData/codegen/box/closures/closureOnTopLevel2.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java index 92138c85e42..138cda0bb36 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java @@ -17,6 +17,8 @@ package org.jetbrains.jet.codegen.binding; import com.intellij.util.containers.Stack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl; @@ -243,7 +245,17 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { @Override public void visitProperty(JetProperty property) { - nameStack.push(peekFromStack(nameStack) + '$' + property.getName()); + DeclarationDescriptor propertyDescriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property); + // working around a problem with shallow analysis + if (propertyDescriptor == null) return; + + String nameForClassOrNamespaceMember = getNameForClassOrNamespaceMember(propertyDescriptor); + if (nameForClassOrNamespaceMember != null) { + nameStack.push(nameForClassOrNamespaceMember); + } + else { + nameStack.push(peekFromStack(nameStack) + '$' + property.getName()); + } super.visitProperty(property); nameStack.pop(); } @@ -254,23 +266,10 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, function); // working around a problem with shallow analysis if (functionDescriptor == null) return; - DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); - if (containingDeclaration instanceof ClassDescriptor) { - nameStack.push(peekFromStack(nameStack) + '$' + function.getName()); - super.visitNamedFunction(function); - nameStack.pop(); - } - else if (containingDeclaration instanceof NamespaceDescriptor) { - String peek = peekFromStack(nameStack); - FqName qualifiedName = ((NamespaceDescriptor) containingDeclaration).getFqName(); - String packageClassName = PackageClassUtils.getPackageClassName(qualifiedName); - if (peek.isEmpty()) { - peek = packageClassName; - } - else { - peek += "/" + packageClassName; - } - nameStack.push(peek + '$' + function.getName()); + + String nameForClassOrNamespaceMember = getNameForClassOrNamespaceMember(functionDescriptor); + if (nameForClassOrNamespaceMember != null) { + nameStack.push(nameForClassOrNamespaceMember); super.visitNamedFunction(function); nameStack.pop(); } @@ -286,4 +285,24 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { classStack.pop(); } } + + @Nullable + private String getNameForClassOrNamespaceMember(@NotNull DeclarationDescriptor descriptor) { + DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); + + String peek = peekFromStack(nameStack); + String name = descriptor.getName().getName(); + if (containingDeclaration instanceof ClassDescriptor) { + return peek + '$' + name; + } + else if (containingDeclaration instanceof NamespaceDescriptor) { + FqName qualifiedName = ((NamespaceDescriptor) containingDeclaration).getFqName(); + String packageClassShortName = PackageClassUtils.getPackageClassName(qualifiedName); + String packageClassName = peek.isEmpty() ? packageClassShortName : peek + "/" + packageClassShortName; + return packageClassName + '$' + name; + } + else { + return null; + } + } } diff --git a/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt b/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt new file mode 100644 index 00000000000..bc0a5f61a4b --- /dev/null +++ b/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt @@ -0,0 +1,21 @@ +package test + +val p = { "OK" }() + +val getter: String + get() = { "OK" }() + +fun f() = { "OK" }() + +val obj = object : Function0() { + override fun invoke() = "OK" +} + +fun box(): String { + if (p != "OK") return "FAIL" + if (getter != "OK") return "FAIL" + if (f() != "OK") return "FAIL" + if (obj() != "OK") return "FAIL" + + return "OK" +} diff --git a/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt b/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt new file mode 100644 index 00000000000..e86ec48df07 --- /dev/null +++ b/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt @@ -0,0 +1,19 @@ +val p = { "OK" }() + +val getter: String + get() = { "OK" }() + +fun f() = { "OK" }() + +val obj = object : Function0() { + override fun invoke() = "OK" +} + +fun box(): String { + if (p != "OK") return "FAIL" + if (getter != "OK") return "FAIL" + if (f() != "OK") return "FAIL" + if (obj() != "OK") return "FAIL" + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/OuterClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/OuterClassGenTest.java index e461c6087b9..be89f5953f2 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/OuterClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/OuterClassGenTest.java @@ -65,7 +65,7 @@ public class OuterClassGenTest extends CodegenTestCase { public void testObjectLiteralInPackageClass() throws Exception { OuterClassInfo expectedInfo = new OuterClassInfo("foo/FooPackage$src$outerClassInfo$", null, null); - doCustomTest("foo$packageObjectLiteral$1", expectedInfo); + doCustomTest("foo.FooPackage$packageObjectLiteral$1", expectedInfo); } public void testLocalClassInTopLevelFunction() throws Exception { diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 3def89030d7..7cb8b8b6854 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -921,6 +921,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/closures/closureInsideConstrucor.kt"); } + @TestMetadata("closureOnTopLevel1.kt") + public void testClosureOnTopLevel1() throws Exception { + doTest("compiler/testData/codegen/box/closures/closureOnTopLevel1.kt"); + } + + @TestMetadata("closureOnTopLevel2.kt") + public void testClosureOnTopLevel2() throws Exception { + doTest("compiler/testData/codegen/box/closures/closureOnTopLevel2.kt"); + } + @TestMetadata("closureWithParameter.kt") public void testClosureWithParameter() throws Exception { doTest("compiler/testData/codegen/box/closures/closureWithParameter.kt");