[FIR] Add prototype of first generation phase
This commit is contained in:
+43
@@ -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()
|
||||||
+13
-3
@@ -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)
|
||||||
}
|
}
|
||||||
+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.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()
|
||||||
|
|||||||
+104
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user