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:
Alexander Udalov
2018-04-25 15:48:13 +02:00
parent b7808ba24d
commit 1c2a9e4b21
9 changed files with 138 additions and 15 deletions
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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)
@@ -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");
@@ -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");
@@ -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");