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 340c0d5148f..de6c3e9cc96 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 @@ -105,6 +105,7 @@ object IrTree : AbstractTreeBuilder() { +descriptor("DeclarationDescriptor") +field("origin", type(Packages.declarations, "IrDeclarationOrigin")) +field("parent", declarationParent) { + needAcceptAndTransform = false skipInIrFactory() } +factory @@ -237,7 +238,7 @@ object IrTree : AbstractTreeBuilder() { TODO: consider dropping [$name] if it isn't used by any known plugin. """.trimIndent() } - +field("defaultValue", expressionBody, nullable = true, isChild = true) + +field("defaultValue", expressionBody, nullable = true) } val `class`: Element by element(Declaration) { parent(declarationBase) @@ -285,7 +286,7 @@ object IrTree : AbstractTreeBuilder() { +listField("superTypes", irTypeType, mutability = Var) { skipInIrFactory() } - +field("thisReceiver", valueParameter, nullable = true, isChild = true) + +field("thisReceiver", valueParameter, nullable = true) +field( "valueClassRepresentation", type>().withArgs(type(Packages.types, "IrSimpleType")), @@ -316,10 +317,12 @@ object IrTree : AbstractTreeBuilder() { """.trimIndent() +field("attributeOwnerId", attributeContainer) { + needAcceptAndTransform = false skipInIrFactory() } // null <=> this element wasn't inlined +field("originalBeforeInline", attributeContainer, nullable = true) { + needAcceptAndTransform = false skipInIrFactory() } } @@ -331,14 +334,14 @@ object IrTree : AbstractTreeBuilder() { +field("isStatic", boolean) { useFieldInIrFactory(defaultValue = "false") } - +field("body", blockBody, isChild = true) + +field("body", blockBody) } val declarationContainer: Element by element(Declaration) { ownsChildren = false parent(declarationParent) - +listField("declarations", declaration, mutability = MutableList, isChild = true) { + +listField("declarations", declaration, mutability = MutableList) { kDoc = """ Accessing list of declaration may trigger lazy declaration list computation for lazy class, which requires computation of fake-overrides for this class. So it's unsafe to access it @@ -354,7 +357,7 @@ object IrTree : AbstractTreeBuilder() { parent(declaration) parent(declarationParent) - +listField("typeParameters", typeParameter, mutability = Var, isChild = true) + +listField("typeParameters", typeParameter, mutability = Var) } val typeParameter: Element by element(Declaration) { needTransformMethod() @@ -394,14 +397,14 @@ object IrTree : AbstractTreeBuilder() { +field("isInline", boolean) +field("isExpect", boolean) +field("returnType", irTypeType) - +field("dispatchReceiverParameter", valueParameter, nullable = true, isChild = true) - +field("extensionReceiverParameter", valueParameter, nullable = true, isChild = true) - +listField("valueParameters", valueParameter, mutability = Var, isChild = true) + +field("dispatchReceiverParameter", valueParameter, nullable = true) + +field("extensionReceiverParameter", valueParameter, nullable = true) + +listField("valueParameters", valueParameter, mutability = Var) // The first `contextReceiverParametersCount` value parameters are context receivers. +field("contextReceiverParametersCount", int) { skipInIrFactory() } - +field("body", body, nullable = true, isChild = true) + +field("body", body, nullable = true) } val constructor: Element by element(Declaration) { parent(function) @@ -416,8 +419,8 @@ object IrTree : AbstractTreeBuilder() { +descriptor("ClassDescriptor") +symbol(enumEntrySymbolType) - +field("initializerExpression", expressionBody, nullable = true, isChild = true) - +field("correspondingClass", `class`, nullable = true, isChild = true) + +field("initializerExpression", expressionBody, nullable = true) + +field("correspondingClass", `class`, nullable = true) } val errorDeclaration: Element by element(Declaration) { parent(declarationBase) @@ -453,7 +456,7 @@ object IrTree : AbstractTreeBuilder() { +field("type", irTypeType) +field("isFinal", boolean) +field("isStatic", boolean) - +field("initializer", expressionBody, nullable = true, isChild = true) + +field("initializer", expressionBody, nullable = true) +field("correspondingPropertySymbol", propertySymbolType, nullable = true) { skipInIrFactory() } @@ -468,9 +471,9 @@ object IrTree : AbstractTreeBuilder() { +symbol(localDelegatedPropertySymbolType) +field("type", irTypeType) +field("isVar", boolean) - +field("delegate", variable, isChild = true) - +field("getter", simpleFunction, isChild = true) - +field("setter", simpleFunction, nullable = true, isChild = true) + +field("delegate", variable) + +field("getter", simpleFunction) + +field("setter", simpleFunction, nullable = true) } val moduleFragment: Element by element(Declaration) { needTransformMethod() @@ -482,7 +485,7 @@ object IrTree : AbstractTreeBuilder() { } +field("name", type(), mutable = false) +field("irBuiltins", type(Packages.tree, "IrBuiltIns"), mutable = false) - +listField("files", file, mutability = MutableList, isChild = true) + +listField("files", file, mutability = MutableList) usedTypes += ArbitraryImportable(Packages.tree, "UNDEFINED_OFFSET") +field("startOffset", int, mutable = false) { baseGetter = "UNDEFINED_OFFSET" @@ -511,9 +514,9 @@ object IrTree : AbstractTreeBuilder() { useFieldInIrFactory(defaultValue = "false") } +isFakeOverrideField() - +field("backingField", field, nullable = true, isChild = true) - +field("getter", simpleFunction, nullable = true, isChild = true) - +field("setter", simpleFunction, nullable = true, isChild = true) + +field("backingField", field, nullable = true) + +field("getter", simpleFunction, nullable = true) + +field("setter", simpleFunction, nullable = true) } private fun isFakeOverrideField() = field("isFakeOverride", boolean) { @@ -534,18 +537,20 @@ object IrTree : AbstractTreeBuilder() { +symbol(scriptSymbolType) // NOTE: is the result of the FE conversion, because there script interpreted as a class and has receiver // TODO: consider removing from here and handle appropriately in the lowering - +field("thisReceiver", valueParameter, isChild = true, nullable = true) // K1 + +field("thisReceiver", valueParameter, nullable = true) // K1 +field("baseClass", irTypeType, nullable = true) // K1 - +listField("explicitCallParameters", variable, mutability = Var, isChild = true) - +listField("implicitReceiversParameters", valueParameter, mutability = Var, isChild = true) + +listField("explicitCallParameters", variable, mutability = Var) + +listField("implicitReceiversParameters", valueParameter, mutability = Var) +listField("providedProperties", propertySymbolType, mutability = Var) - +listField("providedPropertiesParameters", valueParameter, mutability = Var, isChild = true) + +listField("providedPropertiesParameters", valueParameter, mutability = Var) +field("resultProperty", propertySymbolType, nullable = true) - +field("earlierScriptsParameter", valueParameter, nullable = true, isChild = true) + +field("earlierScriptsParameter", valueParameter, nullable = true) +listField("importedScripts", scriptSymbolType, mutability = Var, nullable = true) +listField("earlierScripts", scriptSymbolType, mutability = Var, nullable = true) +field("targetClass", classSymbolType, nullable = true) - +field("constructor", constructor, nullable = true) // K1 + +field("constructor", constructor, nullable = true) { // K1 + needAcceptAndTransform = false + } } val simpleFunction: Element by element(Declaration) { isLeaf = true @@ -586,7 +591,7 @@ object IrTree : AbstractTreeBuilder() { +field("isVar", boolean) +field("isConst", boolean) +field("isLateinit", boolean) - +field("initializer", expression, nullable = true, isChild = true) + +field("initializer", expression, nullable = true) } val packageFragment: Element by element(Declaration) { ownsChildren = false @@ -636,7 +641,9 @@ object IrTree : AbstractTreeBuilder() { parent(metadataSourceOwner) +symbol(fileSymbolType) - +field("module", moduleFragment) + +field("module", moduleFragment) { + needAcceptAndTransform = false + } +field("fileEntry", type(Packages.tree, "IrFileEntry")) } @@ -649,10 +656,12 @@ object IrTree : AbstractTreeBuilder() { parent(attributeContainer) +field("attributeOwnerId", attributeContainer) { + needAcceptAndTransform = false baseDefaultValue = "this" skipInIrFactory() } +field("originalBeforeInline", attributeContainer, nullable = true) { + needAcceptAndTransform = false baseDefaultValue = "null" skipInIrFactory() } @@ -661,7 +670,7 @@ object IrTree : AbstractTreeBuilder() { val statementContainer: Element by element(Expression) { ownsChildren = false - +listField("statements", statement, mutability = MutableList, isChild = true) + +listField("statements", statement, mutability = MutableList) } val body: Element by element(Expression) { needTransformMethod() @@ -677,7 +686,7 @@ object IrTree : AbstractTreeBuilder() { parent(body) +factory - +field("expression", expression, isChild = true) { + +field("expression", expression) { useFieldInIrFactory() } } @@ -703,15 +712,15 @@ object IrTree : AbstractTreeBuilder() { parent(declarationReference) - +field("dispatchReceiver", expression, nullable = true, isChild = true) { + +field("dispatchReceiver", expression, nullable = true) { baseDefaultValue = "null" } - +field("extensionReceiver", expression, nullable = true, isChild = true) { + +field("extensionReceiver", expression, nullable = true) { baseDefaultValue = "null" } +symbol(s) +field("origin", statementOriginType, nullable = true) - +listField("valueArguments", expression.copy(nullable = true), mutability = Array, isChild = true) { + +listField("valueArguments", expression.copy(nullable = true), mutability = Array) { visibility = Visibility.PROTECTED } +listField("typeArguments", irTypeType.copy(nullable = true), mutability = Array) { @@ -831,7 +840,7 @@ object IrTree : AbstractTreeBuilder() { parent(statementContainer) +field("origin", statementOriginType, nullable = true) - +listField("statements", statement, mutability = MutableList, isChild = true) { + +listField("statements", statement, mutability = MutableList) { baseDefaultValue = "ArrayList(2)" } } @@ -870,7 +879,9 @@ object IrTree : AbstractTreeBuilder() { parent(expression) - +field("loop", loop) + +field("loop", loop) { + needAcceptAndTransform = false + } +field("label", string, nullable = true) { baseDefaultValue = "null" } @@ -959,19 +970,19 @@ object IrTree : AbstractTreeBuilder() { val constantPrimitive: Element by element(Expression) { parent(constantValue) - +field("value", const.withArgs("T" to TypeRef.Star), isChild = true) + +field("value", const.withArgs("T" to TypeRef.Star)) } val constantObject: Element by element(Expression) { parent(constantValue) +field("constructor", constructorSymbolType) - +listField("valueArguments", constantValue, mutability = MutableList, isChild = true) + +listField("valueArguments", constantValue, mutability = MutableList) +listField("typeArguments", irTypeType, mutability = MutableList) } val constantArray: Element by element(Expression) { parent(constantValue) - +listField("elements", constantValue, mutability = MutableList, isChild = true) + +listField("elements", constantValue, mutability = MutableList) } val delegatingConstructorCall: Element by element(Expression) { parent(functionAccessExpression) @@ -985,14 +996,14 @@ object IrTree : AbstractTreeBuilder() { parent(dynamicExpression) +field("operator", type(Packages.exprs, "IrDynamicOperator")) - +field("receiver", expression, isChild = true) - +listField("arguments", expression, mutability = MutableList, isChild = true) + +field("receiver", expression) + +listField("arguments", expression, mutability = MutableList) } val dynamicMemberExpression: Element by element(Expression) { parent(dynamicExpression) +field("memberName", string) - +field("receiver", expression, isChild = true) + +field("receiver", expression) } val enumConstructorCall: Element by element(Expression) { parent(functionAccessExpression) @@ -1009,8 +1020,8 @@ object IrTree : AbstractTreeBuilder() { val errorCallExpression: Element by element(Expression) { parent(errorExpression) - +field("explicitReceiver", expression, nullable = true, isChild = true) - +listField("arguments", expression, mutability = MutableList, isChild = true) + +field("explicitReceiver", expression, nullable = true) + +listField("arguments", expression, mutability = MutableList) } val fieldAccessExpression: Element by element(Expression) { nameInVisitorMethod = "FieldAccess" @@ -1020,7 +1031,7 @@ object IrTree : AbstractTreeBuilder() { +symbol(fieldSymbolType, mutable = true) +field("superQualifierSymbol", classSymbolType, nullable = true) - +field("receiver", expression, nullable = true, isChild = true) { + +field("receiver", expression, nullable = true) { baseDefaultValue = "null" } +field("origin", statementOriginType, nullable = true) @@ -1031,7 +1042,7 @@ object IrTree : AbstractTreeBuilder() { val setField: Element by element(Expression) { parent(fieldAccessExpression) - +field("value", expression, isChild = true) + +field("value", expression) } val functionExpression: Element by element(Expression) { transformerReturnType = rootElement @@ -1039,12 +1050,12 @@ object IrTree : AbstractTreeBuilder() { parent(expression) +field("origin", statementOriginType) - +field("function", simpleFunction, isChild = true) + +field("function", simpleFunction) } val getClass: Element by element(Expression) { parent(expression) - +field("argument", expression, isChild = true) + +field("argument", expression) } val instanceInitializerCall: Element by element(Expression) { parent(expression) @@ -1058,10 +1069,10 @@ object IrTree : AbstractTreeBuilder() { parent(expression) +field("origin", statementOriginType, nullable = true) - +field("body", expression, nullable = true, isChild = true) { + +field("body", expression, nullable = true) { baseDefaultValue = "null" } - +field("condition", expression, isChild = true) + +field("condition", expression) +field("label", string, nullable = true) { baseDefaultValue = "null" } @@ -1080,48 +1091,48 @@ object IrTree : AbstractTreeBuilder() { val `return`: Element by element(Expression) { parent(expression) - +field("value", expression, isChild = true) + +field("value", expression) +field("returnTargetSymbol", returnTargetSymbolType) } val stringConcatenation: Element by element(Expression) { parent(expression) - +listField("arguments", expression, mutability = MutableList, isChild = true) + +listField("arguments", expression, mutability = MutableList) } val suspensionPoint: Element by element(Expression) { parent(expression) - +field("suspensionPointIdParameter", variable, isChild = true) - +field("result", expression, isChild = true) - +field("resumeResult", expression, isChild = true) + +field("suspensionPointIdParameter", variable) + +field("result", expression) + +field("resumeResult", expression) } val suspendableExpression: Element by element(Expression) { parent(expression) - +field("suspensionPointId", expression, isChild = true) - +field("result", expression, isChild = true) + +field("suspensionPointId", expression) + +field("result", expression) } val `throw`: Element by element(Expression) { parent(expression) - +field("value", expression, isChild = true) + +field("value", expression) } val `try`: Element by element(Expression) { visitorParameterName = "aTry" parent(expression) - +field("tryResult", expression, isChild = true) - +listField("catches", catch, mutability = MutableList, isChild = true) - +field("finallyExpression", expression, nullable = true, isChild = true) + +field("tryResult", expression) + +listField("catches", catch, mutability = MutableList) + +field("finallyExpression", expression, nullable = true) } val catch: Element by element(Expression) { visitorParameterName = "aCatch" needTransformMethod() transformByChildren = true - +field("catchParameter", variable, isChild = true) - +field("result", expression, isChild = true) + +field("catchParameter", variable) + +field("result", expression) } val typeOperatorCall: Element by element(Expression) { nameInVisitorMethod = "TypeOperator" @@ -1129,7 +1140,7 @@ object IrTree : AbstractTreeBuilder() { parent(expression) +field("operator", type(Packages.exprs, "IrTypeOperator")) - +field("argument", expression, isChild = true) + +field("argument", expression) +field("typeOperand", irTypeType) } val valueAccessExpression: Element by element(Expression) { @@ -1146,14 +1157,14 @@ object IrTree : AbstractTreeBuilder() { val setValue: Element by element(Expression) { parent(valueAccessExpression) - +field("value", expression, isChild = true) + +field("value", expression) } val varargElement: Element by element(Expression) val vararg: Element by element(Expression) { parent(expression) +field("varargElementType", irTypeType) - +listField("elements", varargElement, mutability = MutableList, isChild = true) + +listField("elements", varargElement, mutability = MutableList) } val spreadElement: Element by element(Expression) { visitorParameterName = "spread" @@ -1162,13 +1173,13 @@ object IrTree : AbstractTreeBuilder() { parent(varargElement) - +field("expression", expression, isChild = true) + +field("expression", expression) } val `when`: Element by element(Expression) { parent(expression) +field("origin", statementOriginType, nullable = true) - +listField("branches", branch, mutability = MutableList, isChild = true) + +listField("branches", branch, mutability = MutableList) } val branch: Element by element(Expression) { visitorParameterName = "branch" @@ -1176,8 +1187,8 @@ object IrTree : AbstractTreeBuilder() { needTransformMethod() transformByChildren = true - +field("condition", expression, isChild = true) - +field("result", expression, isChild = true) + +field("condition", expression) + +field("result", expression) } val elseBranch: Element by element(Expression) { visitorParameterName = "branch" 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 d336736675b..4a0b0871c7c 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 @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.generators.tree.addPureAbstractElement import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil.collectPreviouslyGeneratedFiles import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil.removeExtraFilesFromPreviousGeneration -import org.jetbrains.kotlin.ir.generator.model.addWalkableChildren import org.jetbrains.kotlin.ir.generator.model.markLeaves import org.jetbrains.kotlin.ir.generator.print.* import java.io.File @@ -28,7 +27,6 @@ fun main(args: Array) { InterfaceAndAbstractClassConfigurator(model.elements).configureInterfacesAndAbstractClasses() addPureAbstractElement(model.elements, elementBaseType) markLeaves(model.elements) - addWalkableChildren(model.elements) val previouslyGeneratedFiles = collectPreviouslyGeneratedFiles(generationPath) val generatedFiles = sequence { 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 1d73904cb4b..356f7afc442 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 @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.generator.config import org.jetbrains.kotlin.generators.tree.* 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 @@ -14,7 +15,6 @@ import org.jetbrains.kotlin.types.Variance import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty -import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef abstract class AbstractTreeBuilder { private val configurationCallbacks = mutableListOf<() -> Element>() @@ -22,11 +22,11 @@ abstract class AbstractTreeBuilder { abstract val rootElement: Element protected fun Field.skipInIrFactory() { - useInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.No + customUseInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.No } protected fun Field.useFieldInIrFactory(defaultValue: String? = null) { - useInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.Yes(defaultValue) + customUseInIrFactoryStrategy = Field.UseFieldAsParameterInIrFactoryStrategy.Yes(defaultValue) } fun element(category: Element.Category, name: String? = null, initializer: Element.() -> Unit = {}): ElementDelegate { @@ -75,22 +75,18 @@ abstract class AbstractTreeBuilder { type: TypeRefWithNullability, nullable: Boolean = false, mutable: Boolean = true, - isChild: Boolean = false, initializer: SingleField.() -> Unit = {} ): SingleField { - checkChildType(isChild, type, name) - return SingleField(name, type.copy(nullable), mutable, isChild).apply(initializer) + return SingleField(name, type.copy(nullable), mutable).apply(initializer) } protected fun listField( name: String, - elementType: TypeRef, + baseType: TypeRef, nullable: Boolean = false, mutability: ListField.Mutability, - isChild: Boolean = false, initializer: ListField.() -> Unit = {} ): ListField { - checkChildType(isChild, elementType, name) val listType = when (mutability) { ListField.Mutability.MutableList -> StandardTypes.mutableList ListField.Mutability.Array -> StandardTypes.array @@ -98,22 +94,13 @@ abstract class AbstractTreeBuilder { } return ListField( name = name, - baseType = elementType, + baseType = baseType, listType = listType, isNullable = nullable, mutable = mutability == ListField.Mutability.Var, - isChild = isChild, ).apply(initializer) } - private fun checkChildType(isChild: Boolean, type: TypeRef?, name: String) { - if (isChild) { - require(type == null || type is GenericElementOrRef<*, *>) { - "Field $name is a child field but has non-element type $type" - } - } - } - fun build(): Model { val elements = configurationCallbacks.map { it() } return Model(elements, rootElement) diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt index cade4e4f69b..3e40ae62b39 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/model/Model.kt @@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.generator.BASE_PACKAGE import org.jetbrains.kotlin.ir.generator.IrTree import org.jetbrains.kotlin.ir.generator.elementBaseType import org.jetbrains.kotlin.utils.SmartPrinter -import org.jetbrains.kotlin.utils.topologicalSort import org.jetbrains.kotlin.generators.tree.ElementOrRef as GenericElementOrRef import org.jetbrains.kotlin.generators.tree.ElementRef as GenericElementRef @@ -90,8 +89,7 @@ class Element( */ var isLeaf = false - var childrenOrderOverride: List? = null - override var walkableChildren: List = emptyList() + override var childrenOrderOverride: List? = null override var visitorParameterName = category.defaultVisitorParam @@ -104,10 +102,19 @@ class Element( override var hasTransformMethod = false override val hasAcceptChildrenMethod: Boolean - get() = ownsChildren && (isRootElement || walkableChildren.isNotEmpty()) + get() = hasAcceptOrTransformChildrenMethod(Element::walkableChildren) override val hasTransformChildrenMethod: Boolean - get() = ownsChildren && (isRootElement || transformableChildren.isNotEmpty()) + get() = hasAcceptOrTransformChildrenMethod(Element::transformableChildren) + + private fun hasAcceptOrTransformChildrenMethod(walkableOrTransformableChildren: Element.() -> List): Boolean { + if (!ownsChildren) return false + if (!isRootElement && walkableOrTransformableChildren().isEmpty()) return false + val atLeastOneParentHasAcceptOrTransformChildrenMethod = traverseParentsUntil { parent -> + parent != this && parent.hasAcceptOrTransformChildrenMethod(walkableOrTransformableChildren) && !parent.isRootElement + } + return !atLeastOneParentHasAcceptOrTransformChildrenMethod + } var transformByChildren = false var ownsChildren = true // If false, acceptChildren/transformChildren will NOT be generated. @@ -135,7 +142,6 @@ typealias ElementOrRef = GenericElementOrRef sealed class Field( override val name: String, override var isMutable: Boolean, - val isChild: Boolean, ) : AbstractField() { var baseDefaultValue: String? = null var baseGetter: String? = null @@ -147,8 +153,15 @@ sealed class Field( data class Yes(val defaultValue: String?) : UseFieldAsParameterInIrFactoryStrategy() } - var useInIrFactoryStrategy = - if (isChild) UseFieldAsParameterInIrFactoryStrategy.No else UseFieldAsParameterInIrFactoryStrategy.Yes(null) + var customUseInIrFactoryStrategy: UseFieldAsParameterInIrFactoryStrategy? = null + + val useInIrFactoryStrategy: UseFieldAsParameterInIrFactoryStrategy + get() = customUseInIrFactoryStrategy + ?: if (needAcceptAndTransform && containsElement) { + UseFieldAsParameterInIrFactoryStrategy.No + } else { + UseFieldAsParameterInIrFactoryStrategy.Yes(null) + } override val withGetter: Boolean get() = baseGetter != null @@ -175,12 +188,13 @@ sealed class Field( override fun copy() = internalCopy().also(::updateFieldsInCopy) protected fun updateFieldsInCopy(copy: Field) { + copy.needAcceptAndTransform = needAcceptAndTransform copy.useInBaseTransformerDetection = useInBaseTransformerDetection copy.isMutable = isMutable copy.optInAnnotation = optInAnnotation copy.baseDefaultValue = baseDefaultValue copy.baseGetter = baseGetter - copy.useInIrFactoryStrategy = useInIrFactoryStrategy + copy.customUseInIrFactoryStrategy = customUseInIrFactoryStrategy copy.fromParent = fromParent copy.customSetter = customSetter copy.visibility = visibility @@ -195,13 +209,12 @@ class SingleField( name: String, override var typeRef: TypeRefWithNullability, mutable: Boolean, - isChild: Boolean, -) : Field(name, mutable, isChild) { +) : Field(name, mutable) { override fun replaceType(newType: TypeRefWithNullability) = - SingleField(name, newType, isMutable, isChild).also(::updateFieldsInCopy) + SingleField(name, newType, isMutable).also(::updateFieldsInCopy) - override fun internalCopy() = SingleField(name, typeRef, isMutable, isChild) + override fun internalCopy() = SingleField(name, typeRef, isMutable) } class ListField( @@ -210,15 +223,14 @@ class ListField( private val isNullable: Boolean, override val listType: ClassRef, mutable: Boolean, - isChild: Boolean, -) : Field(name, mutable, isChild), AbstractListField { +) : Field(name, mutable), AbstractListField { override val typeRef: ClassRef get() = listType.withArgs(baseType).copy(isNullable) override fun replaceType(newType: TypeRefWithNullability) = copy() - override fun internalCopy() = ListField(name, baseType, isNullable, listType, isMutable, isChild) + override fun internalCopy() = ListField(name, baseType, isNullable, listType, isMutable) enum class Mutability { Var, 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 index 809554a8ac5..453b76c6686 100644 --- 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 @@ -5,8 +5,6 @@ package org.jetbrains.kotlin.ir.generator.model -import org.jetbrains.kotlin.generators.tree.* - typealias Model = org.jetbrains.kotlin.generators.tree.Model internal fun markLeaves(elements: List) { @@ -24,53 +22,3 @@ internal fun markLeaves(elements: List) { el.isLeaf = true } } - - -internal fun addWalkableChildren(elements: List) { - for (element in elements) { - val walkableChildren = mutableMapOf() - - fun visitParents(visited: Element) { - for (parent in visited.elementParents) { - if (!parent.element.ownsChildren) { - for (field in parent.element.fields) { - if (field.isChild) { - walkableChildren[field.name] = field - } - } - - visitParents(parent.element) - } - } - } - - visitParents(element) - - element.fields.filter { it.isChild }.associateByTo(walkableChildren) { it.name } - - element.walkableChildren = reorderIfNecessary(walkableChildren.values.toList(), element.childrenOrderOverride) - } -} - -private fun reorderIfNecessary(fields: List, order: List?): List = - if (order == null) fields else fields.sortedBy { - val position = order.indexOf(it.name) - if (position < 0) order.size else position - } - -private fun iterateElementsParentFirst(elements: List) = sequence { - val pending = elements.sortedBy { it.elementParents.size }.toMutableSet() - pendingLoop@ while (pending.isNotEmpty()) { - val iter = pending.iterator() - while (iter.hasNext()) { - val element = iter.next() - if (element.elementParents.none { it.element in pending }) { - yield(element) - iter.remove() - continue@pendingLoop - } - } - - error("Cannot find next element to process") - } -} diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/FieldContainer.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/FieldContainer.kt index be1a20af3a4..3c4c5e58c66 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/FieldContainer.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/FieldContainer.kt @@ -26,11 +26,19 @@ interface FieldContainer> { val hasTransformChildrenMethod: Boolean get() = false + /** + * Allows to override the order in which the specified children will be visited in `acceptChildren`/`transformChildren` methods. + */ + val childrenOrderOverride: List? + get() = null + /** * The fields on which to run the visitor in generated `acceptChildren` methods. */ val walkableChildren: List - get() = allFields.filter { it.containsElement && !it.withGetter && it.needAcceptAndTransform } + get() = allFields + .filter { it.containsElement && !it.withGetter && it.needAcceptAndTransform } + .reorderFieldsIfNecessary(childrenOrderOverride) /** * The fields on which to run the transformer in generated `transformChildren` methods. diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/utils.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/utils.kt index 98079c7ae0b..4a89b5b9d7d 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/utils.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/utils.kt @@ -5,9 +5,26 @@ package org.jetbrains.kotlin.generators.tree +/** + * Runs [block] on this element and all its parents recursively. + */ fun > Element.traverseParents(block: (Element) -> Unit) { - block(this) - elementParents.forEach { it.element.traverseParents(block) } + traverseParentsUntil { block(it); false } +} + +/** + * Runs [block] on this element and all its parents recursively. + * + * If [block] returns `true` at any point, aborts iteration and returns `true`. + * + * If [block] always returns `false`, visits all the parents and returns `false`. + */ +fun > Element.traverseParentsUntil(block: (Element) -> Boolean): Boolean { + if (block(this)) return true + for (parent in elementParents) { + if (parent.element.traverseParentsUntil(block)) return true + } + return false } /** @@ -46,4 +63,14 @@ operator fun MutableMap>.set(k1: K, k2: V, value: operator fun Map>.get(k1: K, k2: V): U { return getValue(k1).getValue(k2) -} \ No newline at end of file +} + +internal fun > List.reorderFieldsIfNecessary(order: List?): List = + if (order == null) { + this + } else { + sortedBy { + val position = order.indexOf(it.name) + if (position < 0) order.size else position + } + }