[FIR/IR generator] Introduce the common entry point for tree generators
This reduces code duplication.
This commit is contained in:
committed by
Space Team
parent
858343695c
commit
8d1907e2f5
+1
-1
@@ -134,7 +134,7 @@ abstract class AbstractVisitorPrinter<Element : AbstractElement<Element, Field,
|
||||
}
|
||||
|
||||
context(ImportCollector)
|
||||
fun printVisitor(elements: List<Element>) {
|
||||
open fun printVisitor(elements: List<Element>) {
|
||||
val visitorType = this.visitorType
|
||||
printer.run {
|
||||
printKDoc("Auto-generated by [${this@AbstractVisitorPrinter::class.qualifiedName}]")
|
||||
|
||||
+110
-2
@@ -5,7 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.generators.tree.printer
|
||||
|
||||
import org.jetbrains.kotlin.generators.tree.ImportCollector
|
||||
import org.jetbrains.kotlin.generators.tree.*
|
||||
import org.jetbrains.kotlin.generators.tree.config.AbstractBuilderConfigurator
|
||||
import org.jetbrains.kotlin.generators.tree.config.AbstractImplementationConfigurator
|
||||
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil
|
||||
import org.jetbrains.kotlin.utils.SmartPrinter
|
||||
import java.io.File
|
||||
|
||||
@@ -51,4 +54,109 @@ fun printGeneratedType(
|
||||
append(stringBuilder)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The entry point of the tree generator.
|
||||
*
|
||||
* @param generationPath Where to put the generated files.
|
||||
* @param treeGeneratorReadme A relative path to the README file of the tree generator. This path is mentioned in the auto-generation
|
||||
* warning in each generated file.
|
||||
* @param model The configured elements of the tree.
|
||||
* @param pureAbstractElement The abstract class for elements that only implement interfaces to inherit from, see [addPureAbstractElement]
|
||||
* for details.
|
||||
* @param createElementPrinter Provide the class that prints elements, see [AbstractElementPrinter].
|
||||
* @param createVisitorPrinters Provide the class that prints various visitors, see [AbstractVisitorPrinter].
|
||||
* @param implementationConfigurator The class for configuring the set of implementation classes, see [AbstractImplementation] and
|
||||
* [AbstractImplementationConfigurator].
|
||||
* @param builderConfigurator The class for configuring the set of builders, see [Builder] and [AbstractBuilderConfigurator].
|
||||
* @param createImplementationPrinter Provide the class that prints implementations of elements, see [AbstractImplementationPrinter].
|
||||
* @param createBuilderPrinter Provide the class that prints the corresponding builder for each element class, see [AbstractBuilderPrinter].
|
||||
* @param afterConfiguration The routine to run after all implementations and builders were fully configured,
|
||||
* but before anything was printed to a file.
|
||||
* @param enableBaseTransformerTypeDetection Whether to use a special algorithm for inferring return types of transformer methods for each
|
||||
* element, see [detectBaseTransformerTypes].
|
||||
* @param addFiles Arbitrary files to add to the set of generated files.
|
||||
*/
|
||||
fun <Element, Implementation, ElementField, ImplementationField> generateTree(
|
||||
generationPath: File,
|
||||
treeGeneratorReadme: String,
|
||||
model: Model<Element>,
|
||||
pureAbstractElement: ClassRef<*>,
|
||||
createElementPrinter: (SmartPrinter) -> AbstractElementPrinter<Element, ElementField>,
|
||||
createVisitorPrinters: List<Pair<ClassRef<*>, (SmartPrinter, ClassRef<*>) -> AbstractVisitorPrinter<Element, ElementField>>>,
|
||||
implementationConfigurator: AbstractImplementationConfigurator<Implementation, Element, ImplementationField>? = null,
|
||||
builderConfigurator: AbstractBuilderConfigurator<Element, Implementation, ImplementationField, ElementField>? = null,
|
||||
createImplementationPrinter: ((SmartPrinter) -> AbstractImplementationPrinter<Implementation, Element, ImplementationField>)? = null,
|
||||
createBuilderPrinter: ((SmartPrinter) -> AbstractBuilderPrinter<Element, Implementation, ImplementationField, ElementField>)? = null,
|
||||
afterConfiguration: () -> Unit = {},
|
||||
enableBaseTransformerTypeDetection: Boolean = true,
|
||||
addFiles: MutableList<GeneratedFile>.() -> Unit = {},
|
||||
) where Element : AbstractElement<Element, ElementField, Implementation>,
|
||||
Implementation : AbstractImplementation<Implementation, Element, ImplementationField>,
|
||||
ElementField : AbstractField<ElementField>,
|
||||
ImplementationField : AbstractField<*>,
|
||||
ImplementationField : AbstractFieldWithDefaultValue<ElementField> {
|
||||
if (enableBaseTransformerTypeDetection) {
|
||||
detectBaseTransformerTypes(model)
|
||||
}
|
||||
implementationConfigurator?.configureImplementations(model)
|
||||
val implementations = model.elements.flatMap { it.allImplementations }
|
||||
InterfaceAndAbstractClassConfigurator((model.elements + implementations))
|
||||
.configureInterfacesAndAbstractClasses()
|
||||
addPureAbstractElement(model.elements, pureAbstractElement)
|
||||
builderConfigurator?.configureBuilders()
|
||||
afterConfiguration()
|
||||
val generatedFiles = mutableListOf<GeneratedFile>()
|
||||
|
||||
model.elements.mapTo(generatedFiles) { element ->
|
||||
printGeneratedType(
|
||||
generationPath,
|
||||
treeGeneratorReadme,
|
||||
element.packageName,
|
||||
element.typeName,
|
||||
) {
|
||||
createElementPrinter(this).printElement(element)
|
||||
}
|
||||
}
|
||||
|
||||
if (createImplementationPrinter != null) {
|
||||
implementations.mapTo(generatedFiles) { implementation ->
|
||||
printGeneratedType(
|
||||
generationPath,
|
||||
treeGeneratorReadme,
|
||||
implementation.packageName,
|
||||
implementation.typeName,
|
||||
fileSuppressions = listOf("DuplicatedCode", "unused"),
|
||||
) {
|
||||
createImplementationPrinter(this).printImplementation(implementation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (createBuilderPrinter != null && builderConfigurator != null) {
|
||||
(implementations.mapNotNull { it.builder } + builderConfigurator.intermediateBuilders).mapTo(generatedFiles) { builder ->
|
||||
printGeneratedType(
|
||||
generationPath,
|
||||
treeGeneratorReadme,
|
||||
builder.packageName,
|
||||
builder.typeName,
|
||||
fileSuppressions = listOf("DuplicatedCode", "unused"),
|
||||
) {
|
||||
createBuilderPrinter(this).printBuilder(builder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createVisitorPrinters.mapTo(generatedFiles) { (visitorClass, createVisitorPrinter) ->
|
||||
printGeneratedType(generationPath, treeGeneratorReadme, visitorClass.packageName, visitorClass.simpleName) {
|
||||
createVisitorPrinter(this, visitorClass).printVisitor(model.elements)
|
||||
}
|
||||
}
|
||||
|
||||
generatedFiles.addFiles()
|
||||
|
||||
val previouslyGeneratedFiles = GeneratorsFileUtil.collectPreviouslyGeneratedFiles(generationPath)
|
||||
generatedFiles.forEach { GeneratorsFileUtil.writeFileIfContentChanged(it.file, it.newText, logNotChanged = false) }
|
||||
GeneratorsFileUtil.removeExtraFilesFromPreviousGeneration(previouslyGeneratedFiles, generatedFiles.map { it.file })
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ operator fun <K, V, U> Map<K, Map<V, U>>.get(k1: K, k2: V): U {
|
||||
return getValue(k1).getValue(k2)
|
||||
}
|
||||
|
||||
fun <T1, T2, T3, R> ((T1, T2, T3) -> R).bind(t3: T3): ((T1, T2) -> R) = { t1, t2 -> invoke(t1, t2, t3) }
|
||||
|
||||
internal fun <Field : AbstractField<*>> List<Field>.reorderFieldsIfNecessary(order: List<String>?): List<Field> =
|
||||
if (order == null) {
|
||||
this
|
||||
|
||||
Reference in New Issue
Block a user