[FIR] Move base FirExtension infrastructure to :fir:tree module

This is needed for type attribute extension which is used not only
  from :resolve module but also from :(de)serialization modules
This commit is contained in:
Dmitriy Novozhilov
2021-09-30 12:43:22 +03:00
committed by TeamCityServer
parent e26cd74b16
commit 32709151c3
4 changed files with 7 additions and 7 deletions
@@ -0,0 +1,42 @@
/*
* 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
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirPluginKey
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import kotlin.reflect.KClass
typealias AnnotationFqn = FqName
/*
* Accessing extensions
*
* - specific extension -> all extension instances: extension accessor on `FirExtensionService`
* - all declarations matching extension with predicate -> FirPredicateBasedProvider.getSymbolsByPredicate
* - all specific extensions interested in specific declaration -> TODO with StateMachine
*/
abstract class FirExtension(val session: FirSession) {
abstract val name: FirExtensionPointName
abstract val key: FirPluginKey
abstract val extensionType: KClass<out FirExtension>
fun interface Factory<out P : FirExtension> {
fun create(session: FirSession): P
}
}
abstract class FirPredicateBasedExtension(session: FirSession) : FirExtension(session) {
abstract val predicate: DeclarationPredicate
}
data class FirExtensionPointName(val name: Name) {
constructor(name: String) : this(Name.identifier(name))
}
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2020 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
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.NoMutableState
import org.jetbrains.kotlin.fir.utils.ArrayMapAccessor
import org.jetbrains.kotlin.fir.utils.ComponentArrayOwner
import org.jetbrains.kotlin.fir.utils.TypeRegistry
import kotlin.reflect.KClass
@RequiresOptIn
annotation class PluginServicesInitialization
@NoMutableState
class FirExtensionService(val session: FirSession) : ComponentArrayOwner<FirExtension, List<FirExtension>>(), FirSessionComponent {
companion object : TypeRegistry<FirExtension, List<FirExtension>>() {
inline fun <reified P : FirExtension, V : List<P>> registeredExtensions(): ArrayMapAccessor<FirExtension, List<FirExtension>, V> {
@Suppress("UNCHECKED_CAST")
return generateAccessor(P::class, default = emptyList<P>() as V)
}
fun <P : FirExtension, V : List<P>> registeredExtensions(kClass: KClass<P>): ArrayMapAccessor<FirExtension, List<FirExtension>, V> {
@Suppress("UNCHECKED_CAST")
return generateAccessor(kClass, default = emptyList<P>() as V)
}
}
override val typeRegistry: TypeRegistry<FirExtension, List<FirExtension>>
get() = Companion
var registeredExtensionsSize: Int = 0
private set
var registeredPredicateBasedExtensionsSize: Int = 0
private set
@PluginServicesInitialization
fun registerExtensions(extensionClass: KClass<out FirExtension>, extensionFactories: List<FirExtension.Factory<*>>) {
registeredExtensionsSize += extensionFactories.size
val extensions = extensionFactories.map { it.create(session) }
registeredPredicateBasedExtensionsSize += extensions.count { it is FirPredicateBasedExtension }
registerComponent(
extensionClass,
extensions
)
}
@PluginServicesInitialization
fun getAllExtensions(): List<FirExtension> {
return arrayMap.flatten()
}
}
val FirSession.extensionService: FirExtensionService by FirSession.sessionComponentAccessor()
val FirExtensionService.hasExtensions: Boolean
get() = registeredExtensionsSize > 0
val FirExtensionService.hasPredicateBasedExtensions: Boolean
get() = registeredPredicateBasedExtensionsSize > 0
@@ -0,0 +1,113 @@
/*
* 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
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
// -------------------------------------------- Predicates --------------------------------------------
sealed class DeclarationPredicate {
abstract val annotations: Set<AnnotationFqn>
abstract val metaAnnotations: Set<AnnotationFqn>
abstract fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R
object Any : DeclarationPredicate() {
override val annotations: Set<AnnotationFqn>
get() = emptySet()
override val metaAnnotations: Set<AnnotationFqn>
get() = emptySet()
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitAny(this, data)
}
}
class Or(val a: DeclarationPredicate, val b: DeclarationPredicate) : 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 {
return visitor.visitOr(this, data)
}
}
class And(val a: DeclarationPredicate, val b: DeclarationPredicate) : 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 {
return visitor.visitAnd(this, data)
}
}
}
sealed class Annotated(final override val annotations: Set<AnnotationFqn>) : DeclarationPredicate() {
init {
require(annotations.isNotEmpty()) {
"Annotations should be not empty"
}
}
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)
}
}
class AnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitAnnotatedWith(this, data)
}
}
class UnderAnnotatedWith(annotations: Set<AnnotationFqn>) : Annotated(annotations) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitUnderAnnotatedWith(this, data)
}
}
sealed class MetaAnnotated(final override val metaAnnotations: Set<AnnotationFqn>) : DeclarationPredicate() {
init {
require(metaAnnotations.isNotEmpty()) {
"Annotations should be not empty"
}
}
final override val annotations: Set<AnnotationFqn>
get() = emptySet()
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitMetaAnnotated(this, data)
}
}
class AnnotatedWithMeta(metaAnnotations: Set<AnnotationFqn>) : MetaAnnotated(metaAnnotations) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitAnnotatedWithMeta(this, data)
}
}
class UnderMetaAnnotated(metaAnnotations: Set<AnnotationFqn>) : MetaAnnotated(metaAnnotations) {
override fun <R, D> accept(visitor: DeclarationPredicateVisitor<R, D>, data: D): R {
return visitor.visitUnderMetaAnnotated(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)
fun under(vararg annotations: AnnotationFqn): DeclarationPredicate = UnderAnnotatedWith(annotations.toSet())
fun has(vararg annotations: AnnotationFqn): DeclarationPredicate = AnnotatedWith(annotations.toSet())
fun metaUnder(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = AnnotatedWithMeta(metaAnnotations.toSet())
fun metaHas(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = UnderMetaAnnotated(metaAnnotations.toSet())
fun hasOrUnder(vararg annotations: AnnotationFqn): DeclarationPredicate = has(*annotations) or under(*annotations)
fun metaHasOrUnder(vararg metaAnnotations: AnnotationFqn): DeclarationPredicate = metaHas(*metaAnnotations) or metaUnder(*metaAnnotations)
@@ -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 DeclarationPredicateVisitor<R, D> {
abstract fun visitPredicate(predicate: DeclarationPredicate, data: D): R
open fun visitAny(predicate: DeclarationPredicate.Any, data: D): R {
return visitPredicate(predicate, data)
}
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 visitUnderAnnotatedWith(predicate: UnderAnnotatedWith, data: D): R {
return visitAnnotated(predicate, data)
}
open fun visitMetaAnnotated(predicate: MetaAnnotated, data: D): R {
return visitPredicate(predicate, data)
}
open fun visitAnnotatedWithMeta(predicate: AnnotatedWithMeta, data: D): R {
return visitMetaAnnotated(predicate, data)
}
open fun visitUnderMetaAnnotated(predicate: UnderMetaAnnotated, data: D): R {
return visitMetaAnnotated(predicate, data)
}
}