diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionPoint.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionPoint.kt index f5dec2ecebe..ce67c2ad451 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionPoint.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionPoint.kt @@ -17,9 +17,17 @@ abstract class FirExtensionPoint(val session: FirSession) { abstract val annotations: Set abstract val metaAnnotations: Set + abstract val mode: Mode + fun interface Factory

{ fun create(session: FirSession): P } + + enum class Mode { + ANNOTATED_ELEMENT, + ALL_IN_ANNOTATED_ELEMENT, + ALL + } } data class FirExtensionPointName(val name: Name) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionPointService.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionPointService.kt index 3e65f8fb63a..db5e1b070bc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionPointService.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionPointService.kt @@ -10,17 +10,26 @@ import com.google.common.collect.Multimap import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirSession 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.getSymbolByTypeRef import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.utils.ComponentArrayOwner import org.jetbrains.kotlin.fir.utils.ComponentTypeRegistry +import org.jetbrains.kotlin.name.FqName import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KClass import kotlin.reflect.KProperty -@Suppress("EXPERIMENTAL_FEATURE_WARNING") -inline class FirRegisteredExtension

(val extensions: Multimap) +class FirRegisteredExtension

( + val extensionsWithAllMode: List

, + val extensionsWithAnnotatedMode: Multimap, + val extensionsWithAllInAnnotatedMode: Multimap +) { + fun isEmpty(): Boolean { + return extensionsWithAllMode.isEmpty() && extensionsWithAnnotatedMode.isEmpty() && extensionsWithAllInAnnotatedMode.isEmpty() + } +} class FirExtensionPointService( val session: FirSession @@ -30,7 +39,7 @@ class FirExtensionPointService( val accessor = generateAccessor(P::class) return object : ReadOnlyProperty> { override fun getValue(thisRef: FirExtensionPointService, property: KProperty<*>): ExtensionsAccessor

{ - return ExtensionsAccessor(thisRef.session, accessor.getValue(thisRef, property).extensions) + return ExtensionsAccessor(thisRef.session, accessor.getValue(thisRef, property)) } } } @@ -43,15 +52,35 @@ class FirExtensionPointService( fun

registerExtensions(extensionClass: KClass

, extensionFactories: List>) { val extensions = extensionFactories.map { it.create(session) } - val map = createMultimap() + + val extensionsWithAllMode = mutableListOf

() + val extensionsWithAnnotatedMode = createMultimap() + val extensionsWithAllInAnnotatedMode = createMultimap() for (extension in extensions) { _metaAnnotations += extension.metaAnnotations - for (annotation in extension.annotations) { - _annotations += annotation - map.put(annotation, extension) + _annotations += extension.annotations + when (extension.mode) { + 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 @@ -64,17 +93,37 @@ class FirExtensionPointService( class ExtensionsAccessor

( private val session: FirSession, - private val extensions: Multimap + private val extensions: FirRegisteredExtension

) { - fun forDeclaration(declaration: FirAnnotationContainer): Collection

{ - if (declaration.annotations.isEmpty()) return emptySet() - val result = mutableSetOf

() + fun forDeclaration(declaration: FirAnnotationContainer, owners: Collection): Collection

{ + if (extensions.isEmpty()) return emptySet() + 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(annotationTypeRef) ?: return null + return symbol.classId.asSingleFqName() + } + + private fun collectExtensions(result: MutableSet

, declaration: FirAnnotationContainer, extensions: Multimap) { for (annotation in declaration.annotations) { - val symbol = session.firSymbolProvider.getSymbolByTypeRef(annotation.annotationTypeRef) ?: continue - val fqName = symbol.classId.asSingleFqName() + val fqName = annotation.fqName ?: continue result += extensions[fqName] } - return result } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt index a13b1e23d71..20e4ccfb2ee 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt @@ -174,7 +174,7 @@ private class FirStatusResolveTransformer( private fun prepareStatus(declaration: D, status: FirDeclarationStatus): FirDeclarationStatus where D : FirDeclaration, D : FirAnnotationContainer { var result = status - session.extensionPointService.statusTransformerExtensions.forDeclaration(declaration).forEach { + session.extensionPointService.statusTransformerExtensions.forDeclaration(declaration, classes).forEach { result = it.transformStatus(declaration, status) } return result