[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) { fun registerUserDefinedAnnotation(metaAnnotation: AnnotationFqn, annotations: Collection<FirRegularClass>) {
require(annotation.classKind == ClassKind.ANNOTATION_CLASS) for (annotation in annotations) {
val fqName = annotation.symbol.classId.asSingleFqName() require(annotation.classKind == ClassKind.ANNOTATION_CLASS)
_annotations += fqName val fqName = annotation.symbol.classId.asSingleFqName()
val extensions = extensionsWithMetaAnnotations[fqName] _annotations += fqName
if (extensions.isEmpty()) return val extensions = extensionsWithMetaAnnotations[metaAnnotation]
for (extension in extensions) { if (extensions.isEmpty()) return
val registeredExtensions = this[extension::class] for (extension in extensions) {
val registeredExtensions = this[extension::class]
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val map = when (extension.mode) { val map = when (extension.mode) {
FirExtensionPoint.Mode.ANNOTATED_ELEMENT -> registeredExtensions.extensionsWithAnnotatedMode FirExtensionPoint.Mode.ANNOTATED_ELEMENT -> registeredExtensions.extensionsWithAnnotatedMode
FirExtensionPoint.Mode.ALL_IN_ANNOTATED_ELEMENT -> registeredExtensions.extensionsWithAllInAnnotatedMode FirExtensionPoint.Mode.ALL_IN_ANNOTATED_ELEMENT -> registeredExtensions.extensionsWithAllInAnnotatedMode
FirExtensionPoint.Mode.ALL -> throw IllegalStateException("Extension with mode ALL can't be subscribed to meta annotation") FirExtensionPoint.Mode.ALL -> throw IllegalStateException("Extension with mode ALL can't be subscribed to meta annotation")
} as Multimap<AnnotationFqn, FirExtensionPoint> } as Multimap<AnnotationFqn, FirExtensionPoint>
map.put(fqName, extension) map.put(fqName, extension)
}
} }
} }
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.fir.resolve.transformers.plugin 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.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
@@ -33,11 +35,11 @@ class FirPluginAnnotationsResolveTransformer(private val scopeSession: ScopeSess
if (!extensionPointService.hasExtensions) return file.compose() if (!extensionPointService.hasExtensions) return file.compose()
file.replaceResolvePhase(FirResolvePhase.ANNOTATIONS_FOR_PLUGINS) file.replaceResolvePhase(FirResolvePhase.ANNOTATIONS_FOR_PLUGINS)
val newAnnotations = file.resolveAnnotations(extensionPointService.annotations, extensionPointService.metaAnnotations) val newAnnotations = file.resolveAnnotations(extensionPointService.annotations, extensionPointService.metaAnnotations)
if (newAnnotations.isNotEmpty()) { if (!newAnnotations.isEmpty) {
for (annotationClass in newAnnotations) { for (metaAnnotation in newAnnotations.keySet()) {
extensionPointService.registerUserDefinedAnnotation(annotationClass) 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()) file.resolveAnnotations(newAnnotationsFqns, emptySet())
} }
return file.compose() return file.compose()
@@ -46,13 +48,13 @@ class FirPluginAnnotationsResolveTransformer(private val scopeSession: ScopeSess
private fun FirFile.resolveAnnotations( private fun FirFile.resolveAnnotations(
annotations: Set<AnnotationFqn>, annotations: Set<AnnotationFqn>,
metaAnnotations: Set<AnnotationFqn> metaAnnotations: Set<AnnotationFqn>
): Set<FirRegularClass> { ): Multimap<AnnotationFqn, FirRegularClass> {
val importTransformer = FirPartialImportResolveTransformer(annotations) val importTransformer = FirPartialImportResolveTransformer(annotations)
this.transform<FirFile, Nothing?>(importTransformer, null) this.transform<FirFile, Nothing?>(importTransformer, null)
val annotationTransformer = FirAnnotationResolveTransformer(metaAnnotations, session, scopeSession) val annotationTransformer = FirAnnotationResolveTransformer(metaAnnotations, session, scopeSession)
val newAnnotations = mutableSetOf<FirRegularClass>() val newAnnotations = LinkedHashMultimap.create<AnnotationFqn, FirRegularClass>()
this.transform<FirFile, MutableSet<FirRegularClass>>(annotationTransformer, newAnnotations) this.transform<FirFile, Multimap<AnnotationFqn, FirRegularClass>>(annotationTransformer, newAnnotations)
return newAnnotations return newAnnotations
} }
} }
@@ -68,25 +70,29 @@ private class FirAnnotationResolveTransformer(
private val metaAnnotations: Set<AnnotationFqn>, private val metaAnnotations: Set<AnnotationFqn>,
session: FirSession, session: FirSession,
scopeSession: ScopeSession scopeSession: ScopeSession
) : FirAbstractAnnotationResolveTransformer<MutableSet<FirRegularClass>>(session, scopeSession) { ) : FirAbstractAnnotationResolveTransformer<Multimap<AnnotationFqn, FirRegularClass>>(session, scopeSession) {
private val typeResolverTransformer: FirSpecificTypeResolverTransformer = FirSpecificTypeResolverTransformer(towerScope, session) private val typeResolverTransformer: FirSpecificTypeResolverTransformer = FirSpecificTypeResolverTransformer(
towerScope,
session,
errorTypeAsResolved = false
)
override fun transformAnnotationCall( override fun transformAnnotationCall(
annotationCall: FirAnnotationCall, annotationCall: FirAnnotationCall,
data: MutableSet<FirRegularClass> data: Multimap<AnnotationFqn, FirRegularClass>
): CompositeTransformResult<FirStatement> { ): CompositeTransformResult<FirStatement> {
return annotationCall.transformAnnotationTypeRef(typeResolverTransformer, null).compose() return annotationCall.transformAnnotationTypeRef(typeResolverTransformer, null).compose()
} }
override fun transformRegularClass( override fun transformRegularClass(
regularClass: FirRegularClass, regularClass: FirRegularClass,
data: MutableSet<FirRegularClass> data: Multimap<AnnotationFqn, FirRegularClass>
): CompositeTransformResult<FirStatement> { ): CompositeTransformResult<FirStatement> {
return super.transformRegularClass(regularClass, data).also { return super.transformRegularClass(regularClass, data).also {
if (regularClass.classKind == ClassKind.ANNOTATION_CLASS && metaAnnotations.isNotEmpty()) { if (regularClass.classKind == ClassKind.ANNOTATION_CLASS && metaAnnotations.isNotEmpty()) {
val annotations = regularClass.annotations.mapNotNull { it.fqName(session) } val annotations = regularClass.annotations.mapNotNull { it.fqName(session) }
if (annotations.any { it in metaAnnotations }) { for (annotation in annotations.filter { it in metaAnnotations }) {
data += regularClass data.put(annotation, regularClass)
} }
} }
} }