[FIR] Add prototype of first generation phase

This commit is contained in:
Dmitriy Novozhilov
2020-04-29 11:36:00 +03:00
parent b31981619e
commit 728e0604ac
6 changed files with 181 additions and 3 deletions
@@ -0,0 +1,43 @@
/*
* 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.extensions
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
/*
* TODO:
* - add registration of new files
* - check that annotations or meta-annotations is not empty
*/
abstract class FirClassGenerationExtension(session: FirSession) : FirExtensionPoint(session) {
companion object {
val NAME = FirExtensionPointName("StatusTransformer")
}
final override val name: FirExtensionPointName
get() = NAME
final override val mode: Mode = Mode.ANNOTATED_ELEMENT
abstract fun <T> generateClass(
containingFile: FirFile,
annotatedDeclaration: T
): List<GeneratedClass> where T : FirDeclaration, T : FirAnnotationContainer
data class GeneratedClass(val klass: FirRegularClass, val container: FirDeclaration) {
init {
require(container is FirRegularClass || container is FirFile)
}
}
fun interface Factory : FirExtensionPoint.Factory<FirClassGenerationExtension>
}
val FirExtensionPointService.classGenerationExtensions: FirExtensionPointService.ExtensionsAccessor<FirClassGenerationExtension> by FirExtensionPointService.registeredExtensions()
@@ -15,9 +15,15 @@ abstract class FirExtensionRegistrar {
) )
protected inner class ExtensionRegistrarContext { protected inner class ExtensionRegistrarContext {
@JvmName("plusStatusTransformerExtension")
operator fun ((FirSession) -> FirStatusTransformerExtension).unaryPlus() { operator fun ((FirSession) -> FirStatusTransformerExtension).unaryPlus() {
statusTransformerExtensions += FirStatusTransformerExtension.Factory { this.invoke(it) } statusTransformerExtensions += FirStatusTransformerExtension.Factory { this.invoke(it) }
} }
@JvmName("plusClassGenerationExtension")
operator fun ((FirSession) -> FirClassGenerationExtension).unaryPlus() {
classGenerationExtensions += FirClassGenerationExtension.Factory { this.invoke(it) }
}
} }
protected abstract fun ExtensionRegistrarContext.configurePlugin() protected abstract fun ExtensionRegistrarContext.configurePlugin()
@@ -25,21 +31,25 @@ abstract class FirExtensionRegistrar {
fun configure(): RegisteredExtensions { fun configure(): RegisteredExtensions {
ExtensionRegistrarContext().configurePlugin() ExtensionRegistrarContext().configurePlugin()
return RegisteredExtensions( return RegisteredExtensions(
statusTransformerExtensions statusTransformerExtensions,
classGenerationExtensions
) )
} }
private val statusTransformerExtensions: MutableList<FirStatusTransformerExtension.Factory> = mutableListOf() private val statusTransformerExtensions: MutableList<FirStatusTransformerExtension.Factory> = mutableListOf()
private val classGenerationExtensions: MutableList<FirClassGenerationExtension.Factory> = mutableListOf()
class RegisteredExtensions( class RegisteredExtensions(
val statusTransformerExtensions: List<FirStatusTransformerExtension.Factory> val statusTransformerExtensions: List<FirStatusTransformerExtension.Factory>,
val classGenerationExtensions: List<FirClassGenerationExtension.Factory>
) { ) {
companion object { companion object {
val EMPTY = RegisteredExtensions(emptyList()) val EMPTY = RegisteredExtensions(emptyList(), emptyList())
} }
} }
} }
fun FirExtensionPointService.registerExtensions(extensions: FirExtensionRegistrar.RegisteredExtensions) { fun FirExtensionPointService.registerExtensions(extensions: FirExtensionRegistrar.RegisteredExtensions) {
registerExtensions(FirStatusTransformerExtension::class, extensions.statusTransformerExtensions) registerExtensions(FirStatusTransformerExtension::class, extensions.statusTransformerExtensions)
registerExtensions(FirClassGenerationExtension::class, extensions.classGenerationExtensions)
} }
@@ -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.FirBodyResolveTransformerAdapter
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitTypeBodyResolveTransformerAdapter 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.contracts.FirContractResolveTransformerAdapter
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirFirstGenerationTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirPluginAnnotationsResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirPluginAnnotationsResolveTransformer
import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirTransformer
@@ -20,6 +21,7 @@ fun FirResolvePhase.createTransformerByPhase(scopeSession: ScopeSession): FirTra
return when (this) { return when (this) {
RAW_FIR -> throw AssertionError("Raw FIR building phase does not have a transformer") RAW_FIR -> throw AssertionError("Raw FIR building phase does not have a transformer")
ANNOTATIONS_FOR_PLUGINS -> FirPluginAnnotationsResolveTransformer(scopeSession) ANNOTATIONS_FOR_PLUGINS -> FirPluginAnnotationsResolveTransformer(scopeSession)
FIRST_PLUGIN_GENERATION -> FirFirstGenerationTransformer()
IMPORTS -> FirImportResolveTransformer() IMPORTS -> FirImportResolveTransformer()
SUPER_TYPES -> FirSupertypeResolverTransformer(scopeSession) SUPER_TYPES -> FirSupertypeResolverTransformer(scopeSession)
SEALED_CLASS_INHERITORS -> FirSealedClassInheritorsTransformer() SEALED_CLASS_INHERITORS -> FirSealedClassInheritorsTransformer()
@@ -0,0 +1,104 @@
/*
* 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.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.extensions.FirClassGenerationExtension
import org.jetbrains.kotlin.fir.extensions.classGenerationExtensions
import org.jetbrains.kotlin.fir.extensions.extensionPointService
import org.jetbrains.kotlin.fir.extensions.hasExtensions
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
import org.jetbrains.kotlin.fir.visitors.compose
class FirFirstGenerationTransformer : FirDefaultTransformer<Nothing?>() {
private lateinit var session: FirSession
private val generatedDeclarations: MutableList<FirClassGenerationExtension.GeneratedClass> = mutableListOf()
private lateinit var file: FirFile
private val extensionPointService get() = session.extensionPointService
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirDeclaration> {
session = file.session
if (!extensionPointService.hasExtensions) return file.compose()
file.replaceResolvePhase(FirResolvePhase.FIRST_PLUGIN_GENERATION)
generatedDeclarations.clear()
this.file = file
file.transformDeclarations(this, data)
visitAnnotatedDeclaration(file)
addGeneratedClasses()
return file.compose()
}
private fun addGeneratedClasses() {
for ((generatedClass, owner) in generatedDeclarations) {
when (owner) {
is FirFile -> owner.addDeclaration(generatedClass)
is FirRegularClass -> owner.addDeclaration(generatedClass)
else -> throw IllegalStateException()
}
}
}
private fun <T> visitAnnotatedDeclaration(declaration: T) where T : FirDeclaration, T : FirAnnotationContainer {
val extensions = extensionPointService.classGenerationExtensions.forDeclaration(declaration, emptyList())
extensions.flatMapTo(generatedDeclarations) { it.generateClass(file, declaration) }
}
override fun transformProperty(property: FirProperty, data: Nothing?): CompositeTransformResult<FirDeclaration> {
visitAnnotatedDeclaration(property)
return property.compose()
}
override fun transformRegularClass(
regularClass: FirRegularClass,
data: Nothing?
): CompositeTransformResult<FirStatement> {
regularClass.transformDeclarations(this, data)
regularClass.transformCompanionObject(this, data)
visitAnnotatedDeclaration(regularClass)
return regularClass.compose()
}
override fun transformSimpleFunction(
simpleFunction: FirSimpleFunction,
data: Nothing?
): CompositeTransformResult<FirDeclaration> {
simpleFunction.transformValueParameters(this, data)
visitAnnotatedDeclaration(simpleFunction)
return simpleFunction.compose()
}
override fun transformConstructor(
constructor: FirConstructor,
data: Nothing?
): CompositeTransformResult<FirDeclaration> {
constructor.transformValueParameters(this, data)
visitAnnotatedDeclaration(constructor)
return constructor.compose()
}
override fun transformValueParameter(
valueParameter: FirValueParameter,
data: Nothing?
): CompositeTransformResult<FirStatement> {
visitAnnotatedDeclaration(valueParameter)
return valueParameter.compose()
}
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): CompositeTransformResult<FirDeclaration> {
visitAnnotatedDeclaration(typeAlias)
return typeAlias.compose()
}
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return element.compose()
}
}
@@ -9,6 +9,9 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.declarations.builder.AbstractFirRegularClassBuilder import org.jetbrains.kotlin.fir.declarations.builder.AbstractFirRegularClassBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirFileImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirSealedClassImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -16,6 +19,7 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeFlexibleType import org.jetbrains.kotlin.fir.types.ConeFlexibleType
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.fir.types.coneTypeSafe
import java.lang.IllegalStateException
fun FirTypeParameterBuilder.addDefaultBoundIfNecessary(isFlexible: Boolean = false) { fun FirTypeParameterBuilder.addDefaultBoundIfNecessary(isFlexible: Boolean = false) {
if (bounds.isEmpty()) { if (bounds.isEmpty()) {
@@ -90,3 +94,17 @@ fun FirRegularClass.collectEnumEntries(): Collection<FirEnumEntry> {
assert(classKind == ClassKind.ENUM_CLASS) assert(classKind == ClassKind.ENUM_CLASS)
return declarations.filterIsInstance<FirEnumEntry>() return declarations.filterIsInstance<FirEnumEntry>()
} }
fun FirFile.addDeclaration(declaration: FirDeclaration) {
require(this is FirFileImpl)
declarations += declaration
}
fun FirRegularClass.addDeclaration(declaration: FirDeclaration) {
@Suppress("LiftReturnOrAssignment")
when (this) {
is FirClassImpl -> declarations += declaration
is FirSealedClassImpl -> declarations += declaration
else -> throw IllegalStateException()
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.declarations
enum class FirResolvePhase { enum class FirResolvePhase {
RAW_FIR, RAW_FIR,
ANNOTATIONS_FOR_PLUGINS, // run only if some extensions are registered ANNOTATIONS_FOR_PLUGINS, // run only if some extensions are registered
FIRST_PLUGIN_GENERATION, // plugin phase
IMPORTS, IMPORTS,
SUPER_TYPES, SUPER_TYPES,
SEALED_CLASS_INHERITORS, SEALED_CLASS_INHERITORS,