[FIR] Add different modes for extensions and annotations
This commit is contained in:
@@ -17,9 +17,17 @@ abstract class FirExtensionPoint(val session: FirSession) {
|
|||||||
abstract val annotations: Set<AnnotationFqn>
|
abstract val annotations: Set<AnnotationFqn>
|
||||||
abstract val metaAnnotations: Set<AnnotationFqn>
|
abstract val metaAnnotations: Set<AnnotationFqn>
|
||||||
|
|
||||||
|
abstract val mode: Mode
|
||||||
|
|
||||||
fun interface Factory<P : FirExtensionPoint> {
|
fun interface Factory<P : FirExtensionPoint> {
|
||||||
fun create(session: FirSession): P
|
fun create(session: FirSession): P
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
ANNOTATED_ELEMENT,
|
||||||
|
ALL_IN_ANNOTATED_ELEMENT,
|
||||||
|
ALL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class FirExtensionPointName(val name: Name) {
|
data class FirExtensionPointName(val name: Name) {
|
||||||
|
|||||||
+64
-15
@@ -10,17 +10,26 @@ import com.google.common.collect.Multimap
|
|||||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.getSymbolByTypeRef
|
import org.jetbrains.kotlin.fir.resolve.getSymbolByTypeRef
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.utils.ComponentArrayOwner
|
import org.jetbrains.kotlin.fir.utils.ComponentArrayOwner
|
||||||
import org.jetbrains.kotlin.fir.utils.ComponentTypeRegistry
|
import org.jetbrains.kotlin.fir.utils.ComponentTypeRegistry
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
@Suppress("EXPERIMENTAL_FEATURE_WARNING")
|
class FirRegisteredExtension<P : FirExtensionPoint>(
|
||||||
inline class FirRegisteredExtension<P : FirExtensionPoint>(val extensions: Multimap<AnnotationFqn, P>)
|
val extensionsWithAllMode: List<P>,
|
||||||
|
val extensionsWithAnnotatedMode: Multimap<AnnotationFqn, P>,
|
||||||
|
val extensionsWithAllInAnnotatedMode: Multimap<AnnotationFqn, P>
|
||||||
|
) {
|
||||||
|
fun isEmpty(): Boolean {
|
||||||
|
return extensionsWithAllMode.isEmpty() && extensionsWithAnnotatedMode.isEmpty() && extensionsWithAllInAnnotatedMode.isEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FirExtensionPointService(
|
class FirExtensionPointService(
|
||||||
val session: FirSession
|
val session: FirSession
|
||||||
@@ -30,7 +39,7 @@ class FirExtensionPointService(
|
|||||||
val accessor = generateAccessor<V, P>(P::class)
|
val accessor = generateAccessor<V, P>(P::class)
|
||||||
return object : ReadOnlyProperty<FirExtensionPointService, ExtensionsAccessor<P>> {
|
return object : ReadOnlyProperty<FirExtensionPointService, ExtensionsAccessor<P>> {
|
||||||
override fun getValue(thisRef: FirExtensionPointService, property: KProperty<*>): ExtensionsAccessor<P> {
|
override fun getValue(thisRef: FirExtensionPointService, property: KProperty<*>): ExtensionsAccessor<P> {
|
||||||
return ExtensionsAccessor(thisRef.session, accessor.getValue(thisRef, property).extensions)
|
return ExtensionsAccessor(thisRef.session, accessor.getValue(thisRef, property))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,15 +52,35 @@ class FirExtensionPointService(
|
|||||||
|
|
||||||
fun <P : FirExtensionPoint> registerExtensions(extensionClass: KClass<P>, extensionFactories: List<FirExtensionPoint.Factory<P>>) {
|
fun <P : FirExtensionPoint> registerExtensions(extensionClass: KClass<P>, extensionFactories: List<FirExtensionPoint.Factory<P>>) {
|
||||||
val extensions = extensionFactories.map { it.create(session) }
|
val extensions = extensionFactories.map { it.create(session) }
|
||||||
val map = createMultimap<AnnotationFqn, P>()
|
|
||||||
|
val extensionsWithAllMode = mutableListOf<P>()
|
||||||
|
val extensionsWithAnnotatedMode = createMultimap<AnnotationFqn, P>()
|
||||||
|
val extensionsWithAllInAnnotatedMode = createMultimap<AnnotationFqn, P>()
|
||||||
for (extension in extensions) {
|
for (extension in extensions) {
|
||||||
_metaAnnotations += extension.metaAnnotations
|
_metaAnnotations += extension.metaAnnotations
|
||||||
for (annotation in extension.annotations) {
|
_annotations += extension.annotations
|
||||||
_annotations += annotation
|
when (extension.mode) {
|
||||||
map.put(annotation, extension)
|
FirExtensionPoint.Mode.ANNOTATED_ELEMENT -> {
|
||||||
|
for (annotation in extension.annotations) {
|
||||||
|
extensionsWithAnnotatedMode.put(annotation, extension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FirExtensionPoint.Mode.ALL_IN_ANNOTATED_ELEMENT -> {
|
||||||
|
for (annotation in extension.annotations) {
|
||||||
|
extensionsWithAllInAnnotatedMode.put(annotation, extension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FirExtensionPoint.Mode.ALL -> extensionsWithAllMode += extension
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registerComponent(extensionClass, FirRegisteredExtension(map))
|
registerComponent(
|
||||||
|
extensionClass,
|
||||||
|
FirRegisteredExtension(
|
||||||
|
extensionsWithAllMode,
|
||||||
|
extensionsWithAnnotatedMode,
|
||||||
|
extensionsWithAllInAnnotatedMode
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val annotations: Set<AnnotationFqn>
|
val annotations: Set<AnnotationFqn>
|
||||||
@@ -64,17 +93,37 @@ class FirExtensionPointService(
|
|||||||
|
|
||||||
class ExtensionsAccessor<P : FirExtensionPoint>(
|
class ExtensionsAccessor<P : FirExtensionPoint>(
|
||||||
private val session: FirSession,
|
private val session: FirSession,
|
||||||
private val extensions: Multimap<AnnotationFqn, P>
|
private val extensions: FirRegisteredExtension<P>
|
||||||
) {
|
) {
|
||||||
fun forDeclaration(declaration: FirAnnotationContainer): Collection<P> {
|
fun forDeclaration(declaration: FirAnnotationContainer, owners: Collection<FirAnnotationContainer>): Collection<P> {
|
||||||
if (declaration.annotations.isEmpty()) return emptySet()
|
if (extensions.isEmpty()) return emptySet()
|
||||||
val result = mutableSetOf<P>()
|
if (
|
||||||
|
(declaration.annotations.isEmpty() || extensions.extensionsWithAnnotatedMode.isEmpty) &&
|
||||||
|
extensions.extensionsWithAllInAnnotatedMode.isEmpty
|
||||||
|
) {
|
||||||
|
return extensions.extensionsWithAllMode
|
||||||
|
}
|
||||||
|
|
||||||
|
return LinkedHashSet(extensions.extensionsWithAllMode).apply {
|
||||||
|
collectExtensions(this, declaration, extensions.extensionsWithAnnotatedMode)
|
||||||
|
collectExtensions(this, declaration, extensions.extensionsWithAllInAnnotatedMode)
|
||||||
|
for (owner in owners) {
|
||||||
|
collectExtensions(this, owner, extensions.extensionsWithAllInAnnotatedMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val FirAnnotationCall.fqName: FqName?
|
||||||
|
get() {
|
||||||
|
val symbol = session.firSymbolProvider.getSymbolByTypeRef<FirRegularClassSymbol>(annotationTypeRef) ?: return null
|
||||||
|
return symbol.classId.asSingleFqName()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectExtensions(result: MutableSet<P>, declaration: FirAnnotationContainer, extensions: Multimap<AnnotationFqn, P>) {
|
||||||
for (annotation in declaration.annotations) {
|
for (annotation in declaration.annotations) {
|
||||||
val symbol = session.firSymbolProvider.getSymbolByTypeRef<FirRegularClassSymbol>(annotation.annotationTypeRef) ?: continue
|
val fqName = annotation.fqName ?: continue
|
||||||
val fqName = symbol.classId.asSingleFqName()
|
|
||||||
result += extensions[fqName]
|
result += extensions[fqName]
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -174,7 +174,7 @@ private class FirStatusResolveTransformer(
|
|||||||
|
|
||||||
private fun <D> prepareStatus(declaration: D, status: FirDeclarationStatus): FirDeclarationStatus where D : FirDeclaration, D : FirAnnotationContainer {
|
private fun <D> prepareStatus(declaration: D, status: FirDeclarationStatus): FirDeclarationStatus where D : FirDeclaration, D : FirAnnotationContainer {
|
||||||
var result = status
|
var result = status
|
||||||
session.extensionPointService.statusTransformerExtensions.forDeclaration(declaration).forEach {
|
session.extensionPointService.statusTransformerExtensions.forDeclaration(declaration, classes).forEach {
|
||||||
result = it.transformStatus(declaration, status)
|
result = it.transformStatus(declaration, status)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user