From 6cdddaacb0b15edcd2baa94d608d23750fbb46c5 Mon Sep 17 00:00:00 2001 From: Wojciech Litewka Date: Wed, 21 Feb 2024 16:40:11 +0100 Subject: [PATCH] [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 --- .../generator/ImplementationConfigurator.kt | 6 +- .../printer/ImplementationPrinter.kt | 3 + .../generator/ImplementationConfigurator.kt | 129 +++++++++++++++++- .../org/jetbrains/kotlin/ir/generator/Main.kt | 1 + .../kotlin/ir/generator/model/Element.kt | 2 +- .../ir/generator/model/Implementation.kt | 15 +- .../generator/print/ImplementationPrinter.kt | 49 +++++++ .../generators/tree/AbstractFieldPrinter.kt | 7 +- .../generators/tree/AbstractImplementation.kt | 7 + .../tree/AbstractImplementationPrinter.kt | 51 ++++--- .../AbstractImplementationConfigurator.kt | 18 ++- .../kotlin/generators/tree/printer/common.kt | 26 ++-- .../generator/ImplementationConfigurator.kt | 2 +- 13 files changed, 259 insertions(+), 57 deletions(-) create mode 100644 compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/ImplementationPrinter.kt diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt index 8072600c966..3d327ff2729 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt @@ -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 } ) { diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/ImplementationPrinter.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/ImplementationPrinter.kt index 09f1d1e9693..ec18dc42b4f 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/ImplementationPrinter.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/ImplementationPrinter.kt @@ -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( diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/ImplementationConfigurator.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/ImplementationConfigurator.kt index 6089c1317c7..91b5b9218ec 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/ImplementationConfigurator.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/ImplementationConfigurator.kt @@ -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 + } + } + } } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt index 5cb38b2c857..e7254ba8864 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/Main.kt @@ -35,6 +35,7 @@ fun main(args: Array) { typeTransformerType to ::TypeTransformerPrinter.bind(model.rootElement), ), ImplementationConfigurator, + createImplementationPrinter = ::ImplementationPrinter, enableBaseTransformerTypeDetection = false, addFiles = { add(printFactory(generationPath, model)) } ) diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Element.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Element.kt index 6f220670e96..0d8d206ad83 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Element.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Element.kt @@ -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(name) { enum class Category(private val packageDir: String, val defaultVisitorParam: String) { diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Implementation.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Implementation.kt index 8745e36578b..244bd06f6b3 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Implementation.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Implementation.kt @@ -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(element, name) { - override val allFields - get() = element.allFields + override val allFields: List = 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 + } } diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/ImplementationPrinter.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/ImplementationPrinter.kt new file mode 100644 index 00000000000..ba5721e0e41 --- /dev/null +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/ImplementationPrinter.kt @@ -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(printer) { + override fun makeFieldPrinter(printer: SmartPrinter) = object : AbstractFieldPrinter(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)") + } + } + } + } +} \ No newline at end of file diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractFieldPrinter.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractFieldPrinter.kt index 0d828ad16b6..89a1dedbe55 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractFieldPrinter.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractFieldPrinter.kt @@ -30,6 +30,9 @@ abstract class AbstractFieldPrinter>( */ 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>( 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() diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractImplementation.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractImplementation.kt index cfeb52eb752..f7fe1837e8e 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractImplementation.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractImplementation.kt @@ -64,6 +64,10 @@ abstract class AbstractImplementation( get() = true var isPublic = false + var putImplementationOptInInConstructor = true + + var constructorParameterOrderOverride: List? = null + override fun get(fieldName: String): Field? { return allFields.firstOrNull { it.name == fieldName } } @@ -92,4 +96,7 @@ abstract class AbstractImplementation( } var builder: LeafBuilder? = null + + open val doPrint: Boolean + get() = true } diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractImplementationPrinter.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractImplementationPrinter.kt index 6d9267c01d1..8862ba6932b 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractImplementationPrinter.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractImplementationPrinter.kt @@ -25,11 +25,13 @@ abstract class AbstractImplementationPrinter + protected open val separateFieldsWithBlankLine: Boolean + get() = false + protected abstract fun makeFieldPrinter(printer: SmartPrinter): AbstractFieldPrinter 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 - 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 + if (index > 0 && separateFieldsWithBlankLine) { + println() } + fieldPrinter.printField( + field, + inImplementation = true, + override = true, + modality = Modality.ABSTRACT.takeIf { isAbstract } + ) } printAdditionalMethods(implementation) diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/config/AbstractImplementationConfigurator.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/config/AbstractImplementationConfigurator.kt index 49eaf74419f..ca2cff0185b 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/config/AbstractImplementationConfigurator.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/config/AbstractImplementationConfigurator.kt @@ -80,14 +80,14 @@ abstract class AbstractImplementationConfigurator Boolean = { true }, fieldPredicate: (ImplementationField) -> Boolean = { true }, config: ImplementationContext.(field: String) -> Unit, @@ -95,9 +95,17 @@ abstract class AbstractImplementationConfigurator generateTree( pureAbstractElement: ClassRef<*>, createElementPrinter: (SmartPrinter) -> AbstractElementPrinter, createVisitorPrinters: List, (SmartPrinter, ClassRef<*>) -> AbstractVisitorPrinter>>, - implementationConfigurator: AbstractImplementationConfigurator? = null, + implementationConfigurator: AbstractImplementationConfigurator, builderConfigurator: AbstractBuilderConfigurator? = null, - createImplementationPrinter: ((SmartPrinter) -> AbstractImplementationPrinter)? = null, + createImplementationPrinter: (SmartPrinter) -> AbstractImplementationPrinter, createBuilderPrinter: ((SmartPrinter) -> AbstractBuilderPrinter)? = null, enableBaseTransformerTypeDetection: Boolean = true, addFiles: MutableList.() -> Unit = {}, @@ -98,7 +98,7 @@ fun 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 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) } } diff --git a/native/swift/sir/tree-generator/src/org/jetbrains/kotlin/sir/tree/generator/ImplementationConfigurator.kt b/native/swift/sir/tree-generator/src/org/jetbrains/kotlin/sir/tree/generator/ImplementationConfigurator.kt index 5c2cfcf60e0..1725b492a26 100644 --- a/native/swift/sir/tree-generator/src/org/jetbrains/kotlin/sir/tree/generator/ImplementationConfigurator.kt +++ b/native/swift/sir/tree-generator/src/org/jetbrains/kotlin/sir/tree/generator/ImplementationConfigurator.kt @@ -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)