[FIR] Add ability to specify if meta annotation itself should match metaAnnotated predicate
^KT-55843 Fixed
This commit is contained in:
committed by
Space Team
parent
e88a6af7a0
commit
4363b0815c
+1
-1
@@ -134,7 +134,7 @@ internal class LLFirIdePredicateBasedProvider(
|
|||||||
|
|
||||||
override fun visitMetaAnnotatedWith(predicate: AbstractPredicate.MetaAnnotatedWith<P>, data: FirDeclaration): Boolean {
|
override fun visitMetaAnnotatedWith(predicate: AbstractPredicate.MetaAnnotatedWith<P>, data: FirDeclaration): Boolean {
|
||||||
return data.annotations.any { annotation ->
|
return data.annotations.any { annotation ->
|
||||||
annotation.markedWithMetaAnnotation(session, data, predicate.metaAnnotations)
|
annotation.markedWithMetaAnnotation(session, data, predicate.metaAnnotations, predicate.includeItself)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -140,7 +140,7 @@ class FirPredicateBasedProviderImpl(private val session: FirSession) : FirPredic
|
|||||||
|
|
||||||
override fun visitMetaAnnotatedWith(predicate: AbstractPredicate.MetaAnnotatedWith<P>, data: FirDeclaration): Boolean {
|
override fun visitMetaAnnotatedWith(predicate: AbstractPredicate.MetaAnnotatedWith<P>, data: FirDeclaration): Boolean {
|
||||||
return data.annotations.any { annotation ->
|
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(
|
fun FirAnnotation.markedWithMetaAnnotation(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
containingDeclaration: FirDeclaration,
|
containingDeclaration: FirDeclaration,
|
||||||
metaAnnotations: Set<AnnotationFqn>
|
metaAnnotations: Set<AnnotationFqn>,
|
||||||
|
includeItself: Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
containingDeclaration.symbol.lazyResolveToPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
|
containingDeclaration.symbol.lazyResolveToPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
|
||||||
return annotationTypeRef.coneTypeSafe<ConeKotlinType>()
|
return annotationTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||||
?.toRegularClassSymbol(session)
|
?.toRegularClassSymbol(session)
|
||||||
.markedWithMetaAnnotationImpl(session, metaAnnotations, mutableSetOf())
|
.markedWithMetaAnnotationImpl(session, metaAnnotations, includeItself, mutableSetOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FirRegularClassSymbol?.markedWithMetaAnnotationImpl(
|
fun FirRegularClassSymbol?.markedWithMetaAnnotationImpl(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
metaAnnotations: Set<AnnotationFqn>,
|
metaAnnotations: Set<AnnotationFqn>,
|
||||||
|
includeItself: Boolean,
|
||||||
visited: MutableSet<FirRegularClassSymbol>
|
visited: MutableSet<FirRegularClassSymbol>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (this == null) return false
|
if (this == null) return false
|
||||||
if (!visited.add(this)) 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
|
return this.resolvedCompilerAnnotationsWithClassIds
|
||||||
.mapNotNull { it.annotationTypeRef.coneTypeSafe<ConeKotlinType>()?.toRegularClassSymbol(session) }
|
.mapNotNull { it.annotationTypeRef.coneTypeSafe<ConeKotlinType>()?.toRegularClassSymbol(session) }
|
||||||
.any { it.markedWithMetaAnnotationImpl(session, metaAnnotations, visited) }
|
.any { it.markedWithMetaAnnotationImpl(session, metaAnnotations, includeItself = true, visited) }
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ internal abstract class AbstractFirSpecificAnnotationResolveTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun ConeKotlinType.markedWithMetaAnnotation(session: FirSession, metaAnnotations: Set<AnnotationFqn>): Boolean {
|
private fun ConeKotlinType.markedWithMetaAnnotation(session: FirSession, metaAnnotations: Set<AnnotationFqn>): Boolean {
|
||||||
return toRegularClassSymbol(session).markedWithMetaAnnotationImpl(session, metaAnnotations, mutableSetOf())
|
return toRegularClassSymbol(session).markedWithMetaAnnotationImpl(session, metaAnnotations, includeItself = true, mutableSetOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -169,8 +169,13 @@ sealed interface AbstractPredicate<P : AbstractPredicate<P>> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches declarations, which are annotated with annotations which are annotated with [metaAnnotations]
|
* 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
|
* 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
|
* @Ann
|
||||||
* annotation class Some
|
* annotation class Some
|
||||||
@@ -200,6 +205,8 @@ sealed interface AbstractPredicate<P : AbstractPredicate<P>> {
|
|||||||
* and can not be used for global lookup
|
* and can not be used for global lookup
|
||||||
*/
|
*/
|
||||||
sealed interface MetaAnnotatedWith<P : AbstractPredicate<P>> : AbstractPredicate<P> {
|
sealed interface MetaAnnotatedWith<P : AbstractPredicate<P>> : AbstractPredicate<P> {
|
||||||
|
val includeItself: Boolean
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
|
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
|
||||||
return visitor.visitMetaAnnotatedWith(this, data)
|
return visitor.visitMetaAnnotatedWith(this, data)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -91,7 +91,8 @@ sealed class DeclarationPredicate : AbstractPredicate<DeclarationPredicate> {
|
|||||||
// ------------------------------------ MetaAnnotated ------------------------------------
|
// ------------------------------------ MetaAnnotated ------------------------------------
|
||||||
|
|
||||||
class MetaAnnotatedWith(
|
class MetaAnnotatedWith(
|
||||||
override val metaAnnotations: Set<AnnotationFqn>
|
override val metaAnnotations: Set<AnnotationFqn>,
|
||||||
|
override val includeItself: Boolean
|
||||||
) : DeclarationPredicate(), AbstractPredicate.MetaAnnotatedWith<DeclarationPredicate> {
|
) : DeclarationPredicate(), AbstractPredicate.MetaAnnotatedWith<DeclarationPredicate> {
|
||||||
init {
|
init {
|
||||||
require(metaAnnotations.isNotEmpty()) {
|
require(metaAnnotations.isNotEmpty()) {
|
||||||
@@ -122,7 +123,8 @@ sealed class DeclarationPredicate : AbstractPredicate<DeclarationPredicate> {
|
|||||||
override fun annotatedOrUnder(vararg annotations: AnnotationFqn): DeclarationPredicate =
|
override fun annotatedOrUnder(vararg annotations: AnnotationFqn): DeclarationPredicate =
|
||||||
annotated(*annotations) or ancestorAnnotated(*annotations)
|
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 -------------------
|
// ------------------- collections -------------------
|
||||||
override fun annotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate = AnnotatedWith(annotations.toSet())
|
override fun annotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate = AnnotatedWith(annotations.toSet())
|
||||||
@@ -137,7 +139,8 @@ sealed class DeclarationPredicate : AbstractPredicate<DeclarationPredicate> {
|
|||||||
override fun annotatedOrUnder(annotations: Collection<AnnotationFqn>): DeclarationPredicate =
|
override fun annotatedOrUnder(annotations: Collection<AnnotationFqn>): DeclarationPredicate =
|
||||||
annotated(annotations) or ancestorAnnotated(annotations)
|
annotated(annotations) or ancestorAnnotated(annotations)
|
||||||
|
|
||||||
fun metaAnnotated(metaAnnotations: Collection<AnnotationFqn>): DeclarationPredicate = MetaAnnotatedWith(metaAnnotations.toSet())
|
fun metaAnnotated(metaAnnotations: Collection<AnnotationFqn>, includeItself: Boolean): DeclarationPredicate =
|
||||||
|
MetaAnnotatedWith(metaAnnotations.toSet(), includeItself)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ class FirAllOpenPredicateMatcher(
|
|||||||
|
|
||||||
override val predicate = DeclarationPredicate.create {
|
override val predicate = DeclarationPredicate.create {
|
||||||
val annotationFqNames = allOpenAnnotationFqNames.map { FqName(it) }
|
val annotationFqNames = allOpenAnnotationFqNames.map { FqName(it) }
|
||||||
annotated(annotationFqNames) or metaAnnotated(annotationFqNames)
|
annotated(annotationFqNames) or metaAnnotated(annotationFqNames, includeItself = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ class AllOpenStatusTransformer(session: FirSession) : FirStatusTransformerExtens
|
|||||||
companion object {
|
companion object {
|
||||||
private val ALL_OPEN = FqName("org.jetbrains.kotlin.fir.plugin.AllOpen")
|
private val ALL_OPEN = FqName("org.jetbrains.kotlin.fir.plugin.AllOpen")
|
||||||
private val PREDICATE = DeclarationPredicate.create {
|
private val PREDICATE = DeclarationPredicate.create {
|
||||||
annotatedOrUnder(ALL_OPEN) or metaAnnotated(ALL_OPEN)
|
annotatedOrUnder(ALL_OPEN) or metaAnnotated(ALL_OPEN, includeItself = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ class SomeAdditionalSupertypeGenerator(session: FirSession) : FirSupertypeGenera
|
|||||||
companion object {
|
companion object {
|
||||||
private val myInterfaceClassId = ClassId(FqName("foo"), Name.identifier("MyInterface"))
|
private val myInterfaceClassId = ClassId(FqName("foo"), Name.identifier("MyInterface"))
|
||||||
private val PREDICATE = DeclarationPredicate.create {
|
private val PREDICATE = DeclarationPredicate.create {
|
||||||
annotated("MyInterfaceSupertype".fqn()) or metaAnnotated("MetaSupertype".fqn())
|
annotated("MyInterfaceSupertype".fqn()) or metaAnnotated("MetaSupertype".fqn(), includeItself = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -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| {
|
public constructor(): R|foo/Zero| {
|
||||||
super<R|kotlin/Any|>()
|
super<R|kotlin/Any|>()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public final fun test(a: R|foo/Zero|, b: R|foo/First|, c: R|foo/Second|, d: R|foo/Third|): R|kotlin/Unit| {
|
public final fun test(a: R|foo/Zero|, b: R|foo/First|, c: R|foo/Second|, d: R|foo/Third|): R|kotlin/Unit| {
|
||||||
R|<local>/a|.R|foo/MyInterface.foo|()
|
R|<local>/a|.<Unresolved name: foo>#()
|
||||||
R|<local>/b|.R|foo/MyInterface.foo|()
|
R|<local>/b|.R|foo/MyInterface.foo|()
|
||||||
R|<local>/c|.R|foo/MyInterface.foo|()
|
R|<local>/c|.R|foo/MyInterface.foo|()
|
||||||
R|<local>/d|.R|foo/MyInterface.foo|()
|
R|<local>/d|.R|foo/MyInterface.foo|()
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ class First
|
|||||||
class Zero
|
class Zero
|
||||||
|
|
||||||
fun test(a: Zero, b: First, c: Second, d: Third) {
|
fun test(a: Zero, b: First, c: Second, d: Third) {
|
||||||
a.foo()
|
a.<!UNRESOLVED_REFERENCE!>foo<!>() // should be an error, because meta predicate has inludeItself = false
|
||||||
b.foo()
|
b.foo()
|
||||||
c.foo()
|
c.foo()
|
||||||
d.foo()
|
d.foo()
|
||||||
|
|||||||
+3
-2
@@ -13,9 +13,10 @@ object FirSerializationPredicates {
|
|||||||
annotated(setOf(SerializationAnnotations.serializerAnnotationFqName)) // @Serializer(for=...)
|
annotated(setOf(SerializationAnnotations.serializerAnnotationFqName)) // @Serializer(for=...)
|
||||||
}
|
}
|
||||||
internal val hasMetaAnnotation = DeclarationPredicate.create {
|
internal val hasMetaAnnotation = DeclarationPredicate.create {
|
||||||
metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName)
|
metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName, includeItself = false)
|
||||||
}
|
}
|
||||||
internal val annotatedWithSerializableOrMeta = DeclarationPredicate.create {
|
internal val annotatedWithSerializableOrMeta = DeclarationPredicate.create {
|
||||||
annotated(setOf(SerializationAnnotations.serializableAnnotationFqName)) or metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName)
|
annotated(setOf(SerializationAnnotations.serializableAnnotationFqName)) or
|
||||||
|
metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName, includeItself = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ class FirNoArgPredicateMatcher(
|
|||||||
|
|
||||||
override val predicate = DeclarationPredicate.create {
|
override val predicate = DeclarationPredicate.create {
|
||||||
val annotationFqNames = noArgAnnotationFqNames.map { FqName(it) }
|
val annotationFqNames = noArgAnnotationFqNames.map { FqName(it) }
|
||||||
annotated(annotationFqNames) or metaAnnotated(annotationFqNames)
|
annotated(annotationFqNames) or metaAnnotated(annotationFqNames, includeItself = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user