[FIR] Rework predicates system

Now predicates are split into LookupPredicate and DeclarationPredicate
  hierarchies. First one allows to perform global search for declarations
  and second one allows to check if some declaration matches the predicate.
Predicates with meta annotations are excluded from LookupPredicates,
  because it's impossible to create index of annotations with meta-annotations,
  because they can be located inside binary dependencies (so to achieve
  this we need to scan the whole classpath).
Also only one predicate with meta-annotations is left in DeclarationPredicate
  hierarchy (AnnotatedWithMeta)

^KT-53874 Fixed
^KT-53590 Fixed
This commit is contained in:
Dmitriy Novozhilov
2022-11-23 15:16:44 +02:00
committed by Space Team
parent 7a9a71a089
commit 246dc985a6
41 changed files with 934 additions and 605 deletions
@@ -95,7 +95,7 @@ internal class LLFirNonUnderContentRootSessionFactory(private val project: Proje
)
)
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider())
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
register(FirDependenciesSymbolProvider::class, dependencyProvider)
register(FirDependenciesSymbolProvider::class, dependencyProvider)
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getContainingFile
import org.jetbrains.kotlin.analysis.providers.KotlinAnnotationsResolver
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.caches.FirCache
import org.jetbrains.kotlin.fir.caches.createCache
import org.jetbrains.kotlin.fir.caches.firCachesFactory
@@ -23,15 +22,20 @@ import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations
import org.jetbrains.kotlin.fir.extensions.predicate.*
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.extensions.predicate.PredicateVisitor
import org.jetbrains.kotlin.fir.extensions.registeredPluginAnnotations
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.resolve.getCorrespondingClassSymbolOrNull
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitorVoid
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.ClassId
@@ -52,8 +56,8 @@ internal class LLFirIdePredicateBasedProvider(
private val declarationOwnersCache: FirCache<FirFile, FirOwnersStorage, Nothing?> =
session.firCachesFactory.createCache { firFile -> FirOwnersStorage.collectOwners(firFile) }
override fun getSymbolsByPredicate(predicate: DeclarationPredicate): List<FirBasedSymbol<*>> {
val annotations = registeredPluginAnnotations.getAnnotationsForPredicate(predicate)
override fun getSymbolsByPredicate(predicate: LookupPredicate): List<FirBasedSymbol<*>> {
val annotations = predicate.annotations
val annotatedDeclarations = annotations
.asSequence()
.flatMap { annotationsResolver.declarationsByAnnotation(ClassId.topLevel(it)) }
@@ -99,80 +103,83 @@ internal class LLFirIdePredicateBasedProvider(
}
}
override fun matches(predicate: DeclarationPredicate, declaration: FirDeclaration): Boolean {
return predicate.accept(matcher, declaration)
override fun matches(predicate: AbstractPredicate<*>, declaration: FirDeclaration): Boolean {
return when (predicate) {
is DeclarationPredicate -> predicate.accept(declarationPredicateMatcher, declaration)
is LookupPredicate -> predicate.accept(lookupPredicateMatcher, declaration)
}
}
private val matcher: Matcher = Matcher()
private val declarationPredicateMatcher = Matcher<DeclarationPredicate>()
private val lookupPredicateMatcher = Matcher<LookupPredicate>()
private inner class Matcher : DeclarationPredicateVisitor<Boolean, FirDeclaration>() {
override fun visitPredicate(predicate: DeclarationPredicate, data: FirDeclaration): Boolean {
error("When overrides for all possible DeclarationPredicate subtypes are implemented, " +
"this method should never be called, but it was called with $predicate")
private inner class Matcher<P : AbstractPredicate<P>> : PredicateVisitor<P, Boolean, FirDeclaration>() {
override fun visitPredicate(predicate: AbstractPredicate<P>, data: FirDeclaration): Boolean {
error(
"When overrides for all possible DeclarationPredicate subtypes are implemented, " +
"this method should never be called, but it was called with $predicate"
)
}
override fun visitAnd(predicate: DeclarationPredicate.And, data: FirDeclaration): Boolean {
override fun visitAnd(predicate: AbstractPredicate.And<P>, data: FirDeclaration): Boolean {
return predicate.a.accept(this, data) && predicate.b.accept(this, data)
}
override fun visitOr(predicate: DeclarationPredicate.Or, data: FirDeclaration): Boolean {
override fun visitOr(predicate: AbstractPredicate.Or<P>, data: FirDeclaration): Boolean {
return predicate.a.accept(this, data) || predicate.b.accept(this, data)
}
override fun visitAnnotatedWith(predicate: AnnotatedWith, data: FirDeclaration): Boolean {
override fun visitAnnotatedWith(predicate: AbstractPredicate.AnnotatedWith<P>, data: FirDeclaration): Boolean {
return annotationsOnDeclaration(data).any { it in predicate.annotations }
}
override fun visitAncestorAnnotatedWith(predicate: AncestorAnnotatedWith, data: FirDeclaration): Boolean {
override fun visitAncestorAnnotatedWith(predicate: AbstractPredicate.AncestorAnnotatedWith<P>, data: FirDeclaration): Boolean {
return annotationsOnOuterDeclarations(data).any { it in predicate.annotations }
}
override fun visitMetaAnnotatedWith(predicate: MetaAnnotatedWith, data: FirDeclaration): Boolean {
return metaAnnotationsOnDeclaration(data).any { it in predicate.metaAnnotations }
override fun visitMetaAnnotatedWith(predicate: AbstractPredicate.MetaAnnotatedWith<P>, data: FirDeclaration): Boolean {
val visited = mutableSetOf<FirRegularClassSymbol>()
return data.annotations.any { annotation ->
annotation.markedWithMetaAnnotation(predicate.metaAnnotations, visited)
}
}
override fun visitAncestorMetaAnnotatedWith(predicate: AncestorMetaAnnotatedWith, data: FirDeclaration): Boolean {
return metaAnnotationsOnOuterDeclarations(data).any { it in predicate.metaAnnotations }
private fun FirAnnotation.markedWithMetaAnnotation(
metaAnnotations: Set<AnnotationFqn>,
visited: MutableSet<FirRegularClassSymbol>
): Boolean {
val symbol = this.getCorrespondingClassSymbolOrNull(session) ?: return false
if (!visited.add(symbol)) return false
if (symbol.classId.asSingleFqName() in metaAnnotations) return true
if (symbol.resolvedAnnotationsWithClassIds.any { it.markedWithMetaAnnotation(metaAnnotations, visited) }) return true
return false
}
override fun visitParentAnnotatedWith(predicate: ParentAnnotatedWith, data: FirDeclaration): Boolean {
override fun visitParentAnnotatedWith(predicate: AbstractPredicate.ParentAnnotatedWith<P>, data: FirDeclaration): Boolean {
val parent = data.directParentDeclaration ?: return false
val parentPredicate = AnnotatedWith(predicate.annotations)
val parentPredicate = DeclarationPredicate.AnnotatedWith(predicate.annotations)
return parentPredicate.accept(this, parent)
return parentPredicate.accept(declarationPredicateMatcher, parent)
}
override fun visitHasAnnotatedWith(predicate: HasAnnotatedWith, data: FirDeclaration): Boolean {
val childPredicate = AnnotatedWith(predicate.annotations)
return data.anyDirectChildDeclarationMatches(childPredicate)
}
override fun visitParentMetaAnnotatedWith(predicate: ParentMetaAnnotatedWith, data: FirDeclaration): Boolean {
val parent = data.directParentDeclaration ?: return false
val parentPredicate = MetaAnnotatedWith(predicate.annotations)
return parentPredicate.accept(this, parent)
}
override fun visitHasMetaAnnotatedWith(predicate: HasMetaAnnotatedWith, data: FirDeclaration): Boolean {
val childPredicate = MetaAnnotatedWith(predicate.annotations)
override fun visitHasAnnotatedWith(predicate: AbstractPredicate.HasAnnotatedWith<P>, data: FirDeclaration): Boolean {
val childPredicate = DeclarationPredicate.AnnotatedWith(predicate.annotations)
return data.anyDirectChildDeclarationMatches(childPredicate)
}
private val FirDeclaration.directParentDeclaration: FirDeclaration?
get() = getOwnersOfDeclaration(this)?.lastOrNull()?.fir
}
private fun FirDeclaration.anyDirectChildDeclarationMatches(childPredicate: DeclarationPredicate): Boolean {
var result = false
private fun FirDeclaration.anyDirectChildDeclarationMatches(childPredicate: DeclarationPredicate): Boolean {
var result = false
this.forEachDirectChildDeclaration {
result = result || childPredicate.accept(this@Matcher, it)
}
return result
this.forEachDirectChildDeclaration {
result = result || childPredicate.accept(declarationPredicateMatcher, it)
}
return result
}
private fun annotationsOnDeclaration(declaration: FirDeclaration): Set<AnnotationFqn> {
@@ -193,24 +200,9 @@ internal class LLFirIdePredicateBasedProvider(
return psiAnnotations.map { it.asSingleFqName() }.toSet()
}
private fun metaAnnotationsOnDeclaration(declaration: FirDeclaration): Set<AnnotationFqn> {
val directAnnotations = annotationsOnDeclaration(declaration)
val metaAnnotations = directAnnotations
.asSequence()
.mapNotNull { declarationProvider.getAllClassesByClassId(ClassId.topLevel(it)).singleOrNull() }
.flatMap { annotationsResolver.annotationsOnDeclaration(it) }
.toSet()
return metaAnnotations.map { it.asSingleFqName() }.toSet()
}
private fun annotationsOnOuterDeclarations(declaration: FirDeclaration): Set<AnnotationFqn> {
return getOwnersOfDeclaration(declaration)?.flatMap { annotationsOnDeclaration(it.fir) }.orEmpty().toSet()
}
private fun metaAnnotationsOnOuterDeclarations(declaration: FirDeclaration): Set<AnnotationFqn> {
return getOwnersOfDeclaration(declaration)?.flatMap { metaAnnotationsOnDeclaration(it.fir) }.orEmpty().toSet()
}
}
private class FirOwnersStorage(private val declarationToOwner: Map<FirDeclaration, List<FirBasedSymbol<*>>>) {
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
import org.jetbrains.kotlin.analysis.providers.KotlinAnnotationsResolver
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.caches.*
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.extensions.AbstractFirRegisteredPluginAnnotations
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
import org.jetbrains.kotlin.name.ClassId
@@ -26,25 +25,14 @@ internal class LLFirIdeRegisteredPluginAnnotations(
get() = allAnnotationsCache.getValue()
private val allAnnotationsCache: FirLazyValue<Set<AnnotationFqn>, Nothing?> = session.firCachesFactory.createLazyValue {
// at this point, both metaAnnotations and annotationsFromPlugins should be collected
val result = metaAnnotations.flatMapTo(mutableSetOf()) { getAnnotationsWithMetaAnnotation(it) }
if (result.isEmpty()) {
annotationsFromPlugins
} else {
result += annotationsFromPlugins
result
}
// at this point, annotationsFromPlugins should be collected
annotationsFromPlugins
}
// MetaAnnotation -> Annotations
private val annotationsWithMetaAnnotationCache: FirCache<AnnotationFqn, Set<AnnotationFqn>, Nothing?> =
session.firCachesFactory.createCache { metaAnnotation -> collectAnnotationsWithMetaAnnotation(metaAnnotation) }
override fun getAnnotationsWithMetaAnnotation(metaAnnotation: AnnotationFqn): Collection<AnnotationFqn> {
return annotationsWithMetaAnnotationCache.getValue(metaAnnotation)
}
private fun collectAnnotationsWithMetaAnnotation(metaAnnotation: AnnotationFqn): Set<FqName> {
val annotatedDeclarations = annotationsResolver.declarationsByAnnotation(ClassId.topLevel(metaAnnotation))
@@ -59,8 +47,4 @@ internal class LLFirIdeRegisteredPluginAnnotations(
override fun saveAnnotationsFromPlugin(annotations: Collection<AnnotationFqn>) {
annotationsFromPlugins += annotations
}
override fun registerUserDefinedAnnotation(metaAnnotation: AnnotationFqn, annotationClasses: Collection<FirRegularClass>) {
error("This method should never be called in IDE mode")
}
}
@@ -214,7 +214,7 @@ internal object LLFirSessionFactory {
// We need FirRegisteredPluginAnnotations during extensions' registration process
val annotationsResolver = project.createAnnotationResolver(contentScope)
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this@session, annotationsResolver))
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider())
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
val dependencyProvider = LLFirDependentModuleProvidersByProviders(this) {
// <all libraries scope> - <current library scope>
@@ -24,7 +24,7 @@ internal class LLFirDesignatedAnnotationsResolveTransformed(
if (!designationIterator.hasNext()) {
val declaration = designation.declaration
if (declaration is FirRegularClass || declaration is FirTypeAlias) {
declaration.transform<FirDeclaration, Mode>(this, Mode.RegularAnnotations)
declaration.transform<FirDeclaration, Nothing?>(this, null)
}
return
}
@@ -63,5 +63,4 @@ internal class LLFirDesignatedAnnotationsResolveTransformed(
// todo add proper check that COMPILER_REQUIRED_ANNOTATIONS are resolved
// checkNestedDeclarationsAreResolved(declaration)
}
}
@@ -12,17 +12,23 @@ import org.jetbrains.kotlin.fir.FirSession
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.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
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.extensions.predicate.PredicateVisitor
import org.jetbrains.kotlin.fir.resolve.fqName
import org.jetbrains.kotlin.fir.resolve.getCorrespondingClassSymbolOrNull
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@NoMutableState
class FirPredicateBasedProviderImpl(private val session: FirSession) : FirPredicateBasedProvider() {
private val registeredPluginAnnotations = session.registeredPluginAnnotations
private val cache = Cache()
override fun getSymbolsByPredicate(predicate: DeclarationPredicate): List<FirBasedSymbol<*>> {
val annotations = registeredPluginAnnotations.getAnnotationsForPredicate(predicate)
override fun getSymbolsByPredicate(predicate: LookupPredicate): List<FirBasedSymbol<*>> {
val annotations = predicate.annotations
if (annotations.isEmpty()) return emptyList()
val declarations = annotations.flatMapTo(mutableSetOf()) {
cache.declarationByAnnotation[it] + cache.declarationsUnderAnnotated[it]
@@ -76,66 +82,75 @@ class FirPredicateBasedProviderImpl(private val session: FirSession) : FirPredic
// ---------------------------------- Matching ----------------------------------
override fun matches(predicate: DeclarationPredicate, declaration: FirDeclaration): Boolean {
return predicate.accept(matcher, declaration)
override fun matches(predicate: AbstractPredicate<*>, declaration: FirDeclaration): Boolean {
return when (predicate) {
is DeclarationPredicate -> predicate.accept(declarationPredicateMatcher, declaration)
is LookupPredicate -> predicate.accept(lookupPredicateMatcher, declaration)
}
}
private val matcher = Matcher()
private val declarationPredicateMatcher = Matcher<DeclarationPredicate>()
private val lookupPredicateMatcher = Matcher<LookupPredicate>()
private inner class Matcher : DeclarationPredicateVisitor<Boolean, FirDeclaration>() {
override fun visitPredicate(predicate: DeclarationPredicate, data: FirDeclaration): Boolean {
private inner class Matcher<P : AbstractPredicate<P>> : PredicateVisitor<P, Boolean, FirDeclaration>() {
override fun visitPredicate(predicate: AbstractPredicate<P>, data: FirDeclaration): Boolean {
throw IllegalStateException("Should not be there")
}
override fun visitAnd(predicate: DeclarationPredicate.And, data: FirDeclaration): Boolean {
override fun visitAnd(predicate: AbstractPredicate.And<P>, data: FirDeclaration): Boolean {
return predicate.a.accept(this, data) && predicate.b.accept(this, data)
}
override fun visitOr(predicate: DeclarationPredicate.Or, data: FirDeclaration): Boolean {
override fun visitOr(predicate: AbstractPredicate.Or<P>, data: FirDeclaration): Boolean {
return predicate.a.accept(this, data) || predicate.b.accept(this, data)
}
// ------------------------------------ Annotated ------------------------------------
override fun visitAnnotatedWith(predicate: AnnotatedWith, data: FirDeclaration): Boolean {
override fun visitAnnotatedWith(predicate: AbstractPredicate.AnnotatedWith<P>, data: FirDeclaration): Boolean {
return matchWith(data, predicate.annotations)
}
override fun visitAncestorAnnotatedWith(predicate: AncestorAnnotatedWith, data: FirDeclaration): Boolean {
override fun visitAncestorAnnotatedWith(
predicate: AbstractPredicate.AncestorAnnotatedWith<P>,
data: FirDeclaration
): Boolean {
return matchUnder(data, predicate.annotations)
}
override fun visitParentAnnotatedWith(predicate: ParentAnnotatedWith, data: FirDeclaration): Boolean {
override fun visitParentAnnotatedWith(
predicate: AbstractPredicate.ParentAnnotatedWith<P>,
data: FirDeclaration
): Boolean {
return matchParentWith(data, predicate.annotations)
}
override fun visitHasAnnotatedWith(predicate: HasAnnotatedWith, data: FirDeclaration): Boolean {
override fun visitHasAnnotatedWith(predicate: AbstractPredicate.HasAnnotatedWith<P>, data: FirDeclaration): Boolean {
return matchHasAnnotatedWith(data, predicate.annotations)
}
// ------------------------------------ Meta Annotated ------------------------------------
// ------------------------------------ Meta-annotated ------------------------------------
override fun visitMetaAnnotatedWith(predicate: MetaAnnotatedWith, data: FirDeclaration): Boolean {
return matchWith(data, predicate.userDefinedAnnotations)
override fun visitMetaAnnotatedWith(predicate: AbstractPredicate.MetaAnnotatedWith<P>, data: FirDeclaration): Boolean {
val visited = mutableSetOf<FirRegularClassSymbol>()
return data.annotations.any { annotation ->
annotation.markedWithMetaAnnotation(predicate.metaAnnotations, visited)
}
}
override fun visitAncestorMetaAnnotatedWith(predicate: AncestorMetaAnnotatedWith, data: FirDeclaration): Boolean {
return matchUnder(data, predicate.userDefinedAnnotations)
}
override fun visitParentMetaAnnotatedWith(predicate: ParentMetaAnnotatedWith, data: FirDeclaration): Boolean {
return matchParentWith(data, predicate.userDefinedAnnotations)
}
override fun visitHasMetaAnnotatedWith(predicate: HasMetaAnnotatedWith, data: FirDeclaration): Boolean {
return matchHasAnnotatedWith(data, predicate.userDefinedAnnotations)
private fun FirAnnotation.markedWithMetaAnnotation(
metaAnnotations: Set<AnnotationFqn>,
visited: MutableSet<FirRegularClassSymbol>
): Boolean {
val symbol = this.getCorrespondingClassSymbolOrNull(session) ?: return false
if (!visited.add(symbol)) return false
if (symbol.classId.asSingleFqName() in metaAnnotations) return true
if (symbol.resolvedAnnotationsWithClassIds.any { it.markedWithMetaAnnotation(metaAnnotations, visited) }) return true
return false
}
// ------------------------------------ Utilities ------------------------------------
private val MetaAnnotated.userDefinedAnnotations: Set<AnnotationFqn>
get() = metaAnnotations.flatMapTo(mutableSetOf()) { registeredPluginAnnotations.getAnnotationsWithMetaAnnotation(it) }
private fun matchWith(declaration: FirDeclaration, annotations: Set<AnnotationFqn>): Boolean {
return cache.annotationsOfDeclaration[declaration].any { it in annotations }
}
@@ -5,39 +5,21 @@
package org.jetbrains.kotlin.fir.extensions
import com.google.common.collect.LinkedHashMultimap
import com.google.common.collect.Multimap
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.NoMutableState
import org.jetbrains.kotlin.fir.caches.FirCache
import org.jetbrains.kotlin.fir.caches.createCache
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.caches.getValue
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.extensions.predicate.AbstractPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate
abstract class FirRegisteredPluginAnnotations(protected val session: FirSession) : FirSessionComponent {
/**
* Contains all annotations that can be targeted by the plugins. It includes the annotations directly mentioned by the plugin,
* and all the user-defined annotations which are meta-annotated by the annotations from the [metaAnnotations] list.
* Contains all annotations that can be targeted by lookup predicates from plugins
*/
abstract val annotations: Set<AnnotationFqn>
/**
* Contains meta-annotations that can be targeted by the plugins.
*/
abstract val metaAnnotations: Set<AnnotationFqn>
val hasRegisteredAnnotations: Boolean
get() = annotations.isNotEmpty() || metaAnnotations.isNotEmpty()
abstract fun getAnnotationsWithMetaAnnotation(metaAnnotation: AnnotationFqn): Collection<AnnotationFqn>
abstract fun registerUserDefinedAnnotation(metaAnnotation: AnnotationFqn, annotationClasses: Collection<FirRegularClass>)
abstract fun getAnnotationsForPredicate(predicate: DeclarationPredicate): Set<AnnotationFqn>
get() = annotations.isNotEmpty()
@PluginServicesInitialization
abstract fun initialize()
@@ -50,33 +32,16 @@ abstract class FirRegisteredPluginAnnotations(protected val session: FirSession)
* It also has some common code in it.
*/
abstract class AbstractFirRegisteredPluginAnnotations(session: FirSession) : FirRegisteredPluginAnnotations(session) {
final override val metaAnnotations: MutableSet<AnnotationFqn> = mutableSetOf()
private val annotationsForPredicateCache: FirCache<DeclarationPredicate, Set<AnnotationFqn>, Nothing?> =
session.firCachesFactory.createCache { predicate ->
collectAnnotations(predicate)
}
final override fun getAnnotationsForPredicate(predicate: DeclarationPredicate): Set<AnnotationFqn> {
return annotationsForPredicateCache.getValue(predicate)
}
private fun collectAnnotations(predicate: DeclarationPredicate): Set<AnnotationFqn> {
val result = predicate.metaAnnotations.flatMapTo(mutableSetOf()) { getAnnotationsWithMetaAnnotation(it) }
if (result.isEmpty()) return predicate.annotations
result += predicate.annotations
return result
}
@PluginServicesInitialization
final override fun initialize() {
val registrar = object : FirDeclarationPredicateRegistrar() {
val predicates = mutableListOf<DeclarationPredicate>()
override fun register(vararg predicates: DeclarationPredicate) {
val predicates = mutableListOf<AbstractPredicate<*>>()
override fun register(vararg predicates: AbstractPredicate<*>) {
this.predicates += predicates
}
override fun register(predicates: Collection<DeclarationPredicate>) {
override fun register(predicates: Collection<AbstractPredicate<*>>) {
this.predicates += predicates
}
}
@@ -89,7 +54,6 @@ abstract class AbstractFirRegisteredPluginAnnotations(session: FirSession) : Fir
for (predicate in registrar.predicates) {
saveAnnotationsFromPlugin(predicate.annotations)
metaAnnotations += predicate.metaAnnotations
}
}
@@ -100,23 +64,9 @@ abstract class AbstractFirRegisteredPluginAnnotations(session: FirSession) : Fir
class FirRegisteredPluginAnnotationsImpl(session: FirSession) : AbstractFirRegisteredPluginAnnotations(session) {
override val annotations: MutableSet<AnnotationFqn> = mutableSetOf()
// MetaAnnotation -> Annotations
private val userDefinedAnnotations: Multimap<AnnotationFqn, AnnotationFqn> = LinkedHashMultimap.create()
override fun getAnnotationsWithMetaAnnotation(metaAnnotation: AnnotationFqn): Collection<AnnotationFqn> {
return userDefinedAnnotations[metaAnnotation]
}
override fun saveAnnotationsFromPlugin(annotations: Collection<AnnotationFqn>) {
this.annotations += annotations
}
override fun registerUserDefinedAnnotation(metaAnnotation: AnnotationFqn, annotationClasses: Collection<FirRegularClass>) {
require(annotationClasses.all { it.classKind == ClassKind.ANNOTATION_CLASS })
val annotations = annotationClasses.map { it.symbol.classId.asSingleFqName() }
this.annotations += annotations
userDefinedAnnotations.putAll(metaAnnotation, annotations)
}
}
val FirSession.registeredPluginAnnotations: FirRegisteredPluginAnnotations by FirSession.sessionComponentAccessor()
@@ -5,11 +5,8 @@
package org.jetbrains.kotlin.fir.resolve.transformers.plugin
import com.google.common.collect.LinkedHashMultimap
import com.google.common.collect.Multimap
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.caches.firCachesFactory
@@ -21,10 +18,8 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement
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.fqName
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredAnnotationsResolveTransformer.Mode
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
@@ -33,7 +28,6 @@ import org.jetbrains.kotlin.fir.withFileAnalysisExceptionWrapping
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Deprecated
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.DeprecatedSinceKotlin
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.JvmRecord
@@ -46,25 +40,9 @@ class FirCompilerRequiredAnnotationsResolveProcessor(
override fun process(files: Collection<FirFile>) {
val transformer = FirCompilerRequiredAnnotationsResolveTransformer(session, scopeSession)
val registeredPluginAnnotations = session.registeredPluginAnnotations
if (!registeredPluginAnnotations.hasRegisteredAnnotations) {
files.forEach {
withFileAnalysisExceptionWrapping(it) {
it.transformSingle(transformer, Mode.RegularAnnotations)
}
}
return
}
if (registeredPluginAnnotations.metaAnnotations.isNotEmpty()) {
files.forEach {
withFileAnalysisExceptionWrapping(it) {
it.transformSingle(transformer, Mode.MetaAnnotations)
}
}
}
files.forEach {
withFileAnalysisExceptionWrapping(it) {
it.transformSingle(transformer, Mode.RegularAnnotations)
it.transformSingle(transformer, null)
}
}
}
@@ -83,42 +61,21 @@ class FirCompilerRequiredAnnotationsResolveProcessor(
open class FirCompilerRequiredAnnotationsResolveTransformer(
final override val session: FirSession,
scopeSession: ScopeSession
) : FirAbstractPhaseTransformer<Mode>(COMPILER_REQUIRED_ANNOTATIONS) {
enum class Mode {
MetaAnnotations,
RegularAnnotations
}
) : FirAbstractPhaseTransformer<Nothing?>(COMPILER_REQUIRED_ANNOTATIONS) {
private val annotationTransformer = FirAnnotationResolveTransformer(session, scopeSession)
private val importTransformer = FirPartialImportResolveTransformer(session)
val extensionService = session.extensionService
override fun <E : FirElement> transformElement(element: E, data: Mode): E {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): E {
throw IllegalStateException("Should not be here")
}
override fun transformFile(file: FirFile, data: Mode): FirFile {
override fun transformFile(file: FirFile, data: Nothing?): FirFile {
checkSessionConsistency(file)
val registeredPluginAnnotations = session.registeredPluginAnnotations
val regularAnnotations: Set<AnnotationFqn>
val metaAnnotations: Set<AnnotationFqn>
when (data) {
Mode.MetaAnnotations -> {
regularAnnotations = emptySet()
metaAnnotations = registeredPluginAnnotations.metaAnnotations
}
Mode.RegularAnnotations -> {
regularAnnotations = registeredPluginAnnotations.annotations
metaAnnotations = emptySet()
}
}
val regularAnnotations = registeredPluginAnnotations.annotations
val newAnnotations = file.resolveAnnotations(regularAnnotations, metaAnnotations)
if (!newAnnotations.isEmpty) {
for (metaAnnotation in newAnnotations.keySet()) {
registeredPluginAnnotations.registerUserDefinedAnnotation(metaAnnotation, newAnnotations[metaAnnotation])
}
}
file.resolveAnnotations(regularAnnotations)
return file
}
@@ -128,27 +85,21 @@ open class FirCompilerRequiredAnnotationsResolveTransformer(
}
}
override fun transformRegularClass(regularClass: FirRegularClass, data: Mode): FirStatement {
return annotationTransformer.transformRegularClass(regularClass, LinkedHashMultimap.create())
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): FirStatement {
return annotationTransformer.transformRegularClass(regularClass, null)
}
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Mode): FirStatement {
return annotationTransformer.transformTypeAlias(typeAlias, LinkedHashMultimap.create())
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): FirStatement {
return annotationTransformer.transformTypeAlias(typeAlias, null)
}
private fun FirFile.resolveAnnotations(
annotations: Set<AnnotationFqn>,
metaAnnotations: Set<AnnotationFqn>
): Multimap<AnnotationFqn, FirRegularClass> {
val acceptableNames = annotations + metaAnnotations
private fun FirFile.resolveAnnotations(annotations: Set<AnnotationFqn>) {
val acceptableNames = annotations
importTransformer.acceptableFqNames = acceptableNames
this.transformImports(importTransformer, null)
annotationTransformer.acceptableFqNames = acceptableNames
annotationTransformer.metaAnnotations = metaAnnotations
val newAnnotations = LinkedHashMultimap.create<AnnotationFqn, FirRegularClass>()
this.transform<FirFile, Multimap<AnnotationFqn, FirRegularClass>>(annotationTransformer, newAnnotations)
return newAnnotations
this.transform<FirFile, Nothing?>(annotationTransformer, null)
}
}
@@ -164,9 +115,7 @@ private class FirPartialImportResolveTransformer(
private class FirAnnotationResolveTransformer(
session: FirSession,
scopeSession: ScopeSession
) : FirAbstractAnnotationResolveTransformer<Multimap<AnnotationFqn, FirRegularClass>, PersistentList<FirDeclaration>>(
session, scopeSession
) {
) : FirAbstractAnnotationResolveTransformer<Nothing?, PersistentList<FirDeclaration>>(session, scopeSession) {
companion object {
private val REQUIRED_ANNOTATIONS: Set<ClassId> = setOf(
Deprecated, DeprecatedSinceKotlin, WasExperimental, JvmRecord
@@ -178,7 +127,7 @@ private class FirAnnotationResolveTransformer(
private val predicateBasedProvider = session.predicateBasedProvider
var acceptableFqNames: Set<AnnotationFqn> = emptySet()
var metaAnnotations: Set<AnnotationFqn> = emptySet()
private val typeResolverTransformer: FirSpecificTypeResolverTransformer = FirSpecificTypeResolverTransformer(
session,
errorTypeAsResolved = false
@@ -200,14 +149,11 @@ private class FirAnnotationResolveTransformer(
owners = state
}
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: Multimap<AnnotationFqn, FirRegularClass>): FirStatement {
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: Nothing?): FirStatement {
return transformAnnotation(annotationCall, data)
}
override fun transformAnnotation(
annotation: FirAnnotation,
data: Multimap<AnnotationFqn, FirRegularClass>
): FirStatement {
override fun transformAnnotation(annotation: FirAnnotation, data: Nothing?): FirStatement {
val annotationTypeRef = annotation.annotationTypeRef
if (annotationTypeRef !is FirUserTypeRef) return annotation
val name = annotationTypeRef.qualifier.last().name
@@ -224,36 +170,27 @@ private class FirAnnotationResolveTransformer(
return transformedAnnotation
}
override fun transformRegularClass(
regularClass: FirRegularClass,
data: Multimap<AnnotationFqn, FirRegularClass>
): FirStatement {
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): FirStatement {
withClassDeclarationCleanup(classDeclarationsStack, regularClass) {
return super.transformRegularClass(regularClass, data).also {
if (regularClass.classKind == ClassKind.ANNOTATION_CLASS && metaAnnotations.isNotEmpty()) {
val annotations = regularClass.annotations.mapNotNull { it.fqName(session) }
for (annotation in annotations.filter { it in metaAnnotations }) {
data.put(annotation, regularClass)
}
}
calculateDeprecations(regularClass)
}
}
}
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Multimap<AnnotationFqn, FirRegularClass>): FirTypeAlias {
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): FirTypeAlias {
return super.transformTypeAlias(typeAlias, data).also {
calculateDeprecations(typeAlias)
}
}
override fun transformDeclaration(declaration: FirDeclaration, data: Multimap<AnnotationFqn, FirRegularClass>): FirDeclaration {
override fun transformDeclaration(declaration: FirDeclaration, data: Nothing?): FirDeclaration {
return super.transformDeclaration(declaration, data).also {
predicateBasedProvider.registerAnnotatedDeclaration(declaration, owners)
}
}
override fun transformFile(file: FirFile, data: Multimap<AnnotationFqn, FirRegularClass>): FirFile {
override fun transformFile(file: FirFile, data: Nothing?): FirFile {
withFile(file) {
return super.transformFile(file, data)
}
@@ -6,7 +6,9 @@
package org.jetbrains.kotlin.fir.extensions
import org.jetbrains.kotlin.fir.FirSession
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.name.FqName
import org.jetbrains.kotlin.name.Name
import kotlin.reflect.KClass
@@ -38,8 +40,8 @@ data class FirExtensionPointName(val name: Name) {
// todo: KDOC
abstract class FirDeclarationPredicateRegistrar {
abstract fun register(vararg predicates: DeclarationPredicate)
abstract fun register(predicates: Collection<DeclarationPredicate>)
abstract fun register(vararg predicates: AbstractPredicate<*>)
abstract fun register(predicates: Collection<AbstractPredicate<*>>)
}
@RequiresOptIn
@@ -11,11 +11,13 @@ import org.jetbrains.kotlin.fir.FirSessionComponent
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 {
abstract fun getSymbolsByPredicate(predicate: DeclarationPredicate): List<FirBasedSymbol<*>>
abstract fun getSymbolsByPredicate(predicate: LookupPredicate): List<FirBasedSymbol<*>>
abstract fun getOwnersOfDeclaration(declaration: FirDeclaration): List<FirBasedSymbol<*>>?
/**
@@ -23,17 +25,17 @@ abstract class FirPredicateBasedProvider : FirSessionComponent {
* @see FirRegisteredPluginAnnotations.annotations
*/
abstract fun fileHasPluginAnnotations(file: FirFile): Boolean
abstract fun matches(predicate: DeclarationPredicate, declaration: FirDeclaration): Boolean
abstract fun matches(predicate: AbstractPredicate<*>, declaration: FirDeclaration): Boolean
fun matches(predicate: DeclarationPredicate, declaration: FirBasedSymbol<*>): Boolean {
fun matches(predicate: AbstractPredicate<*>, declaration: FirBasedSymbol<*>): Boolean {
return matches(predicate, declaration.fir)
}
fun matches(predicates: List<DeclarationPredicate>, declaration: FirDeclaration): Boolean {
fun matches(predicates: List<AbstractPredicate<*>>, declaration: FirDeclaration): Boolean {
return predicates.any { matches(it, declaration) }
}
fun matches(predicates: List<DeclarationPredicate>, declaration: FirBasedSymbol<*>): Boolean {
fun matches(predicates: List<AbstractPredicate<*>>, declaration: FirBasedSymbol<*>): Boolean {
return matches(predicates, declaration.fir)
}
@@ -41,14 +43,14 @@ abstract class FirPredicateBasedProvider : FirSessionComponent {
}
@NoMutableState
class FirEmptyPredicateBasedProvider(): FirPredicateBasedProvider() {
override fun getSymbolsByPredicate(predicate: DeclarationPredicate): List<FirBasedSymbol<*>> = emptyList()
object FirEmptyPredicateBasedProvider : FirPredicateBasedProvider() {
override fun getSymbolsByPredicate(predicate: LookupPredicate): List<FirBasedSymbol<*>> = emptyList()
override fun getOwnersOfDeclaration(declaration: FirDeclaration): List<FirBasedSymbol<*>>? = null
override fun fileHasPluginAnnotations(file: FirFile): Boolean = false
override fun matches(predicate: DeclarationPredicate, declaration: FirDeclaration): Boolean = false
override fun matches(predicate: AbstractPredicate<*>, declaration: FirDeclaration): Boolean = false
}
val FirSession.predicateBasedProvider: FirPredicateBasedProvider by FirSession.sessionComponentAccessor()
@@ -0,0 +1,97 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.extensions.predicate
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
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
sealed interface Or<P : AbstractPredicate<P>> : AbstractPredicate<P> {
val a: P
val b: P
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
return visitor.visitOr(this, data)
}
}
sealed interface And<P : AbstractPredicate<P>> : AbstractPredicate<P> {
val a: P
val b: P
override fun <R, D> accept(visitor: PredicateVisitor<P, R, D>, data: D): R {
return visitor.visitAnd(this, data)
}
}
// ------------------------------------ Annotated ------------------------------------
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)
}
}
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)
}
}
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)
}
}
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)
}
}
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)
}
}
// ------------------------------------ MetaAnnotated ------------------------------------
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)
}
}
// -------------------------------------------- DSL --------------------------------------------
abstract class BuilderContext<P : AbstractPredicate<P>> {
abstract infix fun P.or(other: P): P
abstract infix fun P.and(other: P): P
// ------------------- varargs -------------------
abstract fun annotated(vararg annotations: AnnotationFqn): P
abstract fun ancestorAnnotated(vararg annotations: AnnotationFqn): P
abstract fun parentAnnotated(vararg annotations: AnnotationFqn): P
abstract fun hasAnnotated(vararg annotations: AnnotationFqn): P
abstract fun annotatedOrUnder(vararg annotations: AnnotationFqn): P
// ------------------- collections -------------------
abstract fun annotated(annotations: Collection<AnnotationFqn>): P
abstract fun ancestorAnnotated(annotations: Collection<AnnotationFqn>): P
abstract fun parentAnnotated(annotations: Collection<AnnotationFqn>): P
abstract fun hasAnnotated(annotations: Collection<AnnotationFqn>): P
abstract fun annotatedOrUnder(annotations: Collection<AnnotationFqn>): P
}
}
@@ -10,226 +10,215 @@ import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
// -------------------------------------------- Predicates --------------------------------------------
// todo: Missing KDOC
sealed class DeclarationPredicate {
abstract val annotations: Set<AnnotationFqn>
abstract val metaAnnotations: Set<AnnotationFqn>
sealed class DeclarationPredicate : AbstractPredicate<DeclarationPredicate> {
abstract override val annotations: Set<AnnotationFqn>
abstract override val metaAnnotations: Set<AnnotationFqn>
abstract fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R
abstract override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R
class Or(val a: DeclarationPredicate, val b: DeclarationPredicate) : DeclarationPredicate() {
class Or(
override val a: DeclarationPredicate,
override val b: DeclarationPredicate
) : DeclarationPredicate(), AbstractPredicate.Or<DeclarationPredicate> {
override val annotations: Set<AnnotationFqn> = a.annotations + b.annotations
override val metaAnnotations: Set<AnnotationFqn> = a.metaAnnotations + b.metaAnnotations
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R {
return visitor.visitOr(this, data)
}
}
class And(val a: DeclarationPredicate, val b: DeclarationPredicate) : DeclarationPredicate() {
class And(
override val a: DeclarationPredicate,
override val b: DeclarationPredicate
) : DeclarationPredicate(), AbstractPredicate.And<DeclarationPredicate> {
override val annotations: Set<AnnotationFqn> = a.annotations + b.annotations
override val metaAnnotations: Set<AnnotationFqn> = a.metaAnnotations + b.metaAnnotations
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R {
return visitor.visitAnd(this, data)
}
}
}
// ------------------------------------ Annotated ------------------------------------
// ------------------------------------ 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() {
init {
require(annotations.isNotEmpty()) {
"Annotations should be not empty"
/**
* 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 {
require(annotations.isNotEmpty()) {
"Annotations should be not empty"
}
}
final override val metaAnnotations: Set<AnnotationFqn>
get() = emptySet()
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R {
return visitor.visitAnnotated(this, data)
}
}
final override val metaAnnotations: Set<AnnotationFqn>
get() = emptySet()
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<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]
*/
class AnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<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) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<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) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<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) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitHasAnnotatedWith(this, data)
}
}
// ------------------------------------ MetaAnnotated ------------------------------------
sealed class MetaAnnotated(final override val metaAnnotations: Set<AnnotationFqn>) : DeclarationPredicate() {
init {
require(metaAnnotations.isNotEmpty()) {
"Annotations should be not empty"
/**
* 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)
}
}
final override val annotations: Set<AnnotationFqn>
get() = emptySet()
/**
* 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 {
return visitor.visitAncestorAnnotatedWith(this, data)
}
}
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitMetaAnnotated(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<DeclarationPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, 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<DeclarationPredicate> {
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R {
return visitor.visitHasAnnotatedWith(this, data)
}
}
// ------------------------------------ MetaAnnotated ------------------------------------
class MetaAnnotatedWith(
override val metaAnnotations: Set<AnnotationFqn>
) : DeclarationPredicate(), AbstractPredicate.MetaAnnotatedWith<DeclarationPredicate> {
init {
require(metaAnnotations.isNotEmpty()) {
"Annotations should be not empty"
}
}
override val annotations: Set<AnnotationFqn>
get() = emptySet()
override fun <R, D> accept(visitor: PredicateVisitor<DeclarationPredicate, R, D>, data: D): R {
return visitor.visitMetaAnnotatedWith(this, data)
}
}
// -------------------------------------------- DSL --------------------------------------------
object BuilderContext : AbstractPredicate.BuilderContext<DeclarationPredicate>() {
override infix fun DeclarationPredicate.or(other: DeclarationPredicate): DeclarationPredicate = Or(this, other)
override infix fun DeclarationPredicate.and(other: DeclarationPredicate): DeclarationPredicate = And(this, other)
// ------------------- varargs -------------------
override fun annotated(vararg annotations: AnnotationFqn): DeclarationPredicate = annotated(annotations.toList())
override fun ancestorAnnotated(vararg annotations: AnnotationFqn): DeclarationPredicate = ancestorAnnotated(annotations.toList())
override fun parentAnnotated(vararg annotations: AnnotationFqn): DeclarationPredicate = parentAnnotated(annotations.toList())
override fun hasAnnotated(vararg annotations: AnnotationFqn): DeclarationPredicate = hasAnnotated(annotations.toList())
override fun annotatedOrUnder(vararg annotations: AnnotationFqn): DeclarationPredicate =
annotated(*annotations) or ancestorAnnotated(*annotations)
fun metaAnnotated(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = MetaAnnotatedWith(metaAnnotations.toSet())
// ------------------- collections -------------------
override fun annotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate = AnnotatedWith(annotations.toSet())
override fun ancestorAnnotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate =
AncestorAnnotatedWith(annotations.toSet())
override fun parentAnnotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate =
ParentAnnotatedWith(annotations.toSet())
override fun hasAnnotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate = HasAnnotatedWith(annotations.toSet())
override fun annotatedOrUnder(annotations: Collection<AnnotationFqn>): DeclarationPredicate =
annotated(annotations) or ancestorAnnotated(annotations)
fun metaAnnotated(metaAnnotations: Collection<AnnotationFqn>): DeclarationPredicate = MetaAnnotatedWith(metaAnnotations.toSet())
}
companion object {
inline fun create(init: BuilderContext.() -> DeclarationPredicate): DeclarationPredicate = BuilderContext.init()
}
}
class MetaAnnotatedWith(metaAnnotations: Set<AnnotationFqn>) : MetaAnnotated(metaAnnotations) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitMetaAnnotatedWith(this, data)
}
}
class AncestorMetaAnnotatedWith(metaAnnotations: Set<AnnotationFqn>) : MetaAnnotated(metaAnnotations) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitAncestorMetaAnnotatedWith(this, data)
}
}
class ParentMetaAnnotatedWith(metaAnnotations: Set<AnnotationFqn>) : MetaAnnotated(metaAnnotations) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitParentMetaAnnotatedWith(this, data)
}
}
class HasMetaAnnotatedWith(metaAnnotations: Set<AnnotationFqn>) : MetaAnnotated(metaAnnotations) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitHasMetaAnnotatedWith(this, data)
}
}
// -------------------------------------------- DSL --------------------------------------------
infix fun DeclarationPredicate.or(other: DeclarationPredicate): DeclarationPredicate = DeclarationPredicate.Or(this, other)
infix fun DeclarationPredicate.and(other: DeclarationPredicate): DeclarationPredicate = DeclarationPredicate.And(this, other)
// ------------------- varargs -------------------
fun annotated(vararg annotations: AnnotationFqn): DeclarationPredicate = AnnotatedWith(annotations.toSet())
fun ancestorAnnotated(vararg annotations: AnnotationFqn): DeclarationPredicate = AncestorAnnotatedWith(annotations.toSet())
fun parentAnnotated(vararg annotations: AnnotationFqn): DeclarationPredicate = ParentAnnotatedWith(annotations.toSet())
fun hasAnnotated(vararg annotations: AnnotationFqn): DeclarationPredicate = HasAnnotatedWith(annotations.toSet())
fun metaAnnotated(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = MetaAnnotatedWith(metaAnnotations.toSet())
fun metaAncestorAnnotated(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = AncestorMetaAnnotatedWith(metaAnnotations.toSet())
fun parentMetaAnnotated(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = ParentMetaAnnotatedWith(metaAnnotations.toSet())
fun hasMetaAnnotated(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = HasMetaAnnotatedWith(metaAnnotations.toSet())
fun annotatedOrUnder(vararg annotations: AnnotationFqn): DeclarationPredicate = annotated(*annotations) or ancestorAnnotated(*annotations)
fun metaAnnotatedOrUnder(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate =
metaAnnotated(*metaAnnotations) or metaAncestorAnnotated(*metaAnnotations)
// ------------------- collections -------------------
fun annotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate = AnnotatedWith(annotations.toSet())
fun ancestorAnnotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate = AncestorAnnotatedWith(annotations.toSet())
fun parentAnnotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate = ParentAnnotatedWith(annotations.toSet())
fun hasAnnotated(annotations: Collection<AnnotationFqn>): DeclarationPredicate = HasAnnotatedWith(annotations.toSet())
fun metaAnnotated(metaAnnotations: Collection<AnnotationFqn>): DeclarationPredicate = MetaAnnotatedWith(metaAnnotations.toSet())
fun metaAncestorAnnotated(metaAnnotations: Collection<AnnotationFqn>): DeclarationPredicate = AncestorMetaAnnotatedWith(metaAnnotations.toSet())
fun parentMetaAnnotated(metaAnnotations: Collection<AnnotationFqn>): DeclarationPredicate = ParentMetaAnnotatedWith(metaAnnotations.toSet())
fun hasMetaAnnotated(metaAnnotations: Collection<AnnotationFqn>): DeclarationPredicate = HasMetaAnnotatedWith(metaAnnotations.toSet())
fun annotatedOrUnder(annotations: Collection<AnnotationFqn>): DeclarationPredicate = annotated(annotations) or ancestorAnnotated(annotations)
fun metaAnnotatedOrUnder(metaAnnotations: Collection<AnnotationFqn>): DeclarationPredicate =
metaAnnotated(metaAnnotations) or metaAncestorAnnotated(metaAnnotations)
@@ -1,58 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.extensions.predicate
abstract class DeclarationPredicateVisitor<R, D> {
abstract fun visitPredicate(predicate: DeclarationPredicate, data: D): R
open fun visitAnd(predicate: DeclarationPredicate.And, data: D): R {
return visitPredicate(predicate, data)
}
open fun visitOr(predicate: DeclarationPredicate.Or, data: D): R {
return visitPredicate(predicate, data)
}
open fun visitAnnotated(predicate: Annotated, data: D): R {
return visitPredicate(predicate, data)
}
open fun visitAnnotatedWith(predicate: AnnotatedWith, data: D): R {
return visitAnnotated(predicate, data)
}
open fun visitAncestorAnnotatedWith(predicate: AncestorAnnotatedWith, data: D): R {
return visitAnnotated(predicate, data)
}
open fun visitParentAnnotatedWith(predicate: ParentAnnotatedWith, data: D): R {
return visitAnnotated(predicate, data)
}
open fun visitHasAnnotatedWith(predicate: HasAnnotatedWith, data: D): R {
return visitAnnotated(predicate, data)
}
open fun visitMetaAnnotated(predicate: MetaAnnotated, data: D): R {
return visitPredicate(predicate, data)
}
open fun visitMetaAnnotatedWith(predicate: MetaAnnotatedWith, data: D): R {
return visitMetaAnnotated(predicate, data)
}
open fun visitAncestorMetaAnnotatedWith(predicate: AncestorMetaAnnotatedWith, data: D): R {
return visitMetaAnnotated(predicate, data)
}
open fun visitParentMetaAnnotatedWith(predicate: ParentMetaAnnotatedWith, data: D): R {
return visitMetaAnnotated(predicate, data)
}
open fun visitHasMetaAnnotatedWith(predicate: HasMetaAnnotatedWith, data: D): R {
return visitMetaAnnotated(predicate, data)
}
}
@@ -0,0 +1,183 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.extensions.predicate
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
sealed class LookupPredicate : AbstractPredicate<LookupPredicate> {
abstract override val annotations: Set<AnnotationFqn>
final override val metaAnnotations: Set<AnnotationFqn>
get() = error("Should not be called")
abstract override fun <R, D> accept(visitor: PredicateVisitor<LookupPredicate, R, D>, data: D): R
class Or(
override val a: LookupPredicate,
override val b: LookupPredicate
) : LookupPredicate(), AbstractPredicate.Or<LookupPredicate> {
override val annotations: Set<AnnotationFqn> = a.annotations + b.annotations
override fun <R, D> accept(visitor: PredicateVisitor<LookupPredicate, R, D>, data: D): R {
return visitor.visitOr(this, data)
}
}
class And(
override val a: LookupPredicate,
override val b: LookupPredicate
) : LookupPredicate(), AbstractPredicate.And<LookupPredicate> {
override val annotations: Set<AnnotationFqn> = a.annotations + b.annotations
override fun <R, D> accept(visitor: PredicateVisitor<LookupPredicate, R, D>, data: D): R {
return visitor.visitAnd(this, data)
}
}
/**
* 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()) {
"Annotations should be not empty"
}
}
override fun <R, D> accept(visitor: PredicateVisitor<LookupPredicate, 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]
*/
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 {
return visitor.visitHasAnnotatedWith(this, data)
}
}
// -------------------------------------------- DSL --------------------------------------------
object BuilderContext : AbstractPredicate.BuilderContext<LookupPredicate>() {
override infix fun LookupPredicate.or(other: LookupPredicate): LookupPredicate = Or(this, other)
override infix fun LookupPredicate.and(other: LookupPredicate): LookupPredicate = And(this, other)
// ------------------- varargs -------------------
override fun annotated(vararg annotations: AnnotationFqn): LookupPredicate = annotated(annotations.toList())
override fun ancestorAnnotated(vararg annotations: AnnotationFqn): LookupPredicate = ancestorAnnotated(annotations.toList())
override fun parentAnnotated(vararg annotations: AnnotationFqn): LookupPredicate = parentAnnotated(annotations.toList())
override fun hasAnnotated(vararg annotations: AnnotationFqn): LookupPredicate = hasAnnotated(annotations.toList())
override fun annotatedOrUnder(vararg annotations: AnnotationFqn): LookupPredicate =
annotated(*annotations) or ancestorAnnotated(*annotations)
// ------------------- collections -------------------
override fun annotated(annotations: Collection<AnnotationFqn>): LookupPredicate = AnnotatedWith(annotations.toSet())
override fun ancestorAnnotated(annotations: Collection<AnnotationFqn>): LookupPredicate = AncestorAnnotatedWith(annotations.toSet())
override fun parentAnnotated(annotations: Collection<AnnotationFqn>): LookupPredicate = ParentAnnotatedWith(annotations.toSet())
override fun hasAnnotated(annotations: Collection<AnnotationFqn>): LookupPredicate = HasAnnotatedWith(annotations.toSet())
override fun annotatedOrUnder(annotations: Collection<AnnotationFqn>): LookupPredicate =
annotated(annotations) or ancestorAnnotated(annotations)
}
companion object {
inline fun create(init: BuilderContext.() -> LookupPredicate): LookupPredicate = BuilderContext.init()
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.extensions.predicate
abstract class PredicateVisitor<P : AbstractPredicate<P>, R, D> {
abstract fun visitPredicate(predicate: AbstractPredicate<P>, data: D): R
open fun visitAnd(predicate: AbstractPredicate.And<P>, data: D): R {
return visitPredicate(predicate, data)
}
open fun visitOr(predicate: AbstractPredicate.Or<P>, data: D): R {
return visitPredicate(predicate, data)
}
open fun visitAnnotated(predicate: AbstractPredicate.Annotated<P>, data: D): R {
return visitPredicate(predicate, data)
}
open fun visitAnnotatedWith(predicate: AbstractPredicate.AnnotatedWith<P>, data: D): R {
return visitAnnotated(predicate, data)
}
open fun visitAncestorAnnotatedWith(predicate: AbstractPredicate.AncestorAnnotatedWith<P>, data: D): R {
return visitAnnotated(predicate, data)
}
open fun visitParentAnnotatedWith(predicate: AbstractPredicate.ParentAnnotatedWith<P>, data: D): R {
return visitAnnotated(predicate, data)
}
open fun visitHasAnnotatedWith(predicate: AbstractPredicate.HasAnnotatedWith<P>, data: D): R {
return visitAnnotated(predicate, data)
}
open fun visitMetaAnnotatedWith(predicate: AbstractPredicate.MetaAnnotatedWith<P>, data: D): R {
return visitPredicate(predicate, data)
}
}
typealias DeclarationPredicateVisitor<R, D> = PredicateVisitor<DeclarationPredicate, R, D>
typealias LookupPredicateVisitor<R, D> = PredicateVisitor<LookupPredicate, R, D>
@@ -15,9 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.extensions.FirExtensionSessionComponent.Factory
import org.jetbrains.kotlin.fir.extensions.FirStatusTransformerExtension
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicate.metaAnnotated
import org.jetbrains.kotlin.fir.extensions.predicate.or
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.utils.AbstractSimpleClassPredicateMatchingService
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -57,7 +55,7 @@ class FirAllOpenPredicateMatcher(
}
}
override val predicate = run {
override val predicate = DeclarationPredicate.create {
val annotationFqNames = allOpenAnnotationFqNames.map { FqName(it) }
annotated(annotationFqNames) or metaAnnotated(annotationFqNames)
}
@@ -0,0 +1,36 @@
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class AllOpen {
// source: 'anonymousObject.kt'
}
@kotlin.Metadata
public final class Test$a$1 {
// source: 'anonymousObject.kt'
enclosing method Test.<init>()V
inner (anonymous) class Test$a$1
method <init>(): void
public final method run(): void
}
@kotlin.Metadata
public final class Test$b$1 {
// source: 'anonymousObject.kt'
enclosing method Test.b()V
inner (anonymous) class Test$b$1
method <init>(): void
public final method run(): void
}
@AllOpen
@kotlin.Metadata
public class Test {
// source: 'anonymousObject.kt'
private final @org.jetbrains.annotations.NotNull field a: java.lang.Runnable
inner (anonymous) class Test$a$1
inner (anonymous) class Test$b$1
public method <init>(): void
private final static method b$lambda$0(): void
public method b(): void
public @org.jetbrains.annotations.NotNull method getA(): java.lang.Runnable
}
@@ -1,6 +1,6 @@
// IGNORE_BACKEND_K2: JVM_IR
// FIR version does not go inside bodies
// Also it's quiestionable do we even need to transform local classes and anonymous objects
annotation class AllOpen
@AllOpen
@@ -1,5 +1,4 @@
// IGNORE_BACKEND_K2: JVM_IR
// FIR version does not support double-transitive annotations by design
// MODULE: lib
annotation class AllOpen
@AllOpen
@@ -14,6 +13,8 @@ annotation class AnotherComponent
@java.lang.annotation.Documented
annotation class Documented
// MODULE: main(lib)
class TestWithoutAnnotations_ShouldBeFinal
@Documented
@@ -0,0 +1,103 @@
Module: lib
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class AllOpen {
// source: 'module_lib_metaAnnotation_differentModules.kt'
}
@OtherComponent
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class AnotherComponent {
// source: 'module_lib_metaAnnotation_differentModules.kt'
}
@java.lang.annotation.Documented
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class Documented {
// source: 'module_lib_metaAnnotation_differentModules.kt'
}
@AllOpen
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class MyComponent {
// source: 'module_lib_metaAnnotation_differentModules.kt'
}
@MyComponent
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class OtherComponent {
// source: 'module_lib_metaAnnotation_differentModules.kt'
}
Module: main
@Documented
@kotlin.Metadata
public final class ClassWithDocumented {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
}
@MyComponent
@kotlin.Metadata
public abstract class MyComponentBase {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
}
@kotlin.Metadata
public final class MyComponentImpl2_ShouldBeFinal {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
public method method(): void
}
@kotlin.Metadata
public class MyComponentImpl3_ShouldBeOpen {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
public final method method_ShouldBeFinal(): void
}
@kotlin.Metadata
public class MyComponentImpl_ShouldBeOpen {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
public method method(): void
}
@AllOpen
@kotlin.Metadata
public class TestAllOpen_ShouldBeOpen {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
}
@AnotherComponent
@kotlin.Metadata
public class TestAnotherComponent_ShouldBeOpen {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
}
@MyComponent
@kotlin.Metadata
public class TestMyComponent_ShouldBeOpen {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
}
@OtherComponent
@kotlin.Metadata
public class TestOtherComponent_ShouldBeOpen {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
}
@kotlin.Metadata
public final class TestWithoutAnnotations_ShouldBeFinal {
// source: 'module_main_metaAnnotation_differentModules.kt'
public method <init>(): void
}
@@ -0,0 +1,45 @@
annotation class AllOpen
@AllOpen
annotation class MyComponent
@MyComponent // Double-transitive annotations is supported
annotation class OtherComponent
@OtherComponent
annotation class AnotherComponent
@java.lang.annotation.Documented
annotation class Documented
class TestWithoutAnnotations_ShouldBeFinal
@Documented
class ClassWithDocumented
@AllOpen
class TestAllOpen_ShouldBeOpen
@MyComponent
class TestMyComponent_ShouldBeOpen
@OtherComponent
class TestOtherComponent_ShouldBeOpen
@AnotherComponent
class TestAnotherComponent_ShouldBeOpen
@MyComponent
abstract class MyComponentBase
class MyComponentImpl_ShouldBeOpen : MyComponentBase() {
fun method() {}
}
final class MyComponentImpl2_ShouldBeFinal : MyComponentBase() {
fun method() {}
}
class MyComponentImpl3_ShouldBeOpen : MyComponentBase() {
final fun method_ShouldBeFinal() {}
}
@@ -1,20 +1,20 @@
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class AllOpen {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
}
@OtherComponent
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class AnotherComponent {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
}
@Documented
@kotlin.Metadata
public final class ClassWithDocumented {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
}
@@ -22,40 +22,40 @@ public final class ClassWithDocumented {
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class Documented {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
}
@AllOpen
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class MyComponent {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
}
@MyComponent
@kotlin.Metadata
public abstract class MyComponentBase {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
}
@kotlin.Metadata
public final class MyComponentImpl2_ShouldBeFinal {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
public method method(): void
}
@kotlin.Metadata
public class MyComponentImpl3_ShouldBeOpen {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
public final method method_ShouldBeFinal(): void
}
@kotlin.Metadata
public class MyComponentImpl_ShouldBeOpen {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
public method method(): void
}
@@ -64,39 +64,39 @@ public class MyComponentImpl_ShouldBeOpen {
@java.lang.annotation.Retention(value=RUNTIME)
@kotlin.Metadata
public annotation class OtherComponent {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
}
@AllOpen
@kotlin.Metadata
public class TestAllOpen_ShouldBeOpen {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
}
@AnotherComponent
@kotlin.Metadata
public class TestAnotherComponent_ShouldBeOpen {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
}
@MyComponent
@kotlin.Metadata
public class TestMyComponent_ShouldBeOpen {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
}
@OtherComponent
@kotlin.Metadata
public class TestOtherComponent_ShouldBeOpen {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
}
@kotlin.Metadata
public final class TestWithoutAnnotations_ShouldBeFinal {
// source: 'metaAnnotation.kt'
// source: 'metaAnnotation_sameModule.kt'
public method <init>(): void
}
@@ -56,9 +56,15 @@ public class BytecodeListingTestForAllOpenGenerated extends AbstractBytecodeList
}
@Test
@TestMetadata("metaAnnotation.kt")
public void testMetaAnnotation() throws Exception {
runTest("plugins/allopen/testData/bytecodeListing/metaAnnotation.kt");
@TestMetadata("metaAnnotation_differentModules.kt")
public void testMetaAnnotation_differentModules() throws Exception {
runTest("plugins/allopen/testData/bytecodeListing/metaAnnotation_differentModules.kt");
}
@Test
@TestMetadata("metaAnnotation_sameModule.kt")
public void testMetaAnnotation_sameModule() throws Exception {
runTest("plugins/allopen/testData/bytecodeListing/metaAnnotation_sameModule.kt");
}
@Test
@@ -56,9 +56,15 @@ public class FirBytecodeListingTestForAllOpenGenerated extends AbstractFirByteco
}
@Test
@TestMetadata("metaAnnotation.kt")
public void testMetaAnnotation() throws Exception {
runTest("plugins/allopen/testData/bytecodeListing/metaAnnotation.kt");
@TestMetadata("metaAnnotation_differentModules.kt")
public void testMetaAnnotation_differentModules() throws Exception {
runTest("plugins/allopen/testData/bytecodeListing/metaAnnotation_differentModules.kt");
}
@Test
@TestMetadata("metaAnnotation_sameModule.kt")
public void testMetaAnnotation_sameModule() throws Exception {
runTest("plugins/allopen/testData/bytecodeListing/metaAnnotation_sameModule.kt");
}
@Test
@@ -56,9 +56,15 @@ public class IrBytecodeListingTestForAllOpenGenerated extends AbstractIrBytecode
}
@Test
@TestMetadata("metaAnnotation.kt")
public void testMetaAnnotation() throws Exception {
runTest("plugins/allopen/testData/bytecodeListing/metaAnnotation.kt");
@TestMetadata("metaAnnotation_differentModules.kt")
public void testMetaAnnotation_differentModules() throws Exception {
runTest("plugins/allopen/testData/bytecodeListing/metaAnnotation_differentModules.kt");
}
@Test
@TestMetadata("metaAnnotation_sameModule.kt")
public void testMetaAnnotation_sameModule() throws Exception {
runTest("plugins/allopen/testData/bytecodeListing/metaAnnotation_sameModule.kt");
}
@Test
@@ -12,9 +12,6 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.FirStatusTransformerExtension
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.annotatedOrUnder
import org.jetbrains.kotlin.fir.extensions.predicate.metaAnnotatedOrUnder
import org.jetbrains.kotlin.fir.extensions.predicate.or
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.extensions.transform
import org.jetbrains.kotlin.name.FqName
@@ -22,7 +19,9 @@ import org.jetbrains.kotlin.name.FqName
class AllOpenStatusTransformer(session: FirSession) : FirStatusTransformerExtension(session) {
companion object {
private val ALL_OPEN = FqName("org.jetbrains.kotlin.fir.plugin.AllOpen")
private val PREDICATE: DeclarationPredicate = annotatedOrUnder(ALL_OPEN) or metaAnnotatedOrUnder(ALL_OPEN)
private val PREDICATE = DeclarationPredicate.create {
annotatedOrUnder(ALL_OPEN) or metaAnnotated(ALL_OPEN)
}
}
override fun transformStatus(status: FirDeclarationStatus, declaration: FirDeclaration): FirDeclarationStatus {
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.expressions.arguments
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.FirStatusTransformerExtension
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.annotatedOrUnder
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.extensions.transform
import org.jetbrains.kotlin.fir.references.FirNamedReference
@@ -37,7 +36,7 @@ class AllPublicVisibilityTransformer(session: FirSession) : FirStatusTransformer
private val PrivateName = Name.identifier("Private")
private val ProtectedName = Name.identifier("Protected")
private val PREDICATE: DeclarationPredicate = annotatedOrUnder(AllPublicClassId.asSingleFqName())
private val PREDICATE = DeclarationPredicate.create { annotatedOrUnder(AllPublicClassId.asSingleFqName()) }
}
override fun transformStatus(status: FirDeclarationStatus, declaration: FirDeclaration): FirDeclarationStatus {
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
@@ -26,7 +25,7 @@ import org.jetbrains.kotlin.name.Name
class SomeAdditionalSupertypeGenerator(session: FirSession) : FirSupertypeGenerationExtension(session) {
companion object {
private val myInterfaceClassId = ClassId(FqName("foo"), Name.identifier("MyInterface"))
private val PREDICATE: DeclarationPredicate = annotated("MyInterfaceSupertype".fqn())
private val PREDICATE = DeclarationPredicate.create { annotated("MyInterfaceSupertype".fqn()) }
}
@@ -13,13 +13,11 @@ import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension
import org.jetbrains.kotlin.fir.extensions.buildUserTypeFromQualifierParts
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.constructClassLikeType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -32,7 +30,7 @@ class SupertypeWithArgumentGenerator(session: FirSession) : FirSupertypeGenerati
companion object {
private val supertypeClassId = ClassId(FqName("foo"), Name.identifier("InterfaceWithArgument"))
private val annotationClassId = ClassId.topLevel("SupertypeWithTypeArgument".fqn())
private val PREDICATE: DeclarationPredicate = annotated(annotationClassId.asSingleFqName())
private val PREDICATE = DeclarationPredicate.create { annotated(annotationClassId.asSingleFqName()) }
}
@@ -5,12 +5,12 @@
package org.jetbrains.kotlin.fir.plugin.generators
import org.jetbrains.kotlin.GeneratedDeclarationKey
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.GeneratedDeclarationKey
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
@@ -18,8 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.origin
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.plugin.fqn
@@ -40,7 +39,7 @@ class AdditionalMembersGenerator(session: FirSession) : FirDeclarationGeneration
private val MATERIALIZE_NAME = Name.identifier("materialize")
private val NESTED_NAME = Name.identifier("Nested")
private val PREDICATE: DeclarationPredicate = annotated("NestedClassAndMaterializeMember".fqn())
private val PREDICATE = LookupPredicate.create { annotated("NestedClassAndMaterializeMember".fqn()) }
}
private val predicateBasedProvider = session.predicateBasedProvider
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.declarations.origin
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.plugin.fqn
@@ -38,7 +38,7 @@ import org.jetbrains.kotlin.name.SpecialNames
*/
class CompanionGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
companion object {
private val PREDICATE = annotated("CompanionWithFoo".fqn())
private val PREDICATE = LookupPredicate.create { annotated("CompanionWithFoo".fqn()) }
private val FOO_NAME = Name.identifier("foo")
}
@@ -17,8 +17,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusIm
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.plugin.fqn
@@ -43,7 +42,7 @@ class ExternalClassGenerator(session: FirSession) : FirDeclarationGenerationExte
private val GENERATED_CLASS_ID = ClassId(FOO_PACKAGE, Name.identifier("AllOpenGenerated"))
private val MATERIALIZE_NAME = Name.identifier("materialize")
private val PREDICATE: DeclarationPredicate = annotated("ExternalClassWithNested".fqn())
private val PREDICATE = LookupPredicate.create { annotated("ExternalClassWithNested".fqn()) }
}
object Key : GeneratedDeclarationKey() {
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildBlock
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.plugin.fqn
@@ -37,8 +37,8 @@ import org.jetbrains.kotlin.name.Name
*/
class MembersOfSerializerGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
companion object {
private val SERIALIZABLE_PREDICATE = annotated("MySerializable".fqn())
private val CORE_SERIALIZER_PREDICATE = annotated("CoreSerializer".fqn())
private val SERIALIZABLE_PREDICATE = LookupPredicate.create { annotated("MySerializable".fqn()) }
private val CORE_SERIALIZER_PREDICATE = LookupPredicate.create { annotated("CoreSerializer".fqn()) }
private val X_NAME = Name.identifier("x")
}
@@ -18,8 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.origin
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.plugin.fqn
@@ -35,7 +34,7 @@ import org.jetbrains.kotlin.name.Name
*/
class TopLevelDeclarationsGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
companion object {
private val PREDICATE: DeclarationPredicate = annotated("DummyFunction".fqn())
private val PREDICATE = LookupPredicate.create { annotated("DummyFunction".fqn()) }
}
private val predicateBasedProvider = session.predicateBasedProvider
@@ -4,7 +4,7 @@ FILE: first.kt
super<R|kotlin/Any|>()
}
public open fun foo(): R|kotlin/Unit| {
public final fun foo(): R|kotlin/Unit| {
}
}
@@ -9,7 +9,7 @@ class A {
@Open
class B : A() {
override fun foo() {
<!OVERRIDING_FINAL_MEMBER!>override<!> fun foo() {
}
}
@@ -9,11 +9,13 @@ import org.jetbrains.kotlin.fir.extensions.predicate.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
object FirSerializationPredicates {
internal val serializerFor: DeclarationPredicate =
AnnotatedWith(setOf(SerializationAnnotations.serializerAnnotationFqName)) // @Serializer(for=...)
internal val generatedSerializer: DeclarationPredicate =
ancestorAnnotated(SerializationAnnotations.serializableAnnotationFqName) // @Serializable X.$serializer
internal val hasMetaAnnotation = metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName)
internal val annotatedWithSerializableOrMeta =
AnnotatedWith(setOf(SerializationAnnotations.serializableAnnotationFqName)) or metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName)
internal val serializerFor = DeclarationPredicate.create {
annotated(setOf(SerializationAnnotations.serializerAnnotationFqName)) // @Serializer(for=...)
}
internal val hasMetaAnnotation = DeclarationPredicate.create {
metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName)
}
internal val annotatedWithSerializableOrMeta = DeclarationPredicate.create {
annotated(setOf(SerializationAnnotations.serializableAnnotationFqName)) or metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName)
}
}
@@ -250,12 +250,6 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
return listOf(copy.symbol)
}
// FIXME: it seems that this list will always be used, why not provide it automatically?
private val matchedClasses by lazy {
session.predicateBasedProvider.getSymbolsByPredicate(FirSerializationPredicates.annotatedWithSerializableOrMeta)
.filterIsInstance<FirRegularClassSymbol>()
}
override fun generateConstructors(context: MemberGenerationContext): List<FirConstructorSymbol> {
val owner = context.owner
val defaultObjectConstructor = buildPrimaryConstructor(
@@ -291,10 +285,15 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
return listOf(defaultObjectConstructor.symbol)
}
fun addSerializerImplClass(
classId: ClassId
): FirClassLikeSymbol<*>? {
val owner = matchedClasses.firstOrNull { it.classId == classId.outerClassId } ?: return null
private fun getClassWithAnnotatedWithSerializableOrMeta(classId: ClassId?): FirRegularClassSymbol? {
if (classId == null) return null
return (session.symbolProvider.getClassLikeSymbolByClassId(classId) as? FirRegularClassSymbol)?.takeIf {
session.predicateBasedProvider.matches(FirSerializationPredicates.annotatedWithSerializableOrMeta, it)
}
}
fun addSerializerImplClass(classId: ClassId): FirClassLikeSymbol<*>? {
val owner = getClassWithAnnotatedWithSerializableOrMeta(classId.outerClassId) ?: return null
val hasTypeParams = owner.typeParameterSymbols.isNotEmpty()
val serializerKind = if (hasTypeParams) ClassKind.CLASS else ClassKind.OBJECT
val serializerFirClass = buildRegularClass {
@@ -332,7 +331,7 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
fun generateCompanionDeclaration(classId: ClassId): FirClassLikeSymbol<*>? {
if (classId.shortClassName != SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT) return null
val owner = matchedClasses.firstOrNull { it.classId == classId.outerClassId } ?: return null
val owner = getClassWithAnnotatedWithSerializableOrMeta(classId.outerClassId) ?: return null
if (owner.companionObjectSymbol != null) return null
val regularClass = buildRegularClass {
moduleData = session.moduleData
@@ -6,9 +6,7 @@
package org.jetbrains.kotlin.noarg.fir
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicate.metaAnnotated
import org.jetbrains.kotlin.fir.extensions.predicate.or
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.utils.AbstractSimpleClassPredicateMatchingService
import org.jetbrains.kotlin.name.FqName
@@ -22,7 +20,7 @@ class FirNoArgPredicateMatcher(
}
}
override val predicate = run {
override val predicate = DeclarationPredicate.create {
val annotationFqNames = noArgAnnotationFqNames.map { FqName(it) }
annotated(annotationFqNames) or metaAnnotated(annotationFqNames)
}
+2 -2
View File
@@ -7,8 +7,8 @@ class Outer {
fun local() {
@NoArg
class Local(val l: Any) {
class <!NOARG_ON_LOCAL_CLASS_ERROR!>Local<!>(val l: Any) {
@NoArg
inner class InnerLocal(val x: Any)
inner class <!NOARG_ON_INNER_CLASS_ERROR!>InnerLocal<!>(val x: Any)
}
}
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
import org.jetbrains.kotlin.fir.extensions.predicate.annotated
import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.resolve.defaultType
@@ -46,7 +46,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
class FirParcelizeDeclarationGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
companion object {
private val PREDICATE = annotated(PARCELIZE_FQN, OLD_PARCELIZE_FQN)
private val PREDICATE = LookupPredicate.create { annotated(PARCELIZE_FQN, OLD_PARCELIZE_FQN) }
private val parcelizeMethodsNames = setOf(DESCRIBE_CONTENTS_NAME, WRITE_TO_PARCEL_NAME)
}