KT-57135 Take into account annotations' allowed targets
- Check allowed targets - Attach field annotations to the backing field
This commit is contained in:
committed by
Space Team
parent
ea2145415d
commit
37ed7beda0
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
-4
@@ -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) {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+29
-20
@@ -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")
|
||||
)
|
||||
|
||||
|
||||
+80
@@ -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
|
||||
)
|
||||
+80
@@ -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"
|
||||
}
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user