[FIR] Add documentation to AbstractPredicate and FirPredicateBasedProvider

This commit is contained in:
Dmitriy Novozhilov
2022-11-25 15:46:13 +02:00
committed by Space Team
parent 6864433581
commit 8d2701209e
6 changed files with 170 additions and 169 deletions
@@ -44,6 +44,7 @@ class FirPredicateBasedProviderImpl(private val session: FirSession) : FirPredic
return file in cache.filesWithPluginAnnotations
}
@FirExtensionApiInternals
override fun registerAnnotatedDeclaration(declaration: FirDeclaration, owners: PersistentList<FirDeclaration>) {
cache.ownersForDeclaration[declaration] = owners
registerOwnersDeclarations(declaration, owners)
@@ -17,10 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirAnnotationResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
import org.jetbrains.kotlin.fir.extensions.markedWithMetaAnnotationImpl
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.extensions.registeredPluginAnnotations
import org.jetbrains.kotlin.fir.extensions.*
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.DesignationState
@@ -157,6 +154,7 @@ internal abstract class AbstractFirSpecificAnnotationResolveTransformer(
} as FirTypeAlias
}
@OptIn(FirExtensionApiInternals::class)
override fun transformDeclaration(declaration: FirDeclaration, data: Nothing?): FirDeclaration {
return (transformAnnotationContainer(declaration, data) as FirDeclaration).also {
predicateBasedProvider.registerAnnotatedDeclaration(declaration, owners)
@@ -12,33 +12,56 @@ import org.jetbrains.kotlin.fir.NoMutableState
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.extensions.predicate.AbstractPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
abstract class FirPredicateBasedProvider : FirSessionComponent {
/**
* @return list of all declarations from compiled source module which are matched to [predicate]
*/
abstract fun getSymbolsByPredicate(predicate: LookupPredicate): List<FirBasedSymbol<*>>
/**
* @return list of all parents of [declaration]
*/
abstract fun getOwnersOfDeclaration(declaration: FirDeclaration): List<FirBasedSymbol<*>>?
/**
* @return `true` iff file has a top-level annotation from the [FirRegisteredPluginAnnotations.annotations] list.
* @return `true` if file has a top-level annotation from the [FirRegisteredPluginAnnotations.annotations] list.
* @see FirRegisteredPluginAnnotations.annotations
*/
abstract fun fileHasPluginAnnotations(file: FirFile): Boolean
/**
* @return if [declaration] matches [predicate] or not
*/
abstract fun matches(predicate: AbstractPredicate<*>, declaration: FirDeclaration): Boolean
/**
* @return if [declaration] matches [predicate] or not
*/
fun matches(predicate: AbstractPredicate<*>, declaration: FirBasedSymbol<*>): Boolean {
return matches(predicate, declaration.fir)
}
/**
* @return if [declaration] matches any predicate from [predicates] or not
*/
fun matches(predicates: List<AbstractPredicate<*>>, declaration: FirDeclaration): Boolean {
return predicates.any { matches(it, declaration) }
}
/**
* @return if [declaration] matches any predicate from [predicates] or not
*/
fun matches(predicates: List<AbstractPredicate<*>>, declaration: FirBasedSymbol<*>): Boolean {
return matches(predicates, declaration.fir)
}
/**
* Utility method which should not be used from plugins
*/
@FirExtensionApiInternals
open fun registerAnnotatedDeclaration(declaration: FirDeclaration, owners: PersistentList<FirDeclaration>) {}
}
@@ -6,13 +6,31 @@
package org.jetbrains.kotlin.fir.extensions.predicate
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
/**
* Predicates are the mechanism for compiler plugins which allows to search for annotated declarations
* or check if some declaration matches some predicate or not.
* There are two different kinds of predicates: [LookupPredicate] and [DeclarationPredicate]
*
* [LookupPredicate] allows user to get all declarations in current module, which matches this predicate
* Both [LookupPredicate] and [DeclarationPredicate] allow user to check if some declaration matches the predicate
* The main component which can be used with predicate is [FirPredicateBasedProvider]
*
* The main difference between [LookupPredicate] and [DeclarationPredicate] is that [DeclarationPredicate] allows
* to create predicate with meta annotations, and [LookupPredicate] allows to use only annotations with predefined
* qualified names
*/
sealed interface AbstractPredicate<P : AbstractPredicate<P>> {
val annotations: Set<AnnotationFqn>
val metaAnnotations: Set<AnnotationFqn>
fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R
/**
* Boolean combinator OR for two predicates, matches declaration if
* [a] matches declaration or [b] matches declaration
*/
sealed interface Or<P : AbstractPredicate<P>> : AbstractPredicate<P> {
val a: P
val b: P
@@ -22,6 +40,10 @@ sealed interface AbstractPredicate<P : AbstractPredicate<P>> {
}
}
/**
* Boolean combinator AND for two predicates, matches declaration if
* [a] matches declaration and [b] matches declaration
*/
sealed interface And<P : AbstractPredicate<P>> : AbstractPredicate<P> {
val a: P
val b: P
@@ -33,31 +55,110 @@ sealed interface AbstractPredicate<P : AbstractPredicate<P>> {
// ------------------------------------ Annotated ------------------------------------
/**
* Base class for all predicates with specific annotations
* Declaration will be matched if at least one of [annotations] is found
*/
sealed interface Annotated<P : AbstractPredicate<P>> : AbstractPredicate<P> {
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
return visitor.visitAnnotated(this, data)
}
}
/**
* Matches declarations, which are annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Ann
* class A {
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun foo, parameter `param` from fun bar, class A]
*/
sealed interface AnnotatedWith<P : AbstractPredicate<P>> : Annotated<P> {
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
return visitor.visitAnnotatedWith(this, data)
}
}
/**
* Matches declaration, if one of its containers annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Ann
* class A {
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun A.baz, class Nested, fun Nested.foobar]
*/
sealed interface AncestorAnnotatedWith<P : AbstractPredicate<P>> : Annotated<P> {
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
return visitor.visitAncestorAnnotatedWith(this, data)
}
}
/**
* Matches declaration, if its direct container annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Ann
* class A {
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun A.baz, class Nested]
*/
sealed interface ParentAnnotatedWith<P : AbstractPredicate<P>> : Annotated<P> {
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
return visitor.visitParentAnnotatedWith(this, data)
}
}
/**
* Matches declaration, if one of its direct child declarations annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* class A {
* @Ann
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun bar, class A]
*/
sealed interface HasAnnotatedWith<P : AbstractPredicate<P>> : Annotated<P> {
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
return visitor.visitHasAnnotatedWith(this, data)
@@ -66,6 +167,38 @@ sealed interface AbstractPredicate<P : AbstractPredicate<P>> {
// ------------------------------------ MetaAnnotated ------------------------------------
/**
* Matches declarations, which are annotated with annotations which are annotated with [metaAnnotations]
* 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`
*
* @Ann
* annotation class Some
*
* @Some
* annotation class Other
*
*
* @Some
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Some
* class A {
* fun baz() {}
*
* class Nested {
* @Other
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun foo, class A, fun A.Nested.foobar]
*
* Note that [MetaAnnotatedWith] predicate has no implementation in [LookupPredicate] hierarchy
* and can not be used for global lookup
*/
sealed interface MetaAnnotatedWith<P : AbstractPredicate<P>> : AbstractPredicate<P> {
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
return visitor.visitMetaAnnotatedWith(this, data)
@@ -9,7 +9,10 @@ import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
// -------------------------------------------- Predicates --------------------------------------------
// todo: Missing KDOC
/**
* For reference read KDoc to [AbstractPredicate]
* @see [AbstractPredicate]
*/
sealed class DeclarationPredicate : AbstractPredicate<DeclarationPredicate> {
abstract override val annotations: Set<AnnotationFqn>
abstract override val metaAnnotations: Set<AnnotationFqn>
@@ -42,10 +45,6 @@ sealed class DeclarationPredicate : AbstractPredicate<DeclarationPredicate> {
// ------------------------------------ Annotated ------------------------------------
/**
* Base class for all predicates with specific annotations
* Declaration will be matched if at least one of [annotations] is found
*/
sealed class Annotated(final override val annotations: Set<AnnotationFqn>) : DeclarationPredicate(),
AbstractPredicate.Annotated<DeclarationPredicate> {
init {
@@ -62,50 +61,12 @@ sealed class DeclarationPredicate : AbstractPredicate<DeclarationPredicate> {
}
}
/**
* Matches declarations, which are annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Ann
* class A {
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun foo, parameter `param` from fun bar, class A]
*/
class AnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations), AbstractPredicate.AnnotatedWith<DeclarationPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R {
return visitor.visitAnnotatedWith(this, data)
}
}
/**
* Matches declaration, if one of its containers annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Ann
* class A {
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun A.baz, class Nested, fun Nested.foobar]
*/
class AncestorAnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations),
AbstractPredicate.AncestorAnnotatedWith<DeclarationPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R {
@@ -113,25 +74,6 @@ sealed class DeclarationPredicate : AbstractPredicate<DeclarationPredicate> {
}
}
/**
* Matches declaration, if its direct container annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Ann
* class A {
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun A.baz, class Nested]
*/
class ParentAnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations),
AbstractPredicate.ParentAnnotatedWith<DeclarationPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R {
@@ -139,26 +81,6 @@ sealed class DeclarationPredicate : AbstractPredicate<DeclarationPredicate> {
}
}
/**
* Matches declaration, if one of its direct child declarations annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* class A {
* @Ann
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun bar, class A]
*/
class HasAnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations),
AbstractPredicate.HasAnnotatedWith<DeclarationPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R {
@@ -7,6 +7,10 @@ package org.jetbrains.kotlin.fir.extensions.predicate
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
/**
* For reference read KDoc to [AbstractPredicate]
* @see [AbstractPredicate]
*/
sealed class LookupPredicate : AbstractPredicate<LookupPredicate> {
abstract override val annotations: Set<AnnotationFqn>
final override val metaAnnotations: Set<AnnotationFqn>
@@ -36,10 +40,6 @@ sealed class LookupPredicate : AbstractPredicate<LookupPredicate> {
}
}
/**
* Base class for all predicates with specific annotations
* Declaration will be matched if at least one of [annotations] is found
*/
sealed class Annotated(final override val annotations: Set<AnnotationFqn>) : LookupPredicate(), AbstractPredicate.Annotated<LookupPredicate> {
init {
require(annotations.isNotEmpty()) {
@@ -52,100 +52,24 @@ sealed class LookupPredicate : AbstractPredicate<LookupPredicate> {
}
}
/**
* Matches declarations, which are annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Ann
* class A {
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun foo, parameter `param` from fun bar, class A]
*/
class AnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations), AbstractPredicate.AnnotatedWith<LookupPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<LookupPredicate, R, D>, data: D): R {
return visitor.visitAnnotatedWith(this, data)
}
}
/**
* Matches declaration, if one of its containers annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Ann
* class A {
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun A.baz, class Nested, fun Nested.foobar]
*/
class AncestorAnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations), AbstractPredicate.AncestorAnnotatedWith<LookupPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<LookupPredicate, R, D>, data: D): R {
return visitor.visitAncestorAnnotatedWith(this, data)
}
}
/**
* Matches declaration, if its direct container annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* @Ann
* class A {
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun A.baz, class Nested]
*/
class ParentAnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations), AbstractPredicate.ParentAnnotatedWith<LookupPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<LookupPredicate, R, D>, data: D): R {
return visitor.visitParentAnnotatedWith(this, data)
}
}
/**
* Matches declaration, if one of its direct child declarations annotated with [annotations]
*
* @Ann
* fun foo() {}
*
* fun bar(@Ann param: Int) {}
*
* class A {
* @Ann
* fun baz() {}
*
* class Nested {
* fun foobar() {}
* }
* }
*
* Matched symbols: [fun bar, class A]
*/
class HasAnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations), AbstractPredicate.HasAnnotatedWith<LookupPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<LookupPredicate, R, D>, data: D): R {