FIR: Add IDE implementation for FirRegisteredPluginAnnotations
It works on `KotlinAnnotationsResolver`, which means that it uses PSI indices to search for the annotations
This commit is contained in:
+66
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.analysis.providers.KotlinAnnotationsResolver
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.caches.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.AbstractFirRegisteredPluginAnnotations
|
||||||
|
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
|
|
||||||
|
internal class LLFirIdeRegisteredPluginAnnotations(
|
||||||
|
session: FirSession,
|
||||||
|
private val annotationsResolver: KotlinAnnotationsResolver
|
||||||
|
) : AbstractFirRegisteredPluginAnnotations(session) {
|
||||||
|
|
||||||
|
private val annotationsFromPlugins: MutableSet<AnnotationFqn> = mutableSetOf()
|
||||||
|
|
||||||
|
override val annotations: Set<AnnotationFqn>
|
||||||
|
get() = allAnnotationsCache.getValue()
|
||||||
|
|
||||||
|
private val allAnnotationsCache: FirLazyValue<Set<AnnotationFqn>, Nothing?> = session.firCachesFactory.createLazyValue {
|
||||||
|
// at this point, both metaAnnotations and annotationsFromPlugins should be collected
|
||||||
|
val result = metaAnnotations.flatMapTo(mutableSetOf()) { getAnnotationsWithMetaAnnotation(it) }
|
||||||
|
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
annotationsFromPlugins
|
||||||
|
} else {
|
||||||
|
result += annotationsFromPlugins
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MetaAnnotation -> Annotations
|
||||||
|
private val annotationsWithMetaAnnotationCache: FirCache<AnnotationFqn, Set<AnnotationFqn>, Nothing?> =
|
||||||
|
session.firCachesFactory.createCache { metaAnnotation -> collectAnnotationsWithMetaAnnotation(metaAnnotation) }
|
||||||
|
|
||||||
|
override fun getAnnotationsWithMetaAnnotation(metaAnnotation: AnnotationFqn): Collection<AnnotationFqn> {
|
||||||
|
return annotationsWithMetaAnnotationCache.getValue(metaAnnotation)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectAnnotationsWithMetaAnnotation(metaAnnotation: AnnotationFqn): Set<FqName> {
|
||||||
|
val annotatedDeclarations = annotationsResolver.declarationsByAnnotation(ClassId.topLevel(metaAnnotation))
|
||||||
|
|
||||||
|
return annotatedDeclarations
|
||||||
|
.asSequence()
|
||||||
|
.filterIsInstance<KtClass>()
|
||||||
|
.filter { it.isAnnotation() && it.isTopLevel() }
|
||||||
|
.mapNotNull { it.fqName }
|
||||||
|
.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun saveAnnotationsFromPlugin(annotations: Collection<AnnotationFqn>) {
|
||||||
|
annotationsFromPlugins += annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerUserDefinedAnnotation(metaAnnotation: AnnotationFqn, annotationClasses: Collection<FirRegularClass>) {
|
||||||
|
error("This method should never be called in IDE mode")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user