From b7a7fce34ef59fe73b7228f892ac24071fa4d1e6 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Thu, 18 Aug 2022 12:24:08 +0200 Subject: [PATCH] Add suspend lambda annotations to invokeSuspend. For non-suspend lambdas annotations are carried over to the invoke method so that tooling can find the annotation there. It seems reasonable that annotations are carried over to the invokeSuspend method on suspend lambdas as well so that similar tooling can be built and work for suspend lambdas. --- .../FirBlackBoxCodegenTestGenerated.java | 6 +++ .../jvm/lower/SuspendLambdaLowering.kt | 2 + .../box/annotations/annotatedLambda/lambda.kt | 4 +- .../annotatedLambda/suspendLambda.kt | 45 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ 7 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/box/annotations/annotatedLambda/suspendLambda.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 88096ea0350..58a6067fac0 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -421,6 +421,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT public void testSamLambda() throws Exception { runTest("compiler/testData/codegen/box/annotations/annotatedLambda/samLambda.kt"); } + + @Test + @TestMetadata("suspendLambda.kt") + public void testSuspendLambda() throws Exception { + runTest("compiler/testData/codegen/box/annotations/annotatedLambda/suspendLambda.kt"); + } } @Nested diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt index 4b28eb979d4..91dc92877ec 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt @@ -254,6 +254,8 @@ private class SuspendLambdaLowering(context: JvmBackendContext) : SuspendLowerin }, null) context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET, localVals.filterNotNull() + body.statements) } + + copyAnnotationsFrom(irFunction) } } diff --git a/compiler/testData/codegen/box/annotations/annotatedLambda/lambda.kt b/compiler/testData/codegen/box/annotations/annotatedLambda/lambda.kt index 0dd5abd9787..f83c3fb6d2a 100644 --- a/compiler/testData/codegen/box/annotations/annotatedLambda/lambda.kt +++ b/compiler/testData/codegen/box/annotations/annotatedLambda/lambda.kt @@ -27,8 +27,6 @@ fun testClass(clazz: Class<*>, name: String) { fun box(): String { testClass(foo0(@Ann("OK") { }), "1") - testClass(foo0( @Ann("OK") { }), "2") - - testClass(foo0() @Ann("OK") { }, "3") + testClass(foo0() @Ann("OK") { }, "2") return "OK" } diff --git a/compiler/testData/codegen/box/annotations/annotatedLambda/suspendLambda.kt b/compiler/testData/codegen/box/annotations/annotatedLambda/suspendLambda.kt new file mode 100644 index 00000000000..6af694f995a --- /dev/null +++ b/compiler/testData/codegen/box/annotations/annotatedLambda/suspendLambda.kt @@ -0,0 +1,45 @@ +// TARGET_BACKEND: JVM +// WITH_STDLIB +// Only implemented in the IR backend. +// IGNORE_BACKEND: JVM + +import java.lang.reflect.Method +import kotlin.test.assertEquals + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.RUNTIME) +annotation class Ann(val x: String) + +fun foo0(block: suspend () -> Unit) = block.javaClass + +fun testHasAnnotation(method: Method, name: String) { + assertEquals( + "OK", + method.getAnnotation(Ann::class.java)?.x, + "Missing or incorrect annotation on method `${method.name}` of test named `$name`" + ) +} + +fun testDoesNotHaveAnnotation(method: Method, name: String) { + assertEquals( + null, + method.getAnnotation(Ann::class.java), + "Unexpected annotation on method `${method.name}` of test named `$name`" + ) +} + +fun testClass(clazz: Class<*>, name: String) { + // Check that non-bridge `invokeSuspend` contains the suspend lambda annotation. + val invokeSuspends = clazz.getDeclaredMethods().filter { !it.isBridge() && it.name == "invokeSuspend" } + invokeSuspends.forEach { testHasAnnotation(it, name) } + // Check that non-bridge `invoke` does not contain the suspend lambda annotation. + val invokes = clazz.getDeclaredMethods().filter { !it.isBridge() && it.name == "invoke" } + invokes.forEach { testDoesNotHaveAnnotation(it, name) } + +} + +fun box(): String { + testClass(foo0(@Ann("OK") { }), "1") + testClass(foo0() @Ann("OK") { }, "2") + return "OK" +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 4cc22166322..3f1dcc9f6ce 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -403,6 +403,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testSamLambda() throws Exception { runTest("compiler/testData/codegen/box/annotations/annotatedLambda/samLambda.kt"); } + + @Test + @TestMetadata("suspendLambda.kt") + public void testSuspendLambda() throws Exception { + runTest("compiler/testData/codegen/box/annotations/annotatedLambda/suspendLambda.kt"); + } } @Nested diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 11c38c0ead0..8a8d7072f71 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -421,6 +421,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testSamLambda() throws Exception { runTest("compiler/testData/codegen/box/annotations/annotatedLambda/samLambda.kt"); } + + @Test + @TestMetadata("suspendLambda.kt") + public void testSuspendLambda() throws Exception { + runTest("compiler/testData/codegen/box/annotations/annotatedLambda/suspendLambda.kt"); + } } @Nested diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index afc73b94b16..431220d534b 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -322,6 +322,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class AnnotatedLambda extends AbstractLightAnalysisModeTest { + @TestMetadata("suspendLambda.kt") + public void ignoreSuspendLambda() throws Exception { + runTest("compiler/testData/codegen/box/annotations/annotatedLambda/suspendLambda.kt"); + } + private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); }