diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 5b9614abc84..d68e6faacc9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.annotation.WrappedAnnotated; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; +import org.jetbrains.kotlin.config.JvmTarget; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.*; import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; @@ -87,9 +88,9 @@ public abstract class AnnotationCodegen { private final InnerClassConsumer innerClassConsumer; private final KotlinTypeMapper typeMapper; - private AnnotationCodegen(@NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper mapper) { + private AnnotationCodegen(@NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper typeMapper) { this.innerClassConsumer = innerClassConsumer; - this.typeMapper = mapper; + this.typeMapper = typeMapper; } /** @@ -217,23 +218,37 @@ public abstract class AnnotationCodegen { generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationClass); } - private static final Map annotationTargetMap = new EnumMap<>(KotlinTarget.class); + private static final Map> annotationTargetMaps = new EnumMap<>(JvmTarget.class); static { - annotationTargetMap.put(KotlinTarget.CLASS, ElementType.TYPE); - annotationTargetMap.put(KotlinTarget.ANNOTATION_CLASS, ElementType.ANNOTATION_TYPE); - annotationTargetMap.put(KotlinTarget.CONSTRUCTOR, ElementType.CONSTRUCTOR); - annotationTargetMap.put(KotlinTarget.LOCAL_VARIABLE, ElementType.LOCAL_VARIABLE); - annotationTargetMap.put(KotlinTarget.FUNCTION, ElementType.METHOD); - annotationTargetMap.put(KotlinTarget.PROPERTY_GETTER, ElementType.METHOD); - annotationTargetMap.put(KotlinTarget.PROPERTY_SETTER, ElementType.METHOD); - annotationTargetMap.put(KotlinTarget.FIELD, ElementType.FIELD); - annotationTargetMap.put(KotlinTarget.VALUE_PARAMETER, ElementType.PARAMETER); + Map jvm6 = new EnumMap<>(KotlinTarget.class); + jvm6.put(KotlinTarget.CLASS, ElementType.TYPE); + jvm6.put(KotlinTarget.ANNOTATION_CLASS, ElementType.ANNOTATION_TYPE); + jvm6.put(KotlinTarget.CONSTRUCTOR, ElementType.CONSTRUCTOR); + jvm6.put(KotlinTarget.LOCAL_VARIABLE, ElementType.LOCAL_VARIABLE); + jvm6.put(KotlinTarget.FUNCTION, ElementType.METHOD); + jvm6.put(KotlinTarget.PROPERTY_GETTER, ElementType.METHOD); + jvm6.put(KotlinTarget.PROPERTY_SETTER, ElementType.METHOD); + jvm6.put(KotlinTarget.FIELD, ElementType.FIELD); + jvm6.put(KotlinTarget.VALUE_PARAMETER, ElementType.PARAMETER); + + Map jvm8 = new EnumMap<>(jvm6); + jvm8.put(KotlinTarget.TYPE_PARAMETER, ElementType.TYPE_PARAMETER); + jvm8.put(KotlinTarget.TYPE, ElementType.TYPE_USE); + + annotationTargetMaps.put(JvmTarget.JVM_1_6, jvm6); + annotationTargetMaps.put(JvmTarget.JVM_1_8, jvm8); } - private void generateTargetAnnotation(@NotNull ClassDescriptor classDescriptor, @NotNull Set annotationDescriptorsAlreadyPresent) { + private void generateTargetAnnotation( + @NotNull ClassDescriptor classDescriptor, @NotNull Set annotationDescriptorsAlreadyPresent + ) { String descriptor = Type.getType(Target.class).getDescriptor(); if (!annotationDescriptorsAlreadyPresent.add(descriptor)) return; + + Map annotationTargetMap = annotationTargetMaps.get(typeMapper.getJvmTarget()); + if (annotationTargetMap == null) throw new AssertionError("No annotation target map for JVM target " + typeMapper.getJvmTarget()); + Set targets = AnnotationChecker.Companion.applicableTargetSet(classDescriptor); Set javaTargets; if (targets == null) { @@ -243,8 +258,10 @@ public abstract class AnnotationCodegen { else { javaTargets = EnumSet.noneOf(ElementType.class); for (KotlinTarget target : targets) { - if (annotationTargetMap.get(target) == null) continue; - javaTargets.add(annotationTargetMap.get(target)); + ElementType elementType = annotationTargetMap.get(target); + if (elementType != null) { + javaTargets.add(elementType); + } } } AnnotationVisitor visitor = visitAnnotation(descriptor, true); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index 33cebbb3b58..0247e31aea2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -178,6 +178,11 @@ public class KotlinTypeMapper { return bindingContext; } + @NotNull + public JvmTarget getJvmTarget() { + return jvmTarget; + } + @NotNull public Type mapOwner(@NotNull DeclarationDescriptor descriptor) { return mapOwner(descriptor, true); diff --git a/compiler/testData/codegen/box/annotations/typeAnnotationOnJdk6.kt b/compiler/testData/codegen/box/annotations/typeAnnotationOnJdk6.kt new file mode 100644 index 00000000000..0e2d9aea7e6 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/typeAnnotationOnJdk6.kt @@ -0,0 +1,11 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME + +@Target(AnnotationTarget.TYPE) +annotation class A + +fun box(): String { + A::class.java.declaredAnnotations.joinToString() + ExtensionFunctionType::class.java.declaredAnnotations.joinToString() + return "OK" +} diff --git a/compiler/testData/codegen/java8/box/annotations/useTypeParameterAnnotationFromJava.kt b/compiler/testData/codegen/java8/box/annotations/useTypeParameterAnnotationFromJava.kt new file mode 100644 index 00000000000..1f656d25d54 --- /dev/null +++ b/compiler/testData/codegen/java8/box/annotations/useTypeParameterAnnotationFromJava.kt @@ -0,0 +1,22 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// FULL_JDK +// JVM_TARGET: 1.8 +// FILE: A.java +import java.util.List; + +public class A<@Anno(1) T> {} + +// FILE: Anno.kt + +import kotlin.test.assertEquals + +@Target(AnnotationTarget.TYPE_PARAMETER) +annotation class Anno(val value: Int = 0) + +fun box(): String { + val typeParameter = A::class.java.typeParameters.single() + assertEquals("[@Anno(value=1)]", typeParameter.annotations.toList().toString()) + + return "OK" +} diff --git a/compiler/testData/codegen/java8/box/annotations/useTypeUseAnnotationFromJava.kt b/compiler/testData/codegen/java8/box/annotations/useTypeUseAnnotationFromJava.kt new file mode 100644 index 00000000000..800fc34202e --- /dev/null +++ b/compiler/testData/codegen/java8/box/annotations/useTypeUseAnnotationFromJava.kt @@ -0,0 +1,30 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// FULL_JDK +// JVM_TARGET: 1.8 +// FILE: A.java +import java.util.List; + +public class A { + public static @Anno(1) String test(List<@Anno(2) String> list) { + return list.get(0); + } +} + +// FILE: Anno.kt + +import java.lang.reflect.AnnotatedParameterizedType +import kotlin.test.assertEquals + +@Target(AnnotationTarget.TYPE) +annotation class Anno(val value: Int = 0) + +fun box(): String { + val method = A::class.java.declaredMethods.single() + assertEquals("[@Anno(value=1)]", method.annotatedReturnType.annotations.toList().toString()) + + val parameterType = method.parameters.single().annotatedType as AnnotatedParameterizedType + assertEquals("[@Anno(value=2)]", parameterType.annotatedActualTypeArguments.single().annotations.toList().toString()) + + return "OK" +} diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java index 85d641cec84..f56e0f3c6d0 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java @@ -133,6 +133,29 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg runTest("compiler/testData/codegen/java8/box/useStream.kt"); } + @TestMetadata("compiler/testData/codegen/java8/box/annotations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Annotations extends AbstractBlackBoxCodegenTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInAnnotations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/java8/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("useTypeParameterAnnotationFromJava.kt") + public void testUseTypeParameterAnnotationFromJava() throws Exception { + runTest("compiler/testData/codegen/java8/box/annotations/useTypeParameterAnnotationFromJava.kt"); + } + + @TestMetadata("useTypeUseAnnotationFromJava.kt") + public void testUseTypeUseAnnotationFromJava() throws Exception { + runTest("compiler/testData/codegen/java8/box/annotations/useTypeUseAnnotationFromJava.kt"); + } + } + @TestMetadata("compiler/testData/codegen/java8/box/builtinStubMethods") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 6d348d5f8f3..3fa6faddadf 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -151,6 +151,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/annotations/singleAssignmentToVarargInAnnotation.kt"); } + @TestMetadata("typeAnnotationOnJdk6.kt") + public void testTypeAnnotationOnJdk6() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotationOnJdk6.kt"); + } + @TestMetadata("varargInAnnotationParameter.kt") public void testVarargInAnnotationParameter() throws Exception { runTest("compiler/testData/codegen/box/annotations/varargInAnnotationParameter.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 2c63fc54097..7accc803f05 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -156,6 +156,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/annotations/singleAssignmentToVarargInAnnotation.kt"); } + @TestMetadata("typeAnnotationOnJdk6.kt") + public void testTypeAnnotationOnJdk6() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotationOnJdk6.kt"); + } + @TestMetadata("varargInAnnotationParameter.kt") public void testVarargInAnnotationParameter() throws Exception { runTest("compiler/testData/codegen/box/annotations/varargInAnnotationParameter.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index f60cd50720c..1122b771ed5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -151,6 +151,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/annotations/singleAssignmentToVarargInAnnotation.kt"); } + @TestMetadata("typeAnnotationOnJdk6.kt") + public void testTypeAnnotationOnJdk6() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotationOnJdk6.kt"); + } + @TestMetadata("varargInAnnotationParameter.kt") public void testVarargInAnnotationParameter() throws Exception { runTest("compiler/testData/codegen/box/annotations/varargInAnnotationParameter.kt");