diff --git a/compiler/testData/codegen/innerClassInfo/anonymousObjectInline.kt b/compiler/testData/codegen/innerClassInfo/anonymousObjectInline.kt new file mode 100644 index 00000000000..dd370f45ade --- /dev/null +++ b/compiler/testData/codegen/innerClassInfo/anonymousObjectInline.kt @@ -0,0 +1,14 @@ +class A { + fun foo() { + inlineFun { "test" } + } + + inline fun inlineFun(lambda: () -> Unit) { + val s = object { + fun run() { + lambda() + } + } + s.run() + } +} diff --git a/compiler/testData/codegen/outerClassInfo/inlineLambda.kt b/compiler/testData/codegen/outerClassInfo/inlineLambda.kt new file mode 100644 index 00000000000..9b62696451a --- /dev/null +++ b/compiler/testData/codegen/outerClassInfo/inlineLambda.kt @@ -0,0 +1,40 @@ +package foo; + +class Foo { + + inline fun inlineFoo(s: () -> Unit) { + { + s() + }() + } + + inline fun simpleFoo(s: () -> Unit) { + s() + } +} + + +class Bar { + fun callToInline() { + Foo().inlineFoo { 1 } + } + + fun objectInInlineLambda() { + val s = 1; + Foo().simpleFoo { + { + s + }() + } + } + + fun objectInLambdaInlinedIntoObject() { + val s = 1; + Foo().inlineFoo { + { + s + }() + } + } + +} \ No newline at end of file diff --git a/compiler/testData/codegen/outerClassInfo/inlineObject.kt b/compiler/testData/codegen/outerClassInfo/inlineObject.kt new file mode 100644 index 00000000000..59f7260e5af --- /dev/null +++ b/compiler/testData/codegen/outerClassInfo/inlineObject.kt @@ -0,0 +1,48 @@ +package foo; + +class Foo { + + inline fun inlineFoo(s: () -> Unit) { + val localObject = object { + fun run() { + s() + } + } + + localObject.run() + } + + inline fun simpleFoo(s: () -> Unit) { + s() + } +} + + +class Bar { + fun callToInline() { + Foo().inlineFoo { 1 } + } + + fun objectInInlineLambda() { + val s = 1; + Foo().simpleFoo { + val localObject = object { + fun run() { s } + } + + localObject.run() + } + } + + fun objectInLambdaInlinedIntoObject() { + val s = 1; + Foo().inlineFoo { + val localObject = object { + fun run() { s } + } + + localObject.run() + } + } + +} \ No newline at end of file diff --git a/compiler/testData/codegen/outerClassInfo/outerClassInfo.java b/compiler/testData/codegen/outerClassInfo/outerClassInfo.java index 70192613b5e..f60a3716288 100644 --- a/compiler/testData/codegen/outerClassInfo/outerClassInfo.java +++ b/compiler/testData/codegen/outerClassInfo/outerClassInfo.java @@ -20,6 +20,16 @@ class Foo { void objectLiteralFoo() { } }; + //anonymous lambda + Foo() { + class LambdaInConstructor{} + } + + + void foo() { + //lambda + class Lambda {} + } } class PackageInnerObject { } diff --git a/compiler/testData/codegen/outerClassInfo/outerClassInfo.kt b/compiler/testData/codegen/outerClassInfo/outerClassInfo.kt index ffdd71855ec..be9cc696b74 100644 --- a/compiler/testData/codegen/outerClassInfo/outerClassInfo.kt +++ b/compiler/testData/codegen/outerClassInfo/outerClassInfo.kt @@ -18,6 +18,14 @@ class Foo { val objectLiteral = object { fun objectLiteralFoo() { } } + + //anonymous lambda in constructor + val s = { 11 }() + + fun foo() { + //anonymous lambda + { }() + } } object PackageInnerObject { diff --git a/compiler/tests/org/jetbrains/jet/codegen/InnerClassInfoGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/InnerClassInfoGenTest.java index 0385acbd737..860935b92a3 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/InnerClassInfoGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/InnerClassInfoGenTest.java @@ -76,6 +76,11 @@ public class InnerClassInfoGenTest extends CodegenTestCase { extractAndCompareInnerClasses("A$foo$C$1", innerC); } + public void testAnonymousObjectInline() { + InnerClassAttribute objectInInlineFun = new InnerClassAttribute("A$inlineFun$s$1", null, null, ACC_PUBLIC | ACC_STATIC | ACC_FINAL); + extractAndCompareInnerClasses("A", objectInInlineFun); + } + public void testEnumEntry() { InnerClassAttribute innerE2 = new InnerClassAttribute("E$E2", "E", "E2", ACC_STATIC | ACC_FINAL); diff --git a/compiler/tests/org/jetbrains/jet/codegen/OuterClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/OuterClassGenTest.java index 25dd2de0282..25294d6f05a 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/OuterClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/OuterClassGenTest.java @@ -62,6 +62,14 @@ public class OuterClassGenTest extends CodegenTestCase { doTest("foo.PackageInnerObject", "outerClassInfo"); } + public void testLambdaInNoInlineFun() throws Exception { + doTest("foo.Foo$foo$1", "foo.Foo$1Lambda", "outerClassInfo"); + } + + public void testLambdaInConstructor() throws Exception { + doTest("foo.Foo$s$1", "foo.Foo$1LambdaInConstructor", "outerClassInfo"); + } + public void testObjectLiteralInPackageClass() throws Exception { OuterClassInfo expectedInfo = new OuterClassInfo("foo/FooPackage-outerClassInfo-", null, null); doCustomTest("foo.FooPackage$packageObjectLiteral$1", expectedInfo, "outerClassInfo"); @@ -77,6 +85,56 @@ public class OuterClassGenTest extends CodegenTestCase { doCustomTest("foo.FooPackage$packageMethod$PackageLocalObject", expectedInfo, "outerClassInfo"); } + public void testLocalObjectInInlineFunction() throws Exception { + OuterClassInfo expectedInfo = new OuterClassInfo("foo/Foo", "inlineFoo", "(Lkotlin/Function0;)V"); + doCustomTest("foo.Foo$inlineFoo$localObject$1", expectedInfo, "inlineObject"); + } + + public void testLocalObjectInlined() throws Exception { + OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", null, null); + doCustomTest("foo.Bar$callToInline$$inlined$inlineFoo$1", expectedInfo, "inlineObject"); + } + + public void testLocalObjectInInlineLambda() throws Exception { + OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", null, null); + doCustomTest("foo.Bar$objectInInlineLambda$$inlined$simpleFoo$lambda$1", expectedInfo, "inlineObject"); + } + + public void testLocalObjectInLambdaInlinedIntoObject() throws Exception { + OuterClassInfo intoObjectInfo = new OuterClassInfo("foo/Bar", null, null); + + String intoObjectName = "foo.Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1"; + doCustomTest(intoObjectName, intoObjectInfo, "inlineObject"); + + OuterClassInfo objectInLambda = new OuterClassInfo(intoObjectName.replace('.', '/'), null, null); + doCustomTest("foo.Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$lambda$lambda$1", objectInLambda, "inlineObject"); + } + + public void testLambdaInInlineFunction() throws Exception { + OuterClassInfo expectedInfo = new OuterClassInfo("foo/Foo", "inlineFoo", "(Lkotlin/Function0;)V"); + doCustomTest("foo.Foo$inlineFoo$1", expectedInfo, "inlineLambda"); + } + + public void testLambdaInlined() throws Exception { + OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", null, null); + doCustomTest("foo.Bar$callToInline$$inlined$inlineFoo$1", expectedInfo, "inlineLambda"); + } + + public void testLambdaInInlineLambda() throws Exception { + OuterClassInfo expectedInfo = new OuterClassInfo("foo/Bar", null, null); + doCustomTest("foo.Bar$objectInInlineLambda$$inlined$simpleFoo$lambda$1", expectedInfo, "inlineLambda"); + } + + public void testLambdaInLambdaInlinedIntoObject() throws Exception { + OuterClassInfo intoObjectInfo = new OuterClassInfo("foo/Bar", null, null); + + String intoObjectName = "foo.Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$1"; + doCustomTest(intoObjectName, intoObjectInfo, "inlineLambda"); + + OuterClassInfo objectInLambda = new OuterClassInfo(intoObjectName.replace('.', '/'), null, null); + doCustomTest("foo.Bar$objectInLambdaInlinedIntoObject$$inlined$inlineFoo$lambda$lambda$1", objectInLambda, "inlineLambda"); + } + private void doTest(@NotNull String className, String testDataFile) throws Exception { doTest(className, className, testDataFile); } @@ -90,12 +148,13 @@ public class OuterClassGenTest extends CodegenTestCase { private void doTest(@NotNull String kotlinClassName, @NotNull String javaClassName, String testDataFile) throws Exception { File javaClassesTempDirectory = compileJava(TEST_FOLDER + "/" + testDataFile + ".java"); - UrlClassLoader javaClassLoader = new UrlClassLoader(new URL[] {javaClassesTempDirectory.toURI().toURL()}, getClass().getClassLoader()); + UrlClassLoader javaClassLoader = UrlClassLoader.build().urls(javaClassesTempDirectory.toURI().toURL()).get(); String javaClassPath = javaClassName.replace('.', File.separatorChar) + ".class"; InputStream javaClassStream = javaClassLoader.getResourceAsStream(javaClassPath); - ClassReader javaReader = new ClassReader(javaClassStream); + assert javaClassStream != null : "Couldn't find class bytecode " + javaClassPath; + ClassReader javaReader = new ClassReader(javaClassStream); ClassReader kotlinReader = getKotlinClassReader(kotlinClassName, testDataFile); checkInfo(kotlinReader, javaReader); @@ -106,27 +165,35 @@ public class OuterClassGenTest extends CodegenTestCase { OuterClassInfo kotlinInfo = getOuterClassInfo(kotlinReader); String message = "Error in enclosingMethodInfo info for: " + kotlinReader.getClassName() + " class"; if ((kotlinInfo.owner == null) || !kotlinInfo.owner.startsWith(expectedInfo.owner)) { - fail(message + " expectedOwner=" + expectedInfo.owner + ", actualOwner=" + kotlinInfo.owner); + assertEquals(message, expectedInfo.owner, kotlinInfo.owner); } assertEquals(message, expectedInfo.method, kotlinInfo.method); assertEquals(message, expectedInfo.descriptor, kotlinInfo.descriptor); } - private ClassReader getKotlinClassReader(@NotNull String kotlinClassName, String testDataFile) { - loadFile(TEST_FOLDER + "/ " + testDataFile + ".kt"); + private ClassReader getKotlinClassReader(@NotNull String kotlinClassName, @NotNull String testDataFile) { + loadFile(TEST_FOLDER + "/" + testDataFile + ".kt"); OutputFileCollection outputFiles = generateClassesInFile(); OutputFile outputFile = outputFiles.get(kotlinClassName.replace('.', '/') + ".class"); - assertNotNull(outputFile); + assertNotNull("Couldn't find kotlin class: " + kotlinClassName ,outputFile); return new ClassReader(outputFile.asByteArray()); } - private void checkInfo(ClassReader kotlinReader, ClassReader javaReader) { + private static void checkInfo(@NotNull ClassReader kotlinReader, @NotNull ClassReader javaReader) { OuterClassInfo kotlinInfo = getOuterClassInfo(kotlinReader); OuterClassInfo javaInfo = getOuterClassInfo(javaReader); - assertEquals("Error in enclosingMethodInfo info for: " + kotlinReader.getClassName() + " class", javaInfo, kotlinInfo); + compareInfo(kotlinReader.getClassName(), kotlinInfo, javaInfo); } - public OuterClassInfo getOuterClassInfo(ClassReader reader) { + private static void compareInfo( + @NotNull String kotlinClassName, + @NotNull OuterClassInfo kotlinInfo, + @NotNull OuterClassInfo expectedJavaInfo + ) { + assertEquals("Error in enclosingMethodInfo info for: " + kotlinClassName + " class", expectedJavaInfo, kotlinInfo); + } + + public static OuterClassInfo getOuterClassInfo(ClassReader reader) { final OuterClassInfo info = new OuterClassInfo(); reader.accept(new ClassVisitor(Opcodes.ASM5) { @Override