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 new file mode 100644 index 00000000000..a0d0de2c45f --- /dev/null +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/ImplementationConfigurator.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2023 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 + +import org.jetbrains.kotlin.ir.generator.config.AbstractIrTreeImplementationConfigurator + +object ImplementationConfigurator : AbstractIrTreeImplementationConfigurator() { + override fun configure(): Unit = with(IrTree) { + impl(simpleFunction) + impl(property) + } + + override fun configureAllImplementations() { + // Use configureFieldInAllImplementations to customize certain fields in all implementation classes + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt index 5973d2e3d08..c2e3a9dbfd1 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/IrTree.kt @@ -496,8 +496,6 @@ object IrTree : AbstractTreeBuilder() { +listField("files", file, mutability = MutableList) } val property: Element by element(Declaration) { - isLeaf = true - parent(declarationBase) parent(possiblyExternalDeclaration) parent(overridableDeclaration.withArgs("S" to propertySymbolType)) @@ -552,8 +550,6 @@ object IrTree : AbstractTreeBuilder() { +field("constructor", constructor, nullable = true, isChild = false) // K1 } val simpleFunction: Element by element(Declaration) { - isLeaf = true - parent(function) parent(overridableDeclaration.withArgs("S" to simpleFunctionSymbolType)) parent(attributeContainer) 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 7d6091e3aec..5cb38b2c857 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 @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.ir.generator import org.jetbrains.kotlin.generators.tree.printer.generateTree -import org.jetbrains.kotlin.ir.generator.model.markLeaves +import org.jetbrains.kotlin.ir.generator.model.Element import org.jetbrains.kotlin.ir.generator.print.* import org.jetbrains.kotlin.utils.bind import java.io.File @@ -15,6 +15,8 @@ const val BASE_PACKAGE = "org.jetbrains.kotlin.ir" internal const val TREE_GENERATOR_README = "compiler/ir/ir.tree/tree-generator/ReadMe.md" +typealias Model = org.jetbrains.kotlin.generators.tree.Model + fun main(args: Array) { val generationPath = args.firstOrNull()?.let { File(it) } ?: File("compiler/ir/ir.tree/gen").canonicalFile @@ -32,9 +34,7 @@ fun main(args: Array) { elementTransformerVoidType to ::TransformerVoidPrinter, typeTransformerType to ::TypeTransformerPrinter.bind(model.rootElement), ), - afterConfiguration = { - markLeaves(model.elements) - }, + ImplementationConfigurator, enableBaseTransformerTypeDetection = false, addFiles = { add(printFactory(generationPath, model)) } ) diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractIrTreeImplementationConfigurator.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractIrTreeImplementationConfigurator.kt new file mode 100644 index 00000000000..70451ede64c --- /dev/null +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractIrTreeImplementationConfigurator.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2023 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.config + +import org.jetbrains.kotlin.generators.tree.config.AbstractImplementationConfigurator +import org.jetbrains.kotlin.ir.generator.model.Element +import org.jetbrains.kotlin.ir.generator.model.Field +import org.jetbrains.kotlin.ir.generator.model.Implementation + +abstract class AbstractIrTreeImplementationConfigurator : AbstractImplementationConfigurator() { + override fun createImplementation(element: Element, name: String?) = Implementation(element, name) +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt index c45a1ce10ba..b10fc179b6b 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/config/AbstractTreeBuilder.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.ir.generator.model.* import org.jetbrains.kotlin.ir.generator.model.ElementOrRef import org.jetbrains.kotlin.ir.generator.model.ElementRef import org.jetbrains.kotlin.ir.generator.model.ListField -import org.jetbrains.kotlin.ir.generator.model.Model +import org.jetbrains.kotlin.ir.generator.Model import org.jetbrains.kotlin.types.Variance import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty 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 eb949ff4d06..6f220670e96 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 @@ -17,7 +17,7 @@ class Element( name: String, override val propertyName: String, category: Category, -) : AbstractElement(name) { +) : AbstractElement(name) { enum class Category(private val packageDir: String, val defaultVisitorParam: String) { Expression("expressions", "expression"), @@ -78,17 +78,6 @@ class Element( override val namePrefix: String get() = "Ir" - /** - * Whether this element is semantically a leaf element in the hierarchy. - * - * This is set automatically by the [markLeaves] function for all true leaves, but can also be set manually to `true` if - * this element should be considered a leaf semantically. - * - * For example, we only generate [org.jetbrains.kotlin.ir.declarations.IrFactory] methods for leaf elements. - * If we want to generate a method for this element, but it has subclasses, it can be done by manually setting this property to `true`. - */ - var isLeaf = false - override var childrenOrderOverride: List? = null override var visitorParameterName = category.defaultVisitorParam @@ -96,7 +85,7 @@ class Element( var customHasAcceptMethod: Boolean? = null override val hasAcceptMethod: Boolean - get() = customHasAcceptMethod ?: (isLeaf && parentInVisitor != null) + get() = customHasAcceptMethod ?: (implementations.isNotEmpty() && parentInVisitor != null) override var hasTransformMethod = false @@ -135,4 +124,4 @@ class Element( } typealias ElementRef = GenericElementRef -typealias ElementOrRef = GenericElementOrRef \ No newline at end of file +typealias ElementOrRef = GenericElementOrRef 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 new file mode 100644 index 00000000000..8745e36578b --- /dev/null +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Implementation.kt @@ -0,0 +1,14 @@ +/* + * 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.model + +import org.jetbrains.kotlin.generators.tree.AbstractImplementation +import org.jetbrains.kotlin.generators.tree.ImplementationKind + +class Implementation(element: Element, name: String?) : AbstractImplementation(element, name) { + override val allFields + get() = element.allFields +} diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt deleted file mode 100644 index 453b76c6686..00000000000 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Transformations.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2010-2021 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.model - -typealias Model = org.jetbrains.kotlin.generators.tree.Model - -internal fun markLeaves(elements: List) { - val leaves = elements.toMutableSet() - - for (el in elements) { - for (parent in el.elementParents) { - if (!parent.element.isLeaf) { - leaves.remove(parent.element) - } - } - } - - for (el in leaves) { - el.isLeaf = true - } -} diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/FactoryPrinter.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/FactoryPrinter.kt index bace47eb821..39fcb2faa62 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/FactoryPrinter.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/FactoryPrinter.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.ir.generator.TREE_GENERATOR_README import org.jetbrains.kotlin.ir.generator.irFactoryType import org.jetbrains.kotlin.ir.generator.model.Element import org.jetbrains.kotlin.ir.generator.model.Field -import org.jetbrains.kotlin.ir.generator.model.Model +import org.jetbrains.kotlin.ir.generator.Model import org.jetbrains.kotlin.ir.generator.stageControllerType import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly import org.jetbrains.kotlin.utils.SmartPrinter @@ -33,7 +33,7 @@ internal fun printFactory(generationPath: File, model: Model): GeneratedFile = p withIndent { println("val stageController: ", stageControllerType.render()) val factoryMethods = model.elements - .filter { it.isLeaf && it.generateIrFactoryMethod } + .filter { it.implementations.isNotEmpty() && it.generateIrFactoryMethod } .sortedWith(compareBy({ it.packageName }, { it.name })) .map(::FactoryMethod) diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractElement.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractElement.kt index a2821da5c18..afdfb1f930a 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractElement.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractElement.kt @@ -42,6 +42,11 @@ abstract class AbstractElement( val isRootElement: Boolean get() = elementParents.isEmpty() + /** + * A list of [Element]s which are direct subclasses of this element. + */ + lateinit var subElements: Set + var isSealed: Boolean = false /** 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 8517ac41569..a9727198200 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 @@ -69,18 +69,11 @@ abstract class AbstractImplementationConfigurator) { - collectLeafsWithoutImplementation(elements).forEach { - impl(it) - } - } - - private fun collectLeafsWithoutImplementation(elements: List): Set { - val leafs = elements.toMutableSet() - elements.forEach { element -> - leafs.removeAll(element.elementParents.map { it.element }.toSet()) - } - leafs.removeAll(elementsWithImpl) - return leafs + elements + .filter { it.subElements.isEmpty() && it !in elementsWithImpl && !it.doesNotNeedImplementation } + .forEach { + impl(it) + } } /** diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/initializeSubElements.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/initializeSubElements.kt new file mode 100644 index 00000000000..15dd82c57f8 --- /dev/null +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/initializeSubElements.kt @@ -0,0 +1,20 @@ +/* + * 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.generators.tree + +internal fun > initializeSubElements(elements: List){ + val elementSubclasses = elements.associateWith { mutableSetOf() } + + for (element in elements) { + for (parent in element.elementParents) { + elementSubclasses.getValue(parent.element) += element + } + } + + for ((element, subElements) in elementSubclasses) { + element.subElements = subElements + } +} diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/common.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/common.kt index 0d1d5c9ee0d..b0f12d2613e 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/common.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/common.kt @@ -72,8 +72,6 @@ fun printGeneratedType( * @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. @@ -89,7 +87,6 @@ fun generateTree( builderConfigurator: AbstractBuilderConfigurator? = null, createImplementationPrinter: ((SmartPrinter) -> AbstractImplementationPrinter)? = null, createBuilderPrinter: ((SmartPrinter) -> AbstractBuilderPrinter)? = null, - afterConfiguration: () -> Unit = {}, enableBaseTransformerTypeDetection: Boolean = true, addFiles: MutableList.() -> Unit = {}, ) where Element : AbstractElement, @@ -100,13 +97,13 @@ fun generateTree( if (enableBaseTransformerTypeDetection) { detectBaseTransformerTypes(model) } + initializeSubElements(model.elements) implementationConfigurator?.configureImplementations(model) val implementations = model.elements.flatMap { it.implementations } InterfaceAndAbstractClassConfigurator((model.elements + implementations)) .configureInterfacesAndAbstractClasses() addPureAbstractElement(model.elements, pureAbstractElement) builderConfigurator?.configureBuilders() - afterConfiguration() val generatedFiles = mutableListOf() model.elements.mapTo(generatedFiles) { element ->