diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index c76fb2f1cad..d7540193dc8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.annotation.WrappedAnnotated; import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.*; +import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.kotlin.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.resolve.AnnotationChecker; @@ -105,6 +106,16 @@ public abstract class AnnotationCodegen { // Skip if the target is not the same if (allowedTarget != null && annotationTarget != null && allowedTarget != annotationTarget) continue; + Set applicableTargets = AnnotationChecker.applicableTargetSet(annotation); + if (annotated instanceof AnonymousFunctionDescriptor + && !applicableTargets.contains(KotlinTarget.FUNCTION) + && !applicableTargets.contains(KotlinTarget.PROPERTY_GETTER) + && !applicableTargets.contains(KotlinTarget.PROPERTY_SETTER)) { + assert (applicableTargets.contains(KotlinTarget.EXPRESSION)) : + "Inconsistent target list for lambda annotation: " + applicableTargets + " on " + annotated; + continue; + } + String descriptor = genAnnotation(annotation); if (descriptor != null) { annotationDescriptorsAlreadyPresent.add(descriptor); diff --git a/compiler/testData/codegen/boxWithJava/annotatedSamLambda/annotatedSamLambda.kt b/compiler/testData/codegen/boxWithJava/annotatedSamLambda/annotatedSamLambda.kt index 664daa280cf..3ac0b147c86 100644 --- a/compiler/testData/codegen/boxWithJava/annotatedSamLambda/annotatedSamLambda.kt +++ b/compiler/testData/codegen/boxWithJava/annotatedSamLambda/annotatedSamLambda.kt @@ -1,7 +1,7 @@ import java.lang.reflect.Method import kotlin.test.assertEquals -@Target(AnnotationTarget.EXPRESSION) +@Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) annotation class Ann(val x: String) diff --git a/compiler/testData/codegen/boxWithStdlib/annotations/annotatedLambda/lambda.kt b/compiler/testData/codegen/boxWithStdlib/annotations/annotatedLambda/lambda.kt index 6384c03c07e..d6eddf8201b 100644 --- a/compiler/testData/codegen/boxWithStdlib/annotations/annotatedLambda/lambda.kt +++ b/compiler/testData/codegen/boxWithStdlib/annotations/annotatedLambda/lambda.kt @@ -1,7 +1,7 @@ import java.lang.reflect.Method import kotlin.test.assertEquals -@Target(AnnotationTarget.EXPRESSION) +@Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) annotation class Ann(val x: String) diff --git a/compiler/testData/codegen/bytecodeListing/annotations/literals.kt b/compiler/testData/codegen/bytecodeListing/annotations/literals.kt new file mode 100644 index 00000000000..c4947fb49d6 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/literals.kt @@ -0,0 +1,20 @@ +@Target(AnnotationTarget.CLASS) +annotation class ClsAnn + +@Target(AnnotationTarget.FUNCTION) +annotation class FunAnn + +@Target(AnnotationTarget.EXPRESSION) +annotation class ExprAnn + +fun bar(arg: () -> Int) = arg() + +open class My + +fun foo(arg: Int): My { + bar @FunAnn { arg } + bar @ExprAnn { arg } + val x = @FunAnn fun() = arg + // TODO: KT-9320: ClsAnn does not appear in bytecode + return (@ClsAnn object: My() {}) +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/annotations/literals.txt b/compiler/testData/codegen/bytecodeListing/annotations/literals.txt new file mode 100644 index 00000000000..7ceb93edb71 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/annotations/literals.txt @@ -0,0 +1,59 @@ +@kotlin.annotation.Target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass ClsAnn + +@kotlin.annotation.Target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass ExprAnn + +@kotlin.annotation.Target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass FunAnn + +@kotlin.jvm.internal.KotlinSyntheticClass @kotlin.jvm.internal.KotlinCallable LiteralsKt$foo$1 { + inner class LiteralsKt$foo$1 + field $arg: int + method invoke(): java.lang.Object + @FunAnn method invoke(): int + method (p0: int): void +} + +@kotlin.jvm.internal.KotlinSyntheticClass @kotlin.jvm.internal.KotlinCallable LiteralsKt$foo$2 { + inner class LiteralsKt$foo$2 + field $arg: int + method invoke(): java.lang.Object + method invoke(): int + method (p0: int): void +} + +@kotlin.jvm.internal.KotlinClass LiteralsKt$foo$3 { + inner class LiteralsKt$foo$3 + field $kotlinClass: kotlin.reflect.KClass + method (): void + method (): void +} + +@kotlin.jvm.internal.KotlinSyntheticClass @kotlin.jvm.internal.KotlinCallable LiteralsKt$foo$x$1 { + inner class LiteralsKt$foo$x$1 + field $arg: int + method invoke(): java.lang.Object + @FunAnn method invoke(): int + method (p0: int): void +} + +@kotlin.jvm.internal.KotlinFileFacade LiteralsKt { + inner class LiteralsKt$foo$1 + inner class LiteralsKt$foo$2 + inner class LiteralsKt$foo$x$1 + inner class LiteralsKt$foo$3 + method bar(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): int + @org.jetbrains.annotations.NotNull method foo(p0: int): My +} + +@kotlin.jvm.internal.KotlinClass My { + field $kotlinClass: kotlin.reflect.KClass + method (): void + method (): void +} + +@java.lang.Deprecated @kotlin.jvm.internal.KotlinPackage _DefaultPackage { + field $kotlinPackage: kotlin.reflect.KPackage + field $moduleName: java.lang.String + method (): void + @kotlin.jvm.internal.KotlinDelegatedMethod method bar(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0): int + @kotlin.jvm.internal.KotlinDelegatedMethod @org.jetbrains.annotations.NotNull method foo(p0: int): My +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 5a6164227e7..84a96b266e5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -49,6 +49,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { doTest(fileName); } + @TestMetadata("literals.kt") + public void testLiterals() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/literals.kt"); + doTest(fileName); + } + @TestMetadata("onProperties.kt") public void testOnProperties() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/annotations/onProperties.kt");