Map annotation target TYPE -> TYPE_USE if JVM target >= 1.8
And TYPE_PARAMETER -> TYPE_PARAMETER similarly #KT-23857 Fixed
This commit is contained in:
@@ -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<KotlinTarget, ElementType> annotationTargetMap = new EnumMap<>(KotlinTarget.class);
|
||||
private static final Map<JvmTarget, Map<KotlinTarget, ElementType>> 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<KotlinTarget, ElementType> 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<KotlinTarget, ElementType> 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<String> annotationDescriptorsAlreadyPresent) {
|
||||
private void generateTargetAnnotation(
|
||||
@NotNull ClassDescriptor classDescriptor, @NotNull Set<String> annotationDescriptorsAlreadyPresent
|
||||
) {
|
||||
String descriptor = Type.getType(Target.class).getDescriptor();
|
||||
if (!annotationDescriptorsAlreadyPresent.add(descriptor)) return;
|
||||
|
||||
Map<KotlinTarget, ElementType> annotationTargetMap = annotationTargetMaps.get(typeMapper.getJvmTarget());
|
||||
if (annotationTargetMap == null) throw new AssertionError("No annotation target map for JVM target " + typeMapper.getJvmTarget());
|
||||
|
||||
Set<KotlinTarget> targets = AnnotationChecker.Companion.applicableTargetSet(classDescriptor);
|
||||
Set<ElementType> 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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
+22
@@ -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"
|
||||
}
|
||||
+30
@@ -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"
|
||||
}
|
||||
Generated
+23
@@ -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)
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user