From f34061acc133b4bd2d44c0477fe4f8d9a3b42c62 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 24 May 2022 09:18:05 +0300 Subject: [PATCH] [FIR] Fix resolution of plugin annotations annotated with meta annotations There was a problem, that after founding of new annotation with meta annotation we did not come back to previous files, which may contain declarations with this new annotation --- ...DesignatedAnnotationsResolveTransformed.kt | 5 +- ...erRequiredAnnotationsResolveTransformer.kt | 57 ++++++++++++++----- .../diagnostics/status/metaAnnotation.fir.txt | 3 +- .../diagnostics/status/metaAnnotation.kt | 7 ++- 4 files changed, 52 insertions(+), 20 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirDesignatedAnnotationsResolveTransformed.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirDesignatedAnnotationsResolveTransformed.kt index 74da3fad396..10545cbcaa2 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirDesignatedAnnotationsResolveTransformed.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirDesignatedAnnotationsResolveTransformed.kt @@ -11,7 +11,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeB import org.jetbrains.kotlin.analysis.low.level.api.fir.util.ensurePhase import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredAnnotationsResolveTransformer @@ -25,7 +24,7 @@ internal class LLFirDesignatedAnnotationsResolveTransformed( if (!designationIterator.hasNext()) { val declaration = designation.declaration if (declaration is FirRegularClass || declaration is FirTypeAlias) { - declaration.transform(this, ResolutionMode.ContextIndependent) + declaration.transform(this, Mode.RegularAnnotations) } return } @@ -71,4 +70,4 @@ internal class LLFirDesignatedAnnotationsResolveTransformed( } } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt index 2ca97a145f8..11f8a9de424 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt @@ -24,9 +24,11 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.fqName import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals import org.jetbrains.kotlin.fir.resolve.transformers.* +import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredAnnotationsResolveTransformer.Mode import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.FirUserTypeRef import org.jetbrains.kotlin.fir.types.coneTypeSafe +import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -37,8 +39,20 @@ import org.jetbrains.kotlin.name.StandardClassIds.Annotations.WasExperimental class FirCompilerRequiredAnnotationsResolveProcessor( session: FirSession, scopeSession: ScopeSession -) : FirTransformerBasedResolveProcessor(session, scopeSession) { - override val transformer = FirCompilerRequiredAnnotationsResolveTransformer(session, scopeSession) +) : FirGlobalResolveProcessor(session, scopeSession) { + + override fun process(files: Collection) { + val transformer = FirCompilerRequiredAnnotationsResolveTransformer(session, scopeSession) + val registeredPluginAnnotations = session.registeredPluginAnnotations + if (!registeredPluginAnnotations.hasRegisteredAnnotations) { + files.forEach { it.transformSingle(transformer, Mode.RegularAnnotations) } + return + } + if (registeredPluginAnnotations.metaAnnotations.isNotEmpty()) { + files.forEach { it.transformSingle(transformer, Mode.MetaAnnotations) } + } + files.forEach { it.transformSingle(transformer, Mode.RegularAnnotations) } + } @OptIn(FirSymbolProviderInternals::class) override fun beforePhase() { @@ -54,42 +68,56 @@ class FirCompilerRequiredAnnotationsResolveProcessor( open class FirCompilerRequiredAnnotationsResolveTransformer( final override val session: FirSession, scopeSession: ScopeSession -) : FirAbstractPhaseTransformer(COMPILER_REQUIRED_ANNOTATIONS) { +) : FirAbstractPhaseTransformer(COMPILER_REQUIRED_ANNOTATIONS) { + enum class Mode { + MetaAnnotations, + RegularAnnotations + } + private val annotationTransformer = FirAnnotationResolveTransformer(session, scopeSession) private val importTransformer = FirPartialImportResolveTransformer(session) val extensionService = session.extensionService - override fun transformElement(element: E, data: Any?): E { + override fun transformElement(element: E, data: Mode): E { throw IllegalStateException("Should not be here") } - override fun transformFile(file: FirFile, data: Any?): FirFile { + override fun transformFile(file: FirFile, data: Mode): FirFile { checkSessionConsistency(file) val registeredPluginAnnotations = session.registeredPluginAnnotations - val newAnnotations = file.resolveAnnotations(registeredPluginAnnotations.annotations, registeredPluginAnnotations.metaAnnotations) + val regularAnnotations: Set + val metaAnnotations: Set + when (data) { + Mode.MetaAnnotations -> { + regularAnnotations = emptySet() + metaAnnotations = registeredPluginAnnotations.metaAnnotations + } + Mode.RegularAnnotations -> { + regularAnnotations = registeredPluginAnnotations.annotations + metaAnnotations = emptySet() + } + } + + val newAnnotations = file.resolveAnnotations(regularAnnotations, metaAnnotations) if (!newAnnotations.isEmpty) { for (metaAnnotation in newAnnotations.keySet()) { registeredPluginAnnotations.registerUserDefinedAnnotation(metaAnnotation, newAnnotations[metaAnnotation]) } - val newAnnotationsFqns = newAnnotations.values().mapTo(mutableSetOf()) { it.symbol.classId.asSingleFqName() } - file.resolveAnnotations(newAnnotationsFqns, emptySet()) } return file } - fun withFile(file: FirFile, f: () -> T): T = annotationTransformer.withFile(file, f) - fun withFileAndScopes(file: FirFile, f: () -> T): T { annotationTransformer.withFile(file) { return annotationTransformer.withFileScopes(file, f) } } - override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): FirStatement { + override fun transformRegularClass(regularClass: FirRegularClass, data: Mode): FirStatement { return annotationTransformer.transformRegularClass(regularClass, LinkedHashMultimap.create()) } - override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Any?): FirStatement { + override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Mode): FirStatement { return annotationTransformer.transformTypeAlias(typeAlias, LinkedHashMultimap.create()) } @@ -97,10 +125,11 @@ open class FirCompilerRequiredAnnotationsResolveTransformer( annotations: Set, metaAnnotations: Set ): Multimap { - importTransformer.acceptableFqNames = annotations + val acceptableNames = annotations + metaAnnotations + importTransformer.acceptableFqNames = acceptableNames this.transformImports(importTransformer, null) - annotationTransformer.acceptableFqNames = annotations + annotationTransformer.acceptableFqNames = acceptableNames annotationTransformer.metaAnnotations = metaAnnotations val newAnnotations = LinkedHashMultimap.create() this.transform>(annotationTransformer, newAnnotations) diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/status/metaAnnotation.fir.txt b/plugins/fir-plugin-prototype/testData/diagnostics/status/metaAnnotation.fir.txt index f8d192c84a5..311a322feb3 100644 --- a/plugins/fir-plugin-prototype/testData/diagnostics/status/metaAnnotation.fir.txt +++ b/plugins/fir-plugin-prototype/testData/diagnostics/status/metaAnnotation.fir.txt @@ -1,4 +1,4 @@ -FILE: metaAnnotation.kt +FILE: first.kt @R|Open|() public open class A : R|kotlin/Any| { public constructor(): R|A| { super() @@ -17,6 +17,7 @@ FILE: metaAnnotation.kt } } +FILE: second.kt @R|org/jetbrains/kotlin/fir/plugin/AllOpen|() public open annotation class Open : R|kotlin/Annotation| { public constructor(): R|Open| { super() diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/status/metaAnnotation.kt b/plugins/fir-plugin-prototype/testData/diagnostics/status/metaAnnotation.kt index 389a2d89434..280bcecc32a 100644 --- a/plugins/fir-plugin-prototype/testData/diagnostics/status/metaAnnotation.kt +++ b/plugins/fir-plugin-prototype/testData/diagnostics/status/metaAnnotation.kt @@ -1,4 +1,4 @@ -import org.jetbrains.kotlin.fir.plugin.AllOpen +// FILE: first.kt @Open class A { @@ -14,5 +14,8 @@ class B : A() { } } +// FILE: second.kt +import org.jetbrains.kotlin.fir.plugin.AllOpen + @AllOpen -annotation class Open \ No newline at end of file +annotation class Open