[FIR] Add stage for resolving annotations from plugins
This commit is contained in:
+7
-8
@@ -138,19 +138,18 @@ class FirExtensionPointService(
|
||||
}
|
||||
}
|
||||
|
||||
private val FirAnnotationCall.fqName: FqName?
|
||||
get() {
|
||||
val symbol = session.firSymbolProvider.getSymbolByTypeRef<FirRegularClassSymbol>(annotationTypeRef) ?: return null
|
||||
return symbol.classId.asSingleFqName()
|
||||
}
|
||||
|
||||
private fun collectExtensions(result: MutableSet<P>, declaration: FirAnnotationContainer, extensions: Multimap<AnnotationFqn, P>) {
|
||||
for (annotation in declaration.annotations) {
|
||||
val fqName = annotation.fqName ?: continue
|
||||
val fqName = annotation.fqName(session) ?: continue
|
||||
result += extensions[fqName]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val FirSession.extensionPointService: FirExtensionPointService by FirSession.sessionComponentAccessor()
|
||||
val FirSession.extensionPointService: FirExtensionPointService by FirSession.sessionComponentAccessor()
|
||||
|
||||
fun FirAnnotationCall.fqName(session: FirSession): FqName? {
|
||||
val symbol = session.firSymbolProvider.getSymbolByTypeRef<FirRegularClassSymbol>(annotationTypeRef) ?: return null
|
||||
return symbol.classId.asSingleFqName()
|
||||
}
|
||||
+9
-2
@@ -18,14 +18,16 @@ import org.jetbrains.kotlin.fir.visitors.compose
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
class FirImportResolveTransformer() : FirAbstractTreeTransformer<Nothing?>(phase = FirResolvePhase.IMPORTS) {
|
||||
open class FirImportResolveTransformer protected constructor(phase: FirResolvePhase) : FirAbstractTreeTransformer<Nothing?>(phase) {
|
||||
constructor() : this(FirResolvePhase.IMPORTS)
|
||||
|
||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
|
||||
private lateinit var symbolProvider: FirSymbolProvider
|
||||
|
||||
override lateinit var session: FirSession
|
||||
final override lateinit var session: FirSession
|
||||
|
||||
constructor(session: FirSession) : this() {
|
||||
this.session = session
|
||||
@@ -43,6 +45,8 @@ class FirImportResolveTransformer() : FirAbstractTreeTransformer<Nothing?>(phase
|
||||
override fun transformImport(import: FirImport, data: Nothing?): CompositeTransformResult<FirImport> {
|
||||
val fqName = import.importedFqName?.takeUnless { it.isRoot } ?: return import.compose()
|
||||
|
||||
if (!fqName.isAcceptable) return import.compose()
|
||||
|
||||
if (import.isAllUnder) {
|
||||
return transformImportForFqName(fqName, import)
|
||||
}
|
||||
@@ -51,6 +55,9 @@ class FirImportResolveTransformer() : FirAbstractTreeTransformer<Nothing?>(phase
|
||||
return transformImportForFqName(parentFqName, import)
|
||||
}
|
||||
|
||||
protected open val FqName.isAcceptable: Boolean
|
||||
get() = true
|
||||
|
||||
private fun transformImportForFqName(fqName: FqName, delegate: FirImport): CompositeTransformResult<FirImport> {
|
||||
val (packageFqName, relativeClassFqName) = resolveToPackageOrClass(symbolProvider, fqName) ?: return delegate.compose()
|
||||
return buildResolvedImport {
|
||||
|
||||
+2
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformerAdapter
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitTypeBodyResolveTransformerAdapter
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractResolveTransformerAdapter
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirPluginAnnotationsResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
|
||||
// TODO: add FirSession parameter
|
||||
@@ -18,6 +19,7 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
fun FirResolvePhase.createTransformerByPhase(scopeSession: ScopeSession): FirTransformer<Nothing?> {
|
||||
return when (this) {
|
||||
RAW_FIR -> throw AssertionError("Raw FIR building phase does not have a transformer")
|
||||
ANNOTATIONS_FOR_PLUGINS -> FirPluginAnnotationsResolveTransformer(scopeSession)
|
||||
IMPORTS -> FirImportResolveTransformer()
|
||||
SUPER_TYPES -> FirSupertypeResolverTransformer(scopeSession)
|
||||
SEALED_CLASS_INHERITORS -> FirSealedClassInheritorsTransformer()
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.resolve.transformers.plugin
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.withScopeCleanup
|
||||
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.compose
|
||||
|
||||
internal abstract class FirAbstractAnnotationResolveTransformer<D>(
|
||||
protected val session: FirSession,
|
||||
protected val scopeSession: ScopeSession
|
||||
) : FirDefaultTransformer<D>() {
|
||||
abstract override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: D): CompositeTransformResult<FirStatement>
|
||||
|
||||
protected val towerScope = FirCompositeScope(mutableListOf())
|
||||
|
||||
override fun transformFile(file: FirFile, data: D): CompositeTransformResult<FirDeclaration> {
|
||||
return withScopeCleanup(towerScope.scopes) {
|
||||
towerScope.addScopes(createImportingScopes(file, session, scopeSession))
|
||||
file.transformDeclarations(this, data)
|
||||
file.transformAnnotations(this, data).compose()
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformProperty(property: FirProperty, data: D): CompositeTransformResult<FirDeclaration> {
|
||||
return property.transformAnnotations(this, data).compose()
|
||||
}
|
||||
|
||||
override fun transformRegularClass(
|
||||
regularClass: FirRegularClass,
|
||||
data: D
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
regularClass.transformDeclarations(this, data)
|
||||
regularClass.transformCompanionObject(this, data)
|
||||
regularClass.transformSuperTypeRefs(this, data)
|
||||
return regularClass.transformAnnotations(this, data).compose()
|
||||
}
|
||||
|
||||
override fun transformSimpleFunction(
|
||||
simpleFunction: FirSimpleFunction,
|
||||
data: D
|
||||
): CompositeTransformResult<FirDeclaration> {
|
||||
simpleFunction.transformValueParameters(this, data)
|
||||
return simpleFunction.transformAnnotations(this, data).compose()
|
||||
}
|
||||
|
||||
override fun transformConstructor(
|
||||
constructor: FirConstructor,
|
||||
data: D
|
||||
): CompositeTransformResult<FirDeclaration> {
|
||||
constructor.transformValueParameters(this, data)
|
||||
return constructor.transformAnnotations(this, data).compose()
|
||||
}
|
||||
|
||||
override fun transformValueParameter(
|
||||
valueParameter: FirValueParameter,
|
||||
data: D
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return valueParameter.transformAnnotations(this, data).compose()
|
||||
}
|
||||
|
||||
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: D): CompositeTransformResult<FirDeclaration> {
|
||||
return typeAlias.transformAnnotations(this, data).compose()
|
||||
}
|
||||
|
||||
override fun transformTypeRef(typeRef: FirTypeRef, data: D): CompositeTransformResult<FirTypeRef> {
|
||||
return typeRef.transformAnnotations(this, data).compose()
|
||||
}
|
||||
|
||||
override fun <E : FirElement> transformElement(element: E, data: D): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.resolve.transformers.plugin
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.extensions.AnnotationFqn
|
||||
import org.jetbrains.kotlin.fir.extensions.extensionPointService
|
||||
import org.jetbrains.kotlin.fir.extensions.fqName
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirSpecificTypeResolverTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.compose
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
class FirPluginAnnotationsResolveTransformer(private val scopeSession: ScopeSession) : FirTransformer<Nothing?>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
||||
throw IllegalStateException("Should not be here")
|
||||
}
|
||||
|
||||
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||
file.replaceResolvePhase(FirResolvePhase.ANNOTATIONS_FOR_PLUGINS)
|
||||
val extensionPointService = file.session.extensionPointService
|
||||
val newAnnotations = file.resolveAnnotations(extensionPointService.annotations, extensionPointService.metaAnnotations)
|
||||
if (newAnnotations.isNotEmpty()) {
|
||||
for (annotationClass in newAnnotations) {
|
||||
extensionPointService.registerUserDefinedAnnotation(annotationClass)
|
||||
}
|
||||
val newAnnotationsFqns = newAnnotations.mapTo(mutableSetOf()) { it.symbol.classId.asSingleFqName() }
|
||||
file.resolveAnnotations(newAnnotationsFqns, emptySet())
|
||||
}
|
||||
return file.compose()
|
||||
}
|
||||
|
||||
private fun FirFile.resolveAnnotations(
|
||||
annotations: Set<AnnotationFqn>,
|
||||
metaAnnotations: Set<AnnotationFqn>
|
||||
): Set<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)
|
||||
return newAnnotations
|
||||
}
|
||||
}
|
||||
|
||||
private class FirPartialImportResolveTransformer(
|
||||
private val acceptableFqNames: Set<FqName>
|
||||
) : FirImportResolveTransformer(FirResolvePhase.ANNOTATIONS_FOR_PLUGINS) {
|
||||
override val FqName.isAcceptable: Boolean
|
||||
get() = this in acceptableFqNames
|
||||
}
|
||||
|
||||
private class FirAnnotationResolveTransformer(
|
||||
private val metaAnnotations: Set<AnnotationFqn>,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
) : FirAbstractAnnotationResolveTransformer<MutableSet<FirRegularClass>>(session, scopeSession) {
|
||||
private val typeResolverTransformer: FirSpecificTypeResolverTransformer = FirSpecificTypeResolverTransformer(towerScope, session)
|
||||
|
||||
override fun transformAnnotationCall(
|
||||
annotationCall: FirAnnotationCall,
|
||||
data: MutableSet<FirRegularClass>
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return annotationCall.transformAnnotationTypeRef(typeResolverTransformer, null).compose()
|
||||
}
|
||||
|
||||
override fun transformRegularClass(
|
||||
regularClass: FirRegularClass,
|
||||
data: MutableSet<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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.declarations
|
||||
|
||||
enum class FirResolvePhase {
|
||||
RAW_FIR,
|
||||
ANNOTATIONS_FOR_PLUGINS, // run only if some extensions are registered
|
||||
IMPORTS,
|
||||
SUPER_TYPES,
|
||||
SEALED_CLASS_INHERITORS,
|
||||
@@ -19,6 +20,7 @@ enum class FirResolvePhase {
|
||||
val requiredToLaunch: FirResolvePhase
|
||||
get() = when (this) {
|
||||
RAW_FIR -> RAW_FIR
|
||||
IMPORTS -> RAW_FIR
|
||||
IMPLICIT_TYPES_BODY_RESOLVE, BODY_RESOLVE -> STATUS
|
||||
else -> values()[ordinal - 1]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user