[FIR] Add documentation to AbstractPredicate and FirPredicateBasedProvider
This commit is contained in:
committed by
Space Team
parent
6864433581
commit
8d2701209e
+1
@@ -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)
|
||||
|
||||
+2
-4
@@ -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)
|
||||
|
||||
+25
-2
@@ -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>) {}
|
||||
}
|
||||
|
||||
|
||||
+134
-1
@@ -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)
|
||||
|
||||
+4
-82
@@ -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 {
|
||||
|
||||
+4
-80
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user