[FIR] Fix collecting annotations with meta annotations

This commit is contained in:
Dmitriy Novozhilov
2020-04-29 12:58:05 +03:00
parent b52452ef84
commit 941e43a226
2 changed files with 36 additions and 28 deletions
@@ -88,22 +88,24 @@ class FirExtensionPointService(
)
}
fun registerUserDefinedAnnotation(annotation: FirRegularClass) {
require(annotation.classKind == ClassKind.ANNOTATION_CLASS)
val fqName = annotation.symbol.classId.asSingleFqName()
_annotations += fqName
val extensions = extensionsWithMetaAnnotations[fqName]
if (extensions.isEmpty()) return
for (extension in extensions) {
val registeredExtensions = this[extension::class]
fun registerUserDefinedAnnotation(metaAnnotation: AnnotationFqn, annotations: Collection<FirRegularClass>) {
for (annotation in annotations) {
require(annotation.classKind == ClassKind.ANNOTATION_CLASS)
val fqName = annotation.symbol.classId.asSingleFqName()
_annotations += fqName
val extensions = extensionsWithMetaAnnotations[metaAnnotation]
if (extensions.isEmpty()) return
for (extension in extensions) {
val registeredExtensions = this[extension::class]
@Suppress("UNCHECKED_CAST")
val map = when (extension.mode) {
FirExtensionPoint.Mode.ANNOTATED_ELEMENT -> registeredExtensions.extensionsWithAnnotatedMode
FirExtensionPoint.Mode.ALL_IN_ANNOTATED_ELEMENT -> registeredExtensions.extensionsWithAllInAnnotatedMode
FirExtensionPoint.Mode.ALL -> throw IllegalStateException("Extension with mode ALL can't be subscribed to meta annotation")
} as Multimap<AnnotationFqn, FirExtensionPoint>
map.put(fqName, extension)
@Suppress("UNCHECKED_CAST")
val map = when (extension.mode) {
FirExtensionPoint.Mode.ANNOTATED_ELEMENT -> registeredExtensions.extensionsWithAnnotatedMode
FirExtensionPoint.Mode.ALL_IN_ANNOTATED_ELEMENT -> registeredExtensions.extensionsWithAllInAnnotatedMode
FirExtensionPoint.Mode.ALL -> throw IllegalStateException("Extension with mode ALL can't be subscribed to meta annotation")
} as Multimap<AnnotationFqn, FirExtensionPoint>
map.put(fqName, extension)
}
}
}
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.fir.resolve.transformers.plugin
import com.google.common.collect.LinkedHashMultimap
import com.google.common.collect.Multimap
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
@@ -33,11 +35,11 @@ class FirPluginAnnotationsResolveTransformer(private val scopeSession: ScopeSess
if (!extensionPointService.hasExtensions) return file.compose()
file.replaceResolvePhase(FirResolvePhase.ANNOTATIONS_FOR_PLUGINS)
val newAnnotations = file.resolveAnnotations(extensionPointService.annotations, extensionPointService.metaAnnotations)
if (newAnnotations.isNotEmpty()) {
for (annotationClass in newAnnotations) {
extensionPointService.registerUserDefinedAnnotation(annotationClass)
if (!newAnnotations.isEmpty) {
for (metaAnnotation in newAnnotations.keySet()) {
extensionPointService.registerUserDefinedAnnotation(metaAnnotation, newAnnotations[metaAnnotation])
}
val newAnnotationsFqns = newAnnotations.mapTo(mutableSetOf()) { it.symbol.classId.asSingleFqName() }
val newAnnotationsFqns = newAnnotations.values().mapTo(mutableSetOf()) { it.symbol.classId.asSingleFqName() }
file.resolveAnnotations(newAnnotationsFqns, emptySet())
}
return file.compose()
@@ -46,13 +48,13 @@ class FirPluginAnnotationsResolveTransformer(private val scopeSession: ScopeSess
private fun FirFile.resolveAnnotations(
annotations: Set<AnnotationFqn>,
metaAnnotations: Set<AnnotationFqn>
): Set<FirRegularClass> {
): Multimap<AnnotationFqn, FirRegularClass> {
val importTransformer = FirPartialImportResolveTransformer(annotations)
this.transform<FirFile, Nothing?>(importTransformer, null)
val annotationTransformer = FirAnnotationResolveTransformer(metaAnnotations, session, scopeSession)
val newAnnotations = mutableSetOf<FirRegularClass>()
this.transform<FirFile, MutableSet<FirRegularClass>>(annotationTransformer, newAnnotations)
val newAnnotations = LinkedHashMultimap.create<AnnotationFqn, FirRegularClass>()
this.transform<FirFile, Multimap<AnnotationFqn, FirRegularClass>>(annotationTransformer, newAnnotations)
return newAnnotations
}
}
@@ -68,25 +70,29 @@ private class FirAnnotationResolveTransformer(
private val metaAnnotations: Set<AnnotationFqn>,
session: FirSession,
scopeSession: ScopeSession
) : FirAbstractAnnotationResolveTransformer<MutableSet<FirRegularClass>>(session, scopeSession) {
private val typeResolverTransformer: FirSpecificTypeResolverTransformer = FirSpecificTypeResolverTransformer(towerScope, session)
) : FirAbstractAnnotationResolveTransformer<Multimap<AnnotationFqn, FirRegularClass>>(session, scopeSession) {
private val typeResolverTransformer: FirSpecificTypeResolverTransformer = FirSpecificTypeResolverTransformer(
towerScope,
session,
errorTypeAsResolved = false
)
override fun transformAnnotationCall(
annotationCall: FirAnnotationCall,
data: MutableSet<FirRegularClass>
data: Multimap<AnnotationFqn, FirRegularClass>
): CompositeTransformResult<FirStatement> {
return annotationCall.transformAnnotationTypeRef(typeResolverTransformer, null).compose()
}
override fun transformRegularClass(
regularClass: FirRegularClass,
data: MutableSet<FirRegularClass>
data: Multimap<AnnotationFqn, FirRegularClass>
): CompositeTransformResult<FirStatement> {
return super.transformRegularClass(regularClass, data).also {
if (regularClass.classKind == ClassKind.ANNOTATION_CLASS && metaAnnotations.isNotEmpty()) {
val annotations = regularClass.annotations.mapNotNull { it.fqName(session) }
if (annotations.any { it in metaAnnotations }) {
data += regularClass
for (annotation in annotations.filter { it in metaAnnotations }) {
data.put(annotation, regularClass)
}
}
}