[IR] Final preparation to autogenerate IR declaration implementations
IR expressions are left out for now, because unlike declarations, which are mostly created via IrFactory, expressions' constructors are widely used, and it's hard to replicate the exact signatures of those constructors with the tree generator. Therefore, some other approach is expected to be taken when generating them in the future. ^KT-65773 In Progress
This commit is contained in:
committed by
Space Team
parent
451c51c849
commit
6cdddaacb0
+3
-3
@@ -629,7 +629,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
|
||||
override fun configureAllImplementations(model: Model) {
|
||||
configureFieldInAllImplementations(
|
||||
field = "controlFlowGraphReference",
|
||||
fieldName = "controlFlowGraphReference",
|
||||
implementationPredicate = { it.typeName != "FirAnonymousFunctionImpl" }
|
||||
) {
|
||||
defaultNull(it)
|
||||
@@ -661,7 +661,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
"FirInaccessibleReceiverExpressionImpl"
|
||||
)
|
||||
configureFieldInAllImplementations(
|
||||
field = "typeRef",
|
||||
fieldName = "typeRef",
|
||||
implementationPredicate = { it.typeName !in implementationWithConfigurableTypeRef },
|
||||
fieldPredicate = { it.defaultValueInImplementation == null }
|
||||
) {
|
||||
@@ -670,7 +670,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations(
|
||||
field = "lValueTypeRef",
|
||||
fieldName = "lValueTypeRef",
|
||||
implementationPredicate = { it.typeName in "FirVariableAssignmentImpl" },
|
||||
fieldPredicate = { it.defaultValueInImplementation == null }
|
||||
) {
|
||||
|
||||
+3
@@ -27,6 +27,9 @@ private class ImplementationFieldPrinter(printer: SmartPrinter) : AbstractFieldP
|
||||
override fun forceMutable(field: FieldWithDefault): Boolean = field.isMutable && field.isMutableOrEmptyIfList()
|
||||
|
||||
override fun actualTypeOfField(field: FieldWithDefault) = field.getMutableType()
|
||||
|
||||
override val wrapOptInAnnotations
|
||||
get() = true
|
||||
}
|
||||
|
||||
internal class ImplementationPrinter(
|
||||
|
||||
+126
-3
@@ -5,16 +5,139 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.generator
|
||||
|
||||
import org.jetbrains.kotlin.generators.tree.StandardTypes
|
||||
import org.jetbrains.kotlin.ir.generator.config.AbstractIrTreeImplementationConfigurator
|
||||
import org.jetbrains.kotlin.ir.generator.model.Element
|
||||
import org.jetbrains.kotlin.ir.generator.model.ListField
|
||||
|
||||
object ImplementationConfigurator : AbstractIrTreeImplementationConfigurator() {
|
||||
override fun configure(model: Model): Unit = with(IrTree) {
|
||||
impl(simpleFunction)
|
||||
impl(property)
|
||||
impl(anonymousInitializer) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(simpleFunction) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
impl(functionWithLateBinding) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(constructor) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(field) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(property) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
impl(propertyWithLateBinding) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(localDelegatedProperty) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(typeParameter) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(valueParameter) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(variable) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(`class`) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(enumEntry) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(script) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(moduleFragment) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(errorDeclaration) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(externalPackageFragment) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(file) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
|
||||
impl(typeAlias) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureAllImplementations(model: Model) {
|
||||
// Use configureFieldInAllImplementations to customize certain fields in all implementation classes
|
||||
configureFieldInAllImplementations("parent") {
|
||||
isLateinit("parent")
|
||||
isMutable("parent")
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations("attributeOwnerId") {
|
||||
default(it, "this")
|
||||
}
|
||||
configureFieldInAllImplementations("originalBeforeInline") {
|
||||
defaultNull(it)
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations("metadata") {
|
||||
defaultNull(it)
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations("annotations") {
|
||||
defaultEmptyList(it)
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations("overriddenSymbols") {
|
||||
defaultEmptyList(it)
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations("typeParameters") {
|
||||
defaultEmptyList(it)
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations("statements") {
|
||||
default(it, "ArrayList(2)")
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations("descriptor", { impl -> impl.allFields.any { it.name == "symbol" } }) {
|
||||
default(it, "symbol.descriptor", withGetter = true)
|
||||
}
|
||||
|
||||
configureFieldInAllImplementations(
|
||||
fieldName = null,
|
||||
fieldPredicate = { it is ListField && it.isChild && it.listType == StandardTypes.mutableList }
|
||||
) {
|
||||
default(it, "ArrayList()")
|
||||
}
|
||||
|
||||
// Generation of implementation classes of IrExpression are left out for subsequent MR, as a part of KT-65773.
|
||||
for (element in model.elements) {
|
||||
if (element.category == Element.Category.Expression) {
|
||||
for (implementation in element.implementations) {
|
||||
implementation.doPrint = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ fun main(args: Array<String>) {
|
||||
typeTransformerType to ::TypeTransformerPrinter.bind(model.rootElement),
|
||||
),
|
||||
ImplementationConfigurator,
|
||||
createImplementationPrinter = ::ImplementationPrinter,
|
||||
enableBaseTransformerTypeDetection = false,
|
||||
addFiles = { add(printFactory(generationPath, model)) }
|
||||
)
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef
|
||||
class Element(
|
||||
name: String,
|
||||
override val propertyName: String,
|
||||
category: Category,
|
||||
val category: Category,
|
||||
) : AbstractElement<Element, Field, Implementation>(name) {
|
||||
|
||||
enum class Category(private val packageDir: String, val defaultVisitorParam: String) {
|
||||
|
||||
+13
-2
@@ -7,8 +7,19 @@ package org.jetbrains.kotlin.ir.generator.model
|
||||
|
||||
import org.jetbrains.kotlin.generators.tree.AbstractImplementation
|
||||
import org.jetbrains.kotlin.generators.tree.ImplementationKind
|
||||
import org.jetbrains.kotlin.generators.tree.ImportCollector
|
||||
import org.jetbrains.kotlin.utils.SmartPrinter
|
||||
|
||||
class Implementation(element: Element, name: String?) : AbstractImplementation<Implementation, Element, Field>(element, name) {
|
||||
override val allFields
|
||||
get() = element.allFields
|
||||
override val allFields: List<Field> = element.allFields.map { it.copy() }
|
||||
|
||||
override var kind: ImplementationKind? = ImplementationKind.FinalClass
|
||||
|
||||
var generationCallback: (context(ImportCollector) SmartPrinter.() -> Unit)? = null
|
||||
|
||||
override var doPrint = true
|
||||
|
||||
init {
|
||||
isPublic = true
|
||||
}
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2010-2024 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.ir.generator.print
|
||||
|
||||
import com.intellij.psi.util.PsiExpressionTrimRenderer.render
|
||||
import org.jetbrains.kotlin.generators.tree.*
|
||||
import org.jetbrains.kotlin.generators.tree.printer.printBlock
|
||||
import org.jetbrains.kotlin.ir.generator.IrTree
|
||||
import org.jetbrains.kotlin.ir.generator.IrTree.parent
|
||||
import org.jetbrains.kotlin.ir.generator.irImplementationDetailType
|
||||
import org.jetbrains.kotlin.ir.generator.model.*
|
||||
import org.jetbrains.kotlin.utils.SmartPrinter
|
||||
|
||||
internal class ImplementationPrinter(printer: SmartPrinter) : AbstractImplementationPrinter<Implementation, Element, Field>(printer) {
|
||||
override fun makeFieldPrinter(printer: SmartPrinter) = object : AbstractFieldPrinter<Field>(printer) {
|
||||
override fun forceMutable(field: Field) = field.isMutable
|
||||
}
|
||||
|
||||
override val pureAbstractElementType: ClassRef<*>
|
||||
get() = org.jetbrains.kotlin.ir.generator.elementBaseType
|
||||
|
||||
override val implementationOptInAnnotation: ClassRef<*>
|
||||
get() = irImplementationDetailType
|
||||
|
||||
override val separateFieldsWithBlankLine: Boolean
|
||||
get() = true
|
||||
|
||||
context(ImportCollector)
|
||||
override fun SmartPrinter.printAdditionalMethods(implementation: Implementation) {
|
||||
implementation.generationCallback?.invoke(this@ImportCollector, this)
|
||||
|
||||
if (
|
||||
implementation.element.traverseParentsUntil { it == IrTree.symbolOwner } &&
|
||||
!implementation.element.let { it == IrTree.propertyWithLateBinding || it == IrTree.functionWithLateBinding }
|
||||
) {
|
||||
val symbolField = implementation["symbol"]
|
||||
if (symbolField != null) {
|
||||
println()
|
||||
print("init")
|
||||
printBlock {
|
||||
println("${symbolField.name}.bind(this)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -30,6 +30,9 @@ abstract class AbstractFieldPrinter<Field : AbstractField<*>>(
|
||||
*/
|
||||
protected open fun actualTypeOfField(field: Field): TypeRefWithNullability = field.typeRef
|
||||
|
||||
protected open val wrapOptInAnnotations: Boolean
|
||||
get() = false
|
||||
|
||||
context(ImportCollector)
|
||||
fun printField(
|
||||
field: Field,
|
||||
@@ -51,9 +54,9 @@ abstract class AbstractFieldPrinter<Field : AbstractField<*>>(
|
||||
isLateinit = (inImplementation || field.isFinal) && field.isLateinit,
|
||||
isVolatile = (inImplementation || field.isFinal) && field.isVolatile,
|
||||
optInAnnotation = field.optInAnnotation,
|
||||
printOptInWrapped = defaultValue != null,
|
||||
printOptInWrapped = wrapOptInAnnotations && defaultValue != null,
|
||||
deprecation = field.deprecation,
|
||||
kDoc = field.kDoc,
|
||||
kDoc = field.kDoc.takeIf { !inImplementation },
|
||||
initializer = defaultValue.takeUnless { field.withGetter }
|
||||
)
|
||||
println()
|
||||
|
||||
+7
@@ -64,6 +64,10 @@ abstract class AbstractImplementation<Implementation, Element, Field>(
|
||||
get() = true
|
||||
var isPublic = false
|
||||
|
||||
var putImplementationOptInInConstructor = true
|
||||
|
||||
var constructorParameterOrderOverride: List<String>? = null
|
||||
|
||||
override fun get(fieldName: String): Field? {
|
||||
return allFields.firstOrNull { it.name == fieldName }
|
||||
}
|
||||
@@ -92,4 +96,7 @@ abstract class AbstractImplementation<Implementation, Element, Field>(
|
||||
}
|
||||
|
||||
var builder: LeafBuilder<Field, Element, Implementation>? = null
|
||||
|
||||
open val doPrint: Boolean
|
||||
get() = true
|
||||
}
|
||||
|
||||
+25
-26
@@ -25,11 +25,13 @@ abstract class AbstractImplementationPrinter<Implementation, Element, Implementa
|
||||
|
||||
protected abstract val pureAbstractElementType: ClassRef<*>
|
||||
|
||||
protected open val separateFieldsWithBlankLine: Boolean
|
||||
get() = false
|
||||
|
||||
protected abstract fun makeFieldPrinter(printer: SmartPrinter): AbstractFieldPrinter<ImplementationField>
|
||||
|
||||
context(ImportCollector)
|
||||
protected open fun SmartPrinter.printAdditionalMethods(implementation: Implementation) {
|
||||
}
|
||||
protected open fun SmartPrinter.printAdditionalMethods(implementation: Implementation) {}
|
||||
|
||||
context(ImportCollector)
|
||||
fun printImplementation(implementation: Implementation) {
|
||||
@@ -63,19 +65,21 @@ abstract class AbstractImplementationPrinter<Implementation, Element, Implementa
|
||||
val fieldPrinter = makeFieldPrinter(this)
|
||||
|
||||
if (!isInterface && !isAbstract && implementation.fieldsInConstructor.isNotEmpty()) {
|
||||
if (implementation.isPublic) {
|
||||
if (implementation.isPublic && implementation.putImplementationOptInInConstructor) {
|
||||
print(" @", implementationOptInAnnotation.render(), " constructor")
|
||||
}
|
||||
println("(")
|
||||
withIndent {
|
||||
implementation.fieldsInConstructor.forEachIndexed { _, field ->
|
||||
if (field.isParameter) {
|
||||
print(field.name, ": ", field.typeRef.render())
|
||||
println(",")
|
||||
} else if (!field.isFinal) {
|
||||
fieldPrinter.printField(field, inImplementation = true, override = true, inConstructor = true)
|
||||
implementation.fieldsInConstructor
|
||||
.reorderFieldsIfNecessary(implementation.constructorParameterOrderOverride)
|
||||
.forEachIndexed { _, field ->
|
||||
if (field.isParameter) {
|
||||
print(field.name, ": ", field.typeRef.render())
|
||||
println(",")
|
||||
} else if (!field.isFinal) {
|
||||
fieldPrinter.printField(field, inImplementation = true, override = true, inConstructor = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
print(")")
|
||||
}
|
||||
@@ -86,23 +90,18 @@ abstract class AbstractImplementationPrinter<Implementation, Element, Implementa
|
||||
}
|
||||
print(implementation.allParents.joinToString { "${it.render()}${it.kind.braces()}" })
|
||||
printBlock {
|
||||
if (isInterface || isAbstract) {
|
||||
implementation.allFields.forEach {
|
||||
fieldPrinter.printField(
|
||||
it,
|
||||
inImplementation = true,
|
||||
override = true,
|
||||
modality = Modality.ABSTRACT.takeIf { isAbstract }
|
||||
)
|
||||
}
|
||||
} else {
|
||||
implementation.fieldsInBody.forEach {
|
||||
fieldPrinter.printField(
|
||||
it,
|
||||
inImplementation = true,
|
||||
override = true
|
||||
)
|
||||
val fields = if (isInterface || isAbstract) implementation.allFields
|
||||
else implementation.fieldsInBody
|
||||
fields.forEachIndexed { index, field ->
|
||||
if (index > 0 && separateFieldsWithBlankLine) {
|
||||
println()
|
||||
}
|
||||
fieldPrinter.printField(
|
||||
field,
|
||||
inImplementation = true,
|
||||
override = true,
|
||||
modality = Modality.ABSTRACT.takeIf { isAbstract }
|
||||
)
|
||||
}
|
||||
|
||||
printAdditionalMethods(implementation)
|
||||
|
||||
+13
-5
@@ -80,14 +80,14 @@ abstract class AbstractImplementationConfigurator<Implementation, Element, Imple
|
||||
* Allows to batch-apply [config] to certain fields in _all_ the implementations that satisfy the given
|
||||
* [implementationPredicate].
|
||||
*
|
||||
* @param field The name of the field to configure across all `Impl` classes.
|
||||
* @param fieldName The name of the field to configure across all `Impl` classes, or `null` if [config] should be applied to all fields.
|
||||
* @param implementationPredicate Only implementations satisfying this predicate will be used in this configuration.
|
||||
* @param fieldPredicate Only fields satisfying this predicate will be configured
|
||||
* @param config The configuration block. Accepts the field name as an argument.
|
||||
* See [ImplementationContext]'s documentation for description of its DSL methods.
|
||||
*/
|
||||
protected fun configureFieldInAllImplementations(
|
||||
field: String,
|
||||
fieldName: String?,
|
||||
implementationPredicate: (Implementation) -> Boolean = { true },
|
||||
fieldPredicate: (ImplementationField) -> Boolean = { true },
|
||||
config: ImplementationContext.(field: String) -> Unit,
|
||||
@@ -95,9 +95,17 @@ abstract class AbstractImplementationConfigurator<Implementation, Element, Imple
|
||||
for (element in elementsWithImpl) {
|
||||
for (implementation in element.implementations) {
|
||||
if (!implementationPredicate(implementation)) continue
|
||||
if (!implementation.allFields.any { it.name == field }) continue
|
||||
if (!fieldPredicate(implementation.getField(field))) continue
|
||||
ImplementationContext(implementation).config(field)
|
||||
if (fieldName != null && !implementation.allFields.any { it.name == fieldName }) continue
|
||||
|
||||
val fields = if (fieldName != null) {
|
||||
listOf(implementation.getField(fieldName))
|
||||
} else {
|
||||
implementation.allFields
|
||||
}
|
||||
|
||||
for (field in fields.filter(fieldPredicate)) {
|
||||
ImplementationContext(implementation).config(field.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-14
@@ -83,9 +83,9 @@ fun <Element, Implementation, ElementField, ImplementationField> generateTree(
|
||||
pureAbstractElement: ClassRef<*>,
|
||||
createElementPrinter: (SmartPrinter) -> AbstractElementPrinter<Element, ElementField>,
|
||||
createVisitorPrinters: List<Pair<ClassRef<*>, (SmartPrinter, ClassRef<*>) -> AbstractVisitorPrinter<Element, ElementField>>>,
|
||||
implementationConfigurator: AbstractImplementationConfigurator<Implementation, Element, ImplementationField>? = null,
|
||||
implementationConfigurator: AbstractImplementationConfigurator<Implementation, Element, ImplementationField>,
|
||||
builderConfigurator: AbstractBuilderConfigurator<Element, Implementation, ImplementationField, ElementField>? = null,
|
||||
createImplementationPrinter: ((SmartPrinter) -> AbstractImplementationPrinter<Implementation, Element, ImplementationField>)? = null,
|
||||
createImplementationPrinter: (SmartPrinter) -> AbstractImplementationPrinter<Implementation, Element, ImplementationField>,
|
||||
createBuilderPrinter: ((SmartPrinter) -> AbstractBuilderPrinter<Element, Implementation, ImplementationField, ElementField>)? = null,
|
||||
enableBaseTransformerTypeDetection: Boolean = true,
|
||||
addFiles: MutableList<GeneratedFile>.() -> Unit = {},
|
||||
@@ -98,7 +98,7 @@ fun <Element, Implementation, ElementField, ImplementationField> generateTree(
|
||||
detectBaseTransformerTypes(model)
|
||||
}
|
||||
initializeSubElements(model.elements)
|
||||
implementationConfigurator?.configureImplementations(model)
|
||||
implementationConfigurator.configureImplementations(model)
|
||||
val implementations = model.elements.flatMap { it.implementations }
|
||||
InterfaceAndAbstractClassConfigurator((model.elements + implementations))
|
||||
.configureInterfacesAndAbstractClasses()
|
||||
@@ -117,17 +117,15 @@ fun <Element, Implementation, ElementField, ImplementationField> generateTree(
|
||||
}
|
||||
}
|
||||
|
||||
if (createImplementationPrinter != null) {
|
||||
implementations.mapTo(generatedFiles) { implementation ->
|
||||
printGeneratedType(
|
||||
generationPath,
|
||||
treeGeneratorReadme,
|
||||
implementation.packageName,
|
||||
implementation.typeName,
|
||||
fileSuppressions = listOf("DuplicatedCode", "unused"),
|
||||
) {
|
||||
createImplementationPrinter(this).printImplementation(implementation)
|
||||
}
|
||||
implementations.filter { it.doPrint }.mapTo(generatedFiles) { implementation ->
|
||||
printGeneratedType(
|
||||
generationPath,
|
||||
treeGeneratorReadme,
|
||||
implementation.packageName,
|
||||
implementation.typeName,
|
||||
fileSuppressions = listOf("DuplicatedCode", "unused"),
|
||||
) {
|
||||
createImplementationPrinter(this).printImplementation(implementation)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ object ImplementationConfigurator : AbstractSwiftIrTreeImplementationConfigurato
|
||||
override fun configureAllImplementations(model: Model) {
|
||||
// Use configureFieldInAllImplementations to customize certain fields in all implementation classes
|
||||
configureFieldInAllImplementations(
|
||||
field = "parent",
|
||||
fieldName = "parent",
|
||||
) {
|
||||
isMutable(it)
|
||||
isLateinit(it)
|
||||
|
||||
Reference in New Issue
Block a user