[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:
committed by
TeamCityServer
parent
e26cd74b16
commit
32709151c3
@@ -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
|
||||
+113
@@ -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)
|
||||
+45
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user