From 4363b0815cb6194fba5cf4d30c7a426afdaf7dd9 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 11 Jan 2023 11:32:44 +0200 Subject: [PATCH] [FIR] Add ability to specify if meta annotation itself should match metaAnnotated predicate ^KT-55843 Fixed --- .../fir/providers/LLFirIdePredicateBasedProvider.kt | 2 +- .../fir/extensions/FirPredicateBasedProviderImpl.kt | 12 +++++++----- ...bstractFirSpecificAnnotationResolveTransformer.kt | 2 +- .../fir/extensions/predicate/AbstractPredicate.kt | 9 ++++++++- .../fir/extensions/predicate/DeclarationPredicate.kt | 9 ++++++--- .../allopen/fir/FirAllOpenStatusTransformer.kt | 2 +- .../kotlin/fir/plugin/AllOpenStatusTransformer.kt | 2 +- .../fir/plugin/SomeAdditionalSupertypeGenerator.kt | 2 +- .../supertypes/metaAnnotationOrder.fir.txt | 4 ++-- .../diagnostics/supertypes/metaAnnotationOrder.kt | 2 +- .../compiler/fir/FirSerializationPredicates.kt | 5 +++-- .../kotlin/noarg/fir/NoArgAnnotationNameProvider.kt | 2 +- 12 files changed, 33 insertions(+), 20 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirIdePredicateBasedProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirIdePredicateBasedProvider.kt index e48a0ffbc2e..8df0ed22446 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirIdePredicateBasedProvider.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirIdePredicateBasedProvider.kt @@ -134,7 +134,7 @@ internal class LLFirIdePredicateBasedProvider( override fun visitMetaAnnotatedWith(predicate: AbstractPredicate.MetaAnnotatedWith

, data: FirDeclaration): Boolean { return data.annotations.any { annotation -> - annotation.markedWithMetaAnnotation(session, data, predicate.metaAnnotations) + annotation.markedWithMetaAnnotation(session, data, predicate.metaAnnotations, predicate.includeItself) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirPredicateBasedProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirPredicateBasedProviderImpl.kt index 3e416d6c030..9d950b2aa03 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirPredicateBasedProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirPredicateBasedProviderImpl.kt @@ -140,7 +140,7 @@ class FirPredicateBasedProviderImpl(private val session: FirSession) : FirPredic override fun visitMetaAnnotatedWith(predicate: AbstractPredicate.MetaAnnotatedWith

, data: FirDeclaration): Boolean { return data.annotations.any { annotation -> - annotation.markedWithMetaAnnotation(session, data, predicate.metaAnnotations) + annotation.markedWithMetaAnnotation(session, data, predicate.metaAnnotations, predicate.includeItself) } } @@ -190,23 +190,25 @@ class FirPredicateBasedProviderImpl(private val session: FirSession) : FirPredic fun FirAnnotation.markedWithMetaAnnotation( session: FirSession, containingDeclaration: FirDeclaration, - metaAnnotations: Set + metaAnnotations: Set, + includeItself: Boolean ): Boolean { containingDeclaration.symbol.lazyResolveToPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) return annotationTypeRef.coneTypeSafe() ?.toRegularClassSymbol(session) - .markedWithMetaAnnotationImpl(session, metaAnnotations, mutableSetOf()) + .markedWithMetaAnnotationImpl(session, metaAnnotations, includeItself, mutableSetOf()) } fun FirRegularClassSymbol?.markedWithMetaAnnotationImpl( session: FirSession, metaAnnotations: Set, + includeItself: Boolean, visited: MutableSet ): Boolean { if (this == null) return false if (!visited.add(this)) return false - if (this.classId.asSingleFqName() in metaAnnotations) return true + if (this.classId.asSingleFqName() in metaAnnotations) return includeItself return this.resolvedCompilerAnnotationsWithClassIds .mapNotNull { it.annotationTypeRef.coneTypeSafe()?.toRegularClassSymbol(session) } - .any { it.markedWithMetaAnnotationImpl(session, metaAnnotations, visited) } + .any { it.markedWithMetaAnnotationImpl(session, metaAnnotations, includeItself = true, visited) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/AbstractFirSpecificAnnotationResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/AbstractFirSpecificAnnotationResolveTransformer.kt index 1eb21973c3e..be3a44214c6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/AbstractFirSpecificAnnotationResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/AbstractFirSpecificAnnotationResolveTransformer.kt @@ -144,7 +144,7 @@ internal abstract class AbstractFirSpecificAnnotationResolveTransformer( } private fun ConeKotlinType.markedWithMetaAnnotation(session: FirSession, metaAnnotations: Set): Boolean { - return toRegularClassSymbol(session).markedWithMetaAnnotationImpl(session, metaAnnotations, mutableSetOf()) + return toRegularClassSymbol(session).markedWithMetaAnnotationImpl(session, metaAnnotations, includeItself = true, mutableSetOf()) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/extensions/predicate/AbstractPredicate.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/extensions/predicate/AbstractPredicate.kt index add10e3d263..42f03eae325 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/extensions/predicate/AbstractPredicate.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/extensions/predicate/AbstractPredicate.kt @@ -169,8 +169,13 @@ sealed interface AbstractPredicate

> { /** * Matches declarations, which are annotated with annotations which are annotated with [metaAnnotations] + * + * [includeItself] flag determines if declaration, annotated with meta-annotation itself will + * be considered as matching to predicate + * * Relation "annotation with meta annotation" is transitive. E.g. in snippet below some declaration will - * be matched with predicate MetaAnnotatedWith("Ann") if it is annotated with `@Ann`, `@Some` or `@Other` + * be matched with predicate MetaAnnotatedWith("Ann") if it is annotated with `@Ann` (if [includeItself] set to true), + * `@Some` or `@Other` * * @Ann * annotation class Some @@ -200,6 +205,8 @@ sealed interface AbstractPredicate

> { * and can not be used for global lookup */ sealed interface MetaAnnotatedWith

> : AbstractPredicate

{ + val includeItself: Boolean + override fun accept(visitor: PredicateVisitor, data: D): R { return visitor.visitMetaAnnotatedWith(this, data) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicate.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicate.kt index 5871e39492f..1daaa8d3cef 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicate.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/extensions/predicate/DeclarationPredicate.kt @@ -91,7 +91,8 @@ sealed class DeclarationPredicate : AbstractPredicate { // ------------------------------------ MetaAnnotated ------------------------------------ class MetaAnnotatedWith( - override val metaAnnotations: Set + override val metaAnnotations: Set, + override val includeItself: Boolean ) : DeclarationPredicate(), AbstractPredicate.MetaAnnotatedWith { init { require(metaAnnotations.isNotEmpty()) { @@ -122,7 +123,8 @@ sealed class DeclarationPredicate : AbstractPredicate { override fun annotatedOrUnder(vararg annotations: AnnotationFqn): DeclarationPredicate = annotated(*annotations) or ancestorAnnotated(*annotations) - fun metaAnnotated(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = MetaAnnotatedWith(metaAnnotations.toSet()) + fun metaAnnotated(vararg metaAnnotations: AnnotationFqn, includeItself: Boolean): DeclarationPredicate = + MetaAnnotatedWith(metaAnnotations.toSet(), includeItself) // ------------------- collections ------------------- override fun annotated(annotations: Collection): DeclarationPredicate = AnnotatedWith(annotations.toSet()) @@ -137,7 +139,8 @@ sealed class DeclarationPredicate : AbstractPredicate { override fun annotatedOrUnder(annotations: Collection): DeclarationPredicate = annotated(annotations) or ancestorAnnotated(annotations) - fun metaAnnotated(metaAnnotations: Collection): DeclarationPredicate = MetaAnnotatedWith(metaAnnotations.toSet()) + fun metaAnnotated(metaAnnotations: Collection, includeItself: Boolean): DeclarationPredicate = + MetaAnnotatedWith(metaAnnotations.toSet(), includeItself) } companion object { diff --git a/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenStatusTransformer.kt b/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenStatusTransformer.kt index f5202413630..c90e8151ffe 100644 --- a/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenStatusTransformer.kt +++ b/plugins/allopen/allopen.k2/src/org/jetbrains/kotlin/allopen/fir/FirAllOpenStatusTransformer.kt @@ -57,7 +57,7 @@ class FirAllOpenPredicateMatcher( override val predicate = DeclarationPredicate.create { val annotationFqNames = allOpenAnnotationFqNames.map { FqName(it) } - annotated(annotationFqNames) or metaAnnotated(annotationFqNames) + annotated(annotationFqNames) or metaAnnotated(annotationFqNames, includeItself = true) } } diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenStatusTransformer.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenStatusTransformer.kt index a2fd9e4e809..8fc0cc13817 100644 --- a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenStatusTransformer.kt +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenStatusTransformer.kt @@ -20,7 +20,7 @@ class AllOpenStatusTransformer(session: FirSession) : FirStatusTransformerExtens companion object { private val ALL_OPEN = FqName("org.jetbrains.kotlin.fir.plugin.AllOpen") private val PREDICATE = DeclarationPredicate.create { - annotatedOrUnder(ALL_OPEN) or metaAnnotated(ALL_OPEN) + annotatedOrUnder(ALL_OPEN) or metaAnnotated(ALL_OPEN, includeItself = true) } } diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/SomeAdditionalSupertypeGenerator.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/SomeAdditionalSupertypeGenerator.kt index a65130bcb27..77809189c16 100644 --- a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/SomeAdditionalSupertypeGenerator.kt +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/SomeAdditionalSupertypeGenerator.kt @@ -31,7 +31,7 @@ class SomeAdditionalSupertypeGenerator(session: FirSession) : FirSupertypeGenera companion object { private val myInterfaceClassId = ClassId(FqName("foo"), Name.identifier("MyInterface")) private val PREDICATE = DeclarationPredicate.create { - annotated("MyInterfaceSupertype".fqn()) or metaAnnotated("MetaSupertype".fqn()) + annotated("MyInterfaceSupertype".fqn()) or metaAnnotated("MetaSupertype".fqn(), includeItself = false) } } diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/supertypes/metaAnnotationOrder.fir.txt b/plugins/fir-plugin-prototype/testData/diagnostics/supertypes/metaAnnotationOrder.fir.txt index 83946e67168..ae8417f85f4 100644 --- a/plugins/fir-plugin-prototype/testData/diagnostics/supertypes/metaAnnotationOrder.fir.txt +++ b/plugins/fir-plugin-prototype/testData/diagnostics/supertypes/metaAnnotationOrder.fir.txt @@ -24,14 +24,14 @@ FILE: main.kt } } - @R|org/jetbrains/kotlin/fir/plugin/MetaSupertype|() public final class Zero : R|kotlin/Any|, R|foo/MyInterface| { + @R|org/jetbrains/kotlin/fir/plugin/MetaSupertype|() public final class Zero : R|kotlin/Any| { public constructor(): R|foo/Zero| { super() } } public final fun test(a: R|foo/Zero|, b: R|foo/First|, c: R|foo/Second|, d: R|foo/Third|): R|kotlin/Unit| { - R|/a|.R|foo/MyInterface.foo|() + R|/a|.#() R|/b|.R|foo/MyInterface.foo|() R|/c|.R|foo/MyInterface.foo|() R|/d|.R|foo/MyInterface.foo|() diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/supertypes/metaAnnotationOrder.kt b/plugins/fir-plugin-prototype/testData/diagnostics/supertypes/metaAnnotationOrder.kt index a243326eaf8..f6ade31946d 100644 --- a/plugins/fir-plugin-prototype/testData/diagnostics/supertypes/metaAnnotationOrder.kt +++ b/plugins/fir-plugin-prototype/testData/diagnostics/supertypes/metaAnnotationOrder.kt @@ -21,7 +21,7 @@ class First class Zero fun test(a: Zero, b: First, c: Second, d: Third) { - a.foo() + a.foo() // should be an error, because meta predicate has inludeItself = false b.foo() c.foo() d.foo() diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/FirSerializationPredicates.kt b/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/FirSerializationPredicates.kt index 12472398125..08742b84d13 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/FirSerializationPredicates.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/FirSerializationPredicates.kt @@ -13,9 +13,10 @@ object FirSerializationPredicates { annotated(setOf(SerializationAnnotations.serializerAnnotationFqName)) // @Serializer(for=...) } internal val hasMetaAnnotation = DeclarationPredicate.create { - metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName) + metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName, includeItself = false) } internal val annotatedWithSerializableOrMeta = DeclarationPredicate.create { - annotated(setOf(SerializationAnnotations.serializableAnnotationFqName)) or metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName) + annotated(setOf(SerializationAnnotations.serializableAnnotationFqName)) or + metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName, includeItself = false) } } diff --git a/plugins/noarg/noarg.k2/src/org/jetbrains/kotlin/noarg/fir/NoArgAnnotationNameProvider.kt b/plugins/noarg/noarg.k2/src/org/jetbrains/kotlin/noarg/fir/NoArgAnnotationNameProvider.kt index dc8c3375115..28d0e78dbf8 100644 --- a/plugins/noarg/noarg.k2/src/org/jetbrains/kotlin/noarg/fir/NoArgAnnotationNameProvider.kt +++ b/plugins/noarg/noarg.k2/src/org/jetbrains/kotlin/noarg/fir/NoArgAnnotationNameProvider.kt @@ -22,7 +22,7 @@ class FirNoArgPredicateMatcher( override val predicate = DeclarationPredicate.create { val annotationFqNames = noArgAnnotationFqNames.map { FqName(it) } - annotated(annotationFqNames) or metaAnnotated(annotationFqNames) + annotated(annotationFqNames) or metaAnnotated(annotationFqNames, includeItself = true) } }