KT-57135 Take into account annotations' allowed targets

- Check allowed targets
- Attach field annotations to the backing field
This commit is contained in:
Pavel Mikhailovskii
2023-03-21 15:07:49 +01:00
committed by Space Team
parent ea2145415d
commit 37ed7beda0
19 changed files with 445 additions and 25 deletions
@@ -24,6 +24,12 @@ public class SymbolLightClassesByPsiForLibraryTestGenerated extends AbstractSymb
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/asJava/lightClasses/lightClassByPsi"), Pattern.compile("^(.+)\\.(kt|kts)$"), null, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/allowedTargets.kt");
}
@Test
@TestMetadata("annotationWithSetParamPropertyModifier.kt")
public void testAnnotationWithSetParamPropertyModifier() throws Exception {
@@ -24,6 +24,12 @@ public class SymbolLightClassesEqualityByPsiForLibraryTestGenerated extends Abst
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/asJava/lightClasses/lightClassByPsi"), Pattern.compile("^(.+)\\.(kt|kts)$"), null, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/allowedTargets.kt");
}
@Test
@TestMetadata("annotationWithSetParamPropertyModifier.kt")
public void testAnnotationWithSetParamPropertyModifier() throws Exception {
@@ -24,6 +24,12 @@ public class SymbolLightClassesParentingByPsiForLibraryTestGenerated extends Abs
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/asJava/lightClasses/lightClassByPsi"), Pattern.compile("^(.+)\\.(kt|kts)$"), null, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/allowedTargets.kt");
}
@Test
@TestMetadata("annotationWithSetParamPropertyModifier.kt")
public void testAnnotationWithSetParamPropertyModifier() throws Exception {
@@ -24,6 +24,12 @@ public class SymbolLightClassesByPsiForSourceTestGenerated extends AbstractSymbo
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/asJava/lightClasses/lightClassByPsi"), Pattern.compile("^(.+)\\.(kt|kts)$"), null, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/allowedTargets.kt");
}
@Test
@TestMetadata("annotationWithSetParamPropertyModifier.kt")
public void testAnnotationWithSetParamPropertyModifier() throws Exception {
@@ -24,6 +24,12 @@ public class SymbolLightClassesEqualityByPsiForSourceTestGenerated extends Abstr
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/asJava/lightClasses/lightClassByPsi"), Pattern.compile("^(.+)\\.(kt|kts)$"), null, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/allowedTargets.kt");
}
@Test
@TestMetadata("annotationWithSetParamPropertyModifier.kt")
public void testAnnotationWithSetParamPropertyModifier() throws Exception {
@@ -24,6 +24,12 @@ public class SymbolLightClassesParentingByPsiForSourceTestGenerated extends Abst
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/asJava/lightClasses/lightClassByPsi"), Pattern.compile("^(.+)\\.(kt|kts)$"), null, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/asJava/lightClasses/lightClassByPsi/allowedTargets.kt");
}
@Test
@TestMetadata("annotationWithSetParamPropertyModifier.kt")
public void testAnnotationWithSetParamPropertyModifier() throws Exception {
@@ -62,10 +62,12 @@ class AnnotationGenerator(private val components: Fir2IrComponents) : Fir2IrComp
val irProperty = irField.correspondingPropertySymbol?.owner ?: throw AssertionError("$irField is not a property field")
val applicableTargets = if (irProperty.isDelegated) delegatedPropertyTargets else propertyTargets
irField.annotations += property.annotations.filter {
val target = it.target(applicableTargets)
target == AnnotationUseSiteTarget.FIELD || target == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
}.toIrAnnotations()
property.backingField?.let {
irField.annotations += it.annotations.filter {
val target = it.target(applicableTargets)
target == AnnotationUseSiteTarget.FIELD || target == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
}.toIrAnnotations()
}
}
fun generate(propertyAccessor: IrFunction, property: FirProperty) {
@@ -41,6 +41,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/codegen/box/annotations/allowedTargets.kt");
}
@Test
@TestMetadata("annotatedAnnotationParameter.kt")
public void testAnnotatedAnnotationParameter() throws Exception {
@@ -41,6 +41,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/codegen/box/annotations/allowedTargets.kt");
}
@Test
@TestMetadata("annotatedAnnotationParameter.kt")
public void testAnnotatedAnnotationParameter() throws Exception {
@@ -147,7 +147,7 @@ open class FirTypeResolveTransformer(
if (result.isPrimary) {
for (valueParameter in result.valueParameters) {
if (valueParameter.correspondingProperty != null) {
valueParameter.removeDuplicateAnnotationsOfPrimaryConstructorElement()
valueParameter.removeIrrelevantAnnotations()
}
}
}
@@ -219,7 +219,7 @@ open class FirTypeResolveTransformer(
unboundCyclesInTypeParametersSupertypes(property)
if (property.source?.kind == KtFakeSourceElementKind.PropertyFromParameter) {
property.removeDuplicateAnnotationsOfPrimaryConstructorElement()
property.removeIrrelevantAnnotations()
}
calculateDeprecations(property)
@@ -480,28 +480,37 @@ open class FirTypeResolveTransformer(
}
/**
* In a scenario like
*
* Filters annotations by target.
* For example, in the following snippet the annotation may apply to the constructor value parameter, the property or the underlying field:
* ```
* annotation class Ann
* class Foo(@Ann val x: String)
* ```
*
* both, the primary ctor value parameter and the property `x` will be annotated with `@Ann`. This is due to the fact, that the
* annotation needs to be resolved in order to determine its annotation targets. We remove annotations from the wrong target if they
* don't explicitly specify the use-site target (in which case they shouldn't have been added to the element in the raw FIR).
*
* For value parameters, we remove the annotation if the targets don't include [AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER].
* For properties, we remove the annotation, if the targets include [AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER].
* This ambiguity may be resolved by specifying the use-site explicitly, i.e. `@field:Ann` or by analysing the allowed targets from
* the [kotlin.annotation.Target] meta-annotation. In latter case, the method will assign a use-site target to the corresponding
* annotation.
*/
private fun FirVariable.removeDuplicateAnnotationsOfPrimaryConstructorElement() {
val isParameter = this is FirValueParameter
replaceAnnotations(annotations.filter {
it.useSiteTarget != null ||
// equivalent to
// CONSTRUCTOR_PARAMETER in targets && isParameter ||
// CONSTRUCTOR_PARAMETER !in targets && !isParameter
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER in it.useSiteTargetsFromMetaAnnotation(session) == isParameter
private fun FirVariable.removeIrrelevantAnnotations() {
replaceAnnotations(annotations.filter { annotation ->
when(annotation.useSiteTarget) {
null -> {
val allowedTargets = annotation.useSiteTargetsFromMetaAnnotation(session)
when {
this is FirValueParameter -> AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER in allowedTargets
this.source?.kind == KtFakeSourceElementKind.PropertyFromParameter && AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER in allowedTargets -> false
this is FirProperty && AnnotationUseSiteTarget.FIELD in allowedTargets && AnnotationUseSiteTarget.PROPERTY !in allowedTargets && backingField != null -> {
(this as? FirProperty)?.backingField?.replaceAnnotations(backingField!!.annotations + annotation)
false
}
else -> true
}
}
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER -> this is FirValueParameter
AnnotationUseSiteTarget.FIELD -> {
(this as? FirProperty)?.backingField?.replaceAnnotations(backingField!!.annotations + annotation)
false
}
else -> true
}
})
}
@@ -1135,6 +1135,7 @@ class JvmSymbols(
KotlinTarget.PROPERTY_GETTER to etMethod,
KotlinTarget.PROPERTY_SETTER to etMethod,
KotlinTarget.FIELD to buildEnumEntry(elementTypeEnum, "FIELD"),
KotlinTarget.BACKING_FIELD to buildEnumEntry(elementTypeEnum, "FIELD"),
KotlinTarget.VALUE_PARAMETER to buildEnumEntry(elementTypeEnum, "PARAMETER")
)
@@ -0,0 +1,80 @@
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
public abstract @interface AnotherUniversalAnnotation /* AnotherUniversalAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.FIELD})
public abstract @interface FieldAnnotation /* FieldAnnotation*/ {
}
public final class MyClass /* MyClass*/ {
@AnotherUniversalAnnotation()
private final int x5;
@FieldAnnotation()
private final int x1;
@UniversalAnnotation()
private final int x6;
private final int x2;
private final int x3;
private final int x4;
private final int x7;
public MyClass(@AnotherUniversalAnnotation() @ParameterAnnotation() @UniversalAnnotation() int, int, @PropertyOrParameterAnnotation() int, @ParameterOrFieldAnnotation() int, int, @AnotherUniversalAnnotation() int, @UniversalAnnotation() int);// .ctor(int, int, int, int, int, int, int)
public final int getX1();// getX1()
public final int getX2();// getX2()
public final int getX3();// getX3()
public final int getX4();// getX4()
public final int getX5();// getX5()
public final int getX6();// getX6()
public final int getX7();// getX7()
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface ParameterAnnotation /* ParameterAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.FIELD, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface ParameterOrFieldAnnotation /* ParameterOrFieldAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY})
public abstract @interface PropertyAnnotation /* PropertyAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.FIELD})
public abstract @interface PropertyOrFieldAnnotation /* PropertyOrFieldAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface PropertyOrParameterAnnotation /* PropertyOrParameterAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.FIELD, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface UniversalAnnotation /* UniversalAnnotation*/ {
}
@@ -0,0 +1,80 @@
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
public abstract @interface AnotherUniversalAnnotation /* AnotherUniversalAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.FIELD})
public abstract @interface FieldAnnotation /* FieldAnnotation*/ {
}
public final class MyClass /* MyClass*/ {
@AnotherUniversalAnnotation()
private final int x5;
@FieldAnnotation()
private final int x1;
@UniversalAnnotation()
private final int x6;
private final int x2;
private final int x3;
private final int x4;
private final int x7;
public MyClass(@AnotherUniversalAnnotation() @FieldAnnotation() @ParameterAnnotation() @PropertyAnnotation() @UniversalAnnotation() int, @PropertyOrFieldAnnotation() int, @PropertyOrParameterAnnotation() int, @ParameterOrFieldAnnotation() int, int, @AnotherUniversalAnnotation() int, @UniversalAnnotation() int);// .ctor(int, int, int, int, int, int, int)
public final int getX1();// getX1()
public final int getX2();// getX2()
public final int getX3();// getX3()
public final int getX4();// getX4()
public final int getX5();// getX5()
public final int getX6();// getX6()
public final int getX7();// getX7()
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface ParameterAnnotation /* ParameterAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.FIELD, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface ParameterOrFieldAnnotation /* ParameterOrFieldAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY})
public abstract @interface PropertyAnnotation /* PropertyAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.FIELD})
public abstract @interface PropertyOrFieldAnnotation /* PropertyOrFieldAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface PropertyOrParameterAnnotation /* PropertyOrParameterAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.FIELD, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface UniversalAnnotation /* UniversalAnnotation*/ {
}
@@ -0,0 +1,33 @@
@Target(AnnotationTarget.PROPERTY)
annotation class PropertyAnnotation
@Target(AnnotationTarget.FIELD)
annotation class FieldAnnotation
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class ParameterAnnotation
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD)
annotation class PropertyOrFieldAnnotation
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
annotation class PropertyOrParameterAnnotation
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
annotation class ParameterOrFieldAnnotation
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
annotation class UniversalAnnotation
annotation class AnotherUniversalAnnotation
class MyClass(
@PropertyAnnotation @FieldAnnotation @ParameterAnnotation @UniversalAnnotation @AnotherUniversalAnnotation val x1: Int,
@PropertyOrFieldAnnotation val x2: Int,
@PropertyOrParameterAnnotation val x3: Int,
@ParameterOrFieldAnnotation val x4: Int,
@property:UniversalAnnotation @field:AnotherUniversalAnnotation val x5: Int,
@field:UniversalAnnotation @param:AnotherUniversalAnnotation val x6: Int,
@param:UniversalAnnotation @property:AnotherUniversalAnnotation val x7: Int
)
@@ -0,0 +1,80 @@
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
public abstract @interface AnotherUniversalAnnotation /* AnotherUniversalAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.FIELD})
public abstract @interface FieldAnnotation /* FieldAnnotation*/ {
}
public final class MyClass /* MyClass*/ {
@AnotherUniversalAnnotation()
private final int x5;
@FieldAnnotation()
private final int x1;
@UniversalAnnotation()
private final int x6;
private final int x2;
private final int x3;
private final int x4;
private final int x7;
public MyClass(@AnotherUniversalAnnotation() @ParameterAnnotation() @UniversalAnnotation() int, int, @PropertyOrParameterAnnotation() int, @ParameterOrFieldAnnotation() int, int, @AnotherUniversalAnnotation() int, @UniversalAnnotation() int);// .ctor(int, int, int, int, int, int, int)
public final int getX1();// getX1()
public final int getX2();// getX2()
public final int getX3();// getX3()
public final int getX4();// getX4()
public final int getX5();// getX5()
public final int getX6();// getX6()
public final int getX7();// getX7()
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface ParameterAnnotation /* ParameterAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.FIELD, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface ParameterOrFieldAnnotation /* ParameterOrFieldAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY})
public abstract @interface PropertyAnnotation /* PropertyAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.FIELD})
public abstract @interface PropertyOrFieldAnnotation /* PropertyOrFieldAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface PropertyOrParameterAnnotation /* PropertyOrParameterAnnotation*/ {
}
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER})
@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.PROPERTY, kotlin.annotation.AnnotationTarget.FIELD, kotlin.annotation.AnnotationTarget.VALUE_PARAMETER})
public abstract @interface UniversalAnnotation /* UniversalAnnotation*/ {
}
@@ -0,0 +1,73 @@
// WITH_STDLIB
// WITH_REFLECT
// TARGET_BACKEND: JVM_IR
import kotlin.test.assertEquals
import kotlin.reflect.*
import kotlin.reflect.jvm.javaField
@Target(AnnotationTarget.PROPERTY)
annotation class PropertyAnnotation
@Target(AnnotationTarget.FIELD)
annotation class FieldAnnotation
@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class ParameterAnnotation
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD)
annotation class PropertyOrFieldAnnotation
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
annotation class PropertyOrParameterAnnotation
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
annotation class ParameterOrFieldAnnotation
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER)
annotation class UniversalAnnotation
annotation class AnotherUniversalAnnotation
class C(
@PropertyAnnotation @FieldAnnotation @ParameterAnnotation @UniversalAnnotation @AnotherUniversalAnnotation val x1: Int,
@PropertyOrFieldAnnotation val x2: Int,
@PropertyOrParameterAnnotation val x3: Int,
@ParameterOrFieldAnnotation val x4: Int,
@property:UniversalAnnotation @field:AnotherUniversalAnnotation val x5: Int,
@field:UniversalAnnotation @param:AnotherUniversalAnnotation val x6: Int,
@param:UniversalAnnotation @property:AnotherUniversalAnnotation val x7: Int
)
fun box(): String {
val parameterAnnotations = C::class.constructors.single().parameters.map { it.name to it.annotations.map { it.annotationClass.simpleName ?: "" }.toSet() }.toMap()
assertEquals(setOf("ParameterAnnotation", "UniversalAnnotation", "AnotherUniversalAnnotation"), parameterAnnotations["x1"])
assertEquals(setOf(), parameterAnnotations["x2"])
assertEquals(setOf("PropertyOrParameterAnnotation"), parameterAnnotations["x3"])
assertEquals(setOf("ParameterOrFieldAnnotation"), parameterAnnotations["x4"])
assertEquals(setOf(), parameterAnnotations["x5"])
assertEquals(setOf("AnotherUniversalAnnotation"), parameterAnnotations["x6"])
assertEquals(setOf("UniversalAnnotation"), parameterAnnotations["x7"])
val properties = C::class.members.filterIsInstance<KProperty<*>>()
val propertyAnnotations = properties.map { it.name to it.annotations.map { it.annotationClass.simpleName ?: "" }.toSet() }.toMap()
assertEquals(setOf("PropertyAnnotation"), propertyAnnotations["x1"])
assertEquals(setOf("PropertyOrFieldAnnotation"), propertyAnnotations["x2"])
assertEquals(setOf(), propertyAnnotations["x3"])
assertEquals(setOf(), propertyAnnotations["x4"])
assertEquals(setOf("UniversalAnnotation"), propertyAnnotations["x5"])
assertEquals(setOf(), propertyAnnotations["x6"])
assertEquals(setOf("AnotherUniversalAnnotation"), propertyAnnotations["x7"])
val fieldAnnotations = properties.map { it.javaField!! }.map { it.name to it.declaredAnnotations.map { it.annotationClass.simpleName ?: "" }.toSet() }.toMap()
assertEquals(setOf("FieldAnnotation"), fieldAnnotations["x1"])
assertEquals(setOf(), fieldAnnotations["x2"])
assertEquals(setOf(), fieldAnnotations["x3"])
assertEquals(setOf(), fieldAnnotations["x4"])
assertEquals(setOf("AnotherUniversalAnnotation"), fieldAnnotations["x5"])
assertEquals(setOf("UniversalAnnotation"), fieldAnnotations["x6"])
assertEquals(setOf(), fieldAnnotations["x7"])
return "OK"
}
@@ -41,6 +41,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/codegen/box/annotations/allowedTargets.kt");
}
@Test
@TestMetadata("annotatedAnnotationParameter.kt")
public void testAnnotatedAnnotationParameter() throws Exception {
@@ -41,6 +41,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("allowedTargets.kt")
public void testAllowedTargets() throws Exception {
runTest("compiler/testData/codegen/box/annotations/allowedTargets.kt");
}
@Test
@TestMetadata("annotatedAnnotationParameter.kt")
public void testAnnotatedAnnotationParameter() throws Exception {
@@ -54,7 +54,9 @@ object AnnotationTargetLists {
val T_PROPERTY_GETTER = targetList(PROPERTY_GETTER)
val T_PROPERTY_SETTER = targetList(PROPERTY_SETTER)
val T_BACKING_FIELD = targetList(BACKING_FIELD)
val T_BACKING_FIELD = targetList(BACKING_FIELD) {
extraTargets(FIELD)
}
val T_VALUE_PARAMETER_WITHOUT_VAL = targetList(VALUE_PARAMETER)