diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirResolvedImportImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirResolvedImportImpl.kt index 9716a098e26..99f0d895e78 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirResolvedImportImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirResolvedImportImpl.kt @@ -38,8 +38,7 @@ internal class FirResolvedImportImpl( override val importedName: Name? get() = importedFqName?.shortName() - override fun acceptChildren(visitor: FirVisitor, data: D) { - } + override fun acceptChildren(visitor: FirVisitor, data: D) {} override fun transformChildren(transformer: FirTransformer, data: D): FirResolvedImportImpl { return this diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirEmptyExpressionBlock.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirEmptyExpressionBlock.kt index d4f6202972c..99d8f77e748 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirEmptyExpressionBlock.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirEmptyExpressionBlock.kt @@ -31,8 +31,7 @@ class FirEmptyExpressionBlock : FirBlock() { override val statements: List get() = emptyList() - override fun acceptChildren(visitor: FirVisitor, data: D) { - } + override fun acceptChildren(visitor: FirVisitor, data: D) {} override fun transformChildren(transformer: FirTransformer, data: D): FirEmptyExpressionBlock { transformOtherChildren(transformer, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLazyBlockImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLazyBlockImpl.kt index 02ed0196fbe..e638051c414 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLazyBlockImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLazyBlockImpl.kt @@ -31,8 +31,7 @@ internal class FirLazyBlockImpl : FirLazyBlock() { override val statements: List get() = error("FirLazyBlock should be calculated before accessing") - override fun acceptChildren(visitor: FirVisitor, data: D) { - } + override fun acceptChildren(visitor: FirVisitor, data: D) {} override fun transformChildren(transformer: FirTransformer, data: D): FirLazyBlockImpl { transformOtherChildren(transformer, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLazyExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLazyExpressionImpl.kt index aaf0bc92e66..6c17186ebef 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLazyExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirLazyExpressionImpl.kt @@ -28,8 +28,7 @@ internal class FirLazyExpressionImpl( override val annotations: List get() = error("FirLazyExpression should be calculated before accessing") - override fun acceptChildren(visitor: FirVisitor, data: D) { - } + override fun acceptChildren(visitor: FirVisitor, data: D) {} override fun transformChildren(transformer: FirTransformer, data: D): FirLazyExpressionImpl { return this diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Element.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Element.kt index d81a64df5bd..66b52d80259 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Element.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Element.kt @@ -55,6 +55,24 @@ class Element(override val name: String, kind: Kind) : AbstractElement + get() = emptyList() // Use Implementation#walkableChildren instead + + override val transformableChildren: List + get() = emptyList() // Use Implementation#transformableChildren instead + var baseTransformerType: Element? = null val transformerType: Element get() = baseTransformerType ?: this diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Implementation.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Implementation.kt index efd887ba8dc..71b964d08c5 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Implementation.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/model/Implementation.kt @@ -59,6 +59,22 @@ class Implementation(val element: Element, val name: String?) : FieldContainer, } } + override val hasAcceptChildrenMethod: Boolean + get() { + val isInterface = kind == ImplementationKind.Interface || kind == ImplementationKind.SealedInterface + val isAbstract = kind == ImplementationKind.AbstractClass || kind == ImplementationKind.SealedClass + return !isInterface && !isAbstract + } + + override val hasTransformChildrenMethod: Boolean + get() = true + + override val walkableChildren: List + get() = allFields.filter { it.isFirType && !it.withGetter && it.needAcceptAndTransform } + + override val transformableChildren: List + get() = walkableChildren.filter { it.isMutable } + fun addParent(parent: Implementation, arg: Importable? = null) { _parents += ImplementationWithArg(parent, arg) } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/element.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/element.kt index 4739e83fcc8..fcf780b18c7 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/element.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/element.kt @@ -60,22 +60,26 @@ fun SmartPrinter.printElement(element: Element) { } } } - if (allFields.isNotEmpty()) { + + if (hasAcceptMethod) { + if (allFields.isNotEmpty()) { + println() + } + override() + println("fun accept(visitor: FirVisitor, data: D): R =") + withIndent { + println("visitor.visit${element.name}(this, data)") + } + } + + if (hasTransformMethod) { println() - } - - override() - println("fun accept(visitor: FirVisitor, data: D): R =") - withIndent { - println("visitor.visit${element.name}(this, data)") - } - - println() - println("@Suppress(\"UNCHECKED_CAST\")") - override() - println("fun transform(transformer: FirTransformer, data: D): E =") - withIndent { - println("transformer.transform$name(this, data) as E") + println("@Suppress(\"UNCHECKED_CAST\")") + override() + println("fun transform(transformer: FirTransformer, data: D): E =") + withIndent { + println("transformer.transform$name(this, data) as E") + } } fun Field.replaceDeclaration(override: Boolean, overridenType: TypeRef? = null, forceNullable: Boolean = false) { @@ -121,12 +125,16 @@ fun SmartPrinter.printElement(element: Element) { } println() println("fun accept(visitor: FirVisitorVoid) = accept(visitor, null)") - println() - println("fun acceptChildren(visitor: FirVisitor, data: D)") + if (element.hasAcceptChildrenMethod) { + println() + println("fun acceptChildren(visitor: FirVisitor, data: D)") + } println() println("fun acceptChildren(visitor: FirVisitorVoid) = acceptChildren(visitor, null)") - println() - println("fun transformChildren(transformer: FirTransformer, data: D): FirElement") + if (element.hasTransformChildrenMethod) { + println() + println("fun transformChildren(transformer: FirTransformer, data: D): FirElement") + } } } println("}") diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/implementation.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/implementation.kt index 241ec33dec1..d28c0af9d73 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/implementation.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/implementation.kt @@ -138,14 +138,14 @@ fun SmartPrinter.printImplementation(implementation: Implementation) { } fun Field.acceptString(): String = "${name}${call()}accept(visitor, data)" - if (!isInterface && !isAbstract) { + if (hasAcceptChildrenMethod) { print("override fun acceptChildren(visitor: FirVisitor, data: D) {") - if (element.allFirFields.isNotEmpty()) { + val walkableFields = walkableChildren + if (walkableFields.isNotEmpty()) { println() withIndent { - for (field in allFields.filter { it.isFirType }) { - if (field.withGetter || !field.needAcceptAndTransform) continue + for (field in walkableFields) { when (field.name) { "explicitReceiver" -> { val explicitReceiver = implementation["explicitReceiver"]!! @@ -202,65 +202,65 @@ fun SmartPrinter.printImplementation(implementation: Implementation) { println() } - abstract() - print("override fun transformChildren(transformer: FirTransformer, data: D): $typeWithArguments") - if (!isInterface && !isAbstract) { - println(" {") - withIndent { - for (field in allFields) { - when { - !field.isMutable || !field.isFirType || field.withGetter || !field.needAcceptAndTransform -> {} - - field.name == "explicitReceiver" -> { - val explicitReceiver = implementation["explicitReceiver"]!! - val dispatchReceiver = implementation["dispatchReceiver"]!! - val extensionReceiver = implementation["extensionReceiver"]!! - if (explicitReceiver.isMutable) { - println("explicitReceiver = explicitReceiver${explicitReceiver.call()}transform(transformer, data)") - } - if (dispatchReceiver.isMutable) { - println( - """ + if (hasTransformChildrenMethod) { + abstract() + print("override fun transformChildren(transformer: FirTransformer, data: D): $typeWithArguments") + if (!isInterface && !isAbstract) { + println(" {") + withIndent { + for (field in transformableChildren) { + when { + field.name == "explicitReceiver" -> { + val explicitReceiver = implementation["explicitReceiver"]!! + val dispatchReceiver = implementation["dispatchReceiver"]!! + val extensionReceiver = implementation["extensionReceiver"]!! + if (explicitReceiver.isMutable) { + println("explicitReceiver = explicitReceiver${explicitReceiver.call()}transform(transformer, data)") + } + if (dispatchReceiver.isMutable) { + println( + """ |if (dispatchReceiver !== explicitReceiver) { | dispatchReceiver = dispatchReceiver?.transform(transformer, data) | } """.trimMargin(), - ) - } - if (extensionReceiver.isMutable) { - println( - """ + ) + } + if (extensionReceiver.isMutable) { + println( + """ |if (extensionReceiver !== explicitReceiver && extensionReceiver !== dispatchReceiver) { | extensionReceiver = extensionReceiver?.transform(transformer, data) | } """.trimMargin(), - ) + ) + } } - } - field.name in setOf("dispatchReceiver", "extensionReceiver") -> {} + field.name in setOf("dispatchReceiver", "extensionReceiver") -> {} - field.needsSeparateTransform -> { - if (!(element.needTransformOtherChildren && field.needTransformInOtherChildren)) { - println("transform${field.name.replaceFirstChar(Char::uppercaseChar)}(transformer, data)") + field.needsSeparateTransform -> { + if (!(element.needTransformOtherChildren && field.needTransformInOtherChildren)) { + println("transform${field.name.replaceFirstChar(Char::uppercaseChar)}(transformer, data)") + } } - } - !element.needTransformOtherChildren -> { - field.transform() - } + !element.needTransformOtherChildren -> { + field.transform() + } - else -> {} + else -> {} + } } + if (element.needTransformOtherChildren) { + println("transformOtherChildren(transformer, data)") + } + println("return this") } - if (element.needTransformOtherChildren) { - println("transformOtherChildren(transformer, data)") - } - println("return this") + println("}") + } else { + println() } - println("}") - } else { - println() } for (field in allFields) { 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 f70d2385e64..20cdcc09c6b 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 @@ -54,13 +54,22 @@ class Element( var isLeaf = config.isForcedLeaf val childrenOrderOverride: List? = config.childrenOrderOverride - var walkableChildren: List = emptyList() - val transformableChildren get() = walkableChildren.filter { it.transformable } + override var walkableChildren: List = emptyList() + override val transformableChildren get() = walkableChildren.filter { it.transformable } val visitFunName = "visit" + (config.visitorName ?: name).replaceFirstChar(Char::uppercaseChar) val visitorParam = config.visitorParam ?: config.category.defaultVisitorParam - var accept = config.accept - val transform = config.transform + + override var hasAcceptMethod = config.accept + + override val hasTransformMethod = config.transform + + override val hasAcceptChildrenMethod: Boolean + get() = ownsChildren && (isRootElement || walkableChildren.isNotEmpty()) + + override val hasTransformChildrenMethod: Boolean + get() = ownsChildren && (isRootElement || transformableChildren.isNotEmpty()) + val transformByChildren = config.transformByChildren val ownsChildren = config.ownsChildren val generateIrFactoryMethod = config.generateIrFactoryMethod 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 32c256b7ca8..3c5e4c1e5d0 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 @@ -153,7 +153,7 @@ private fun markLeaves(elements: List) { for (el in leaves) { el.isLeaf = true if (el.visitorParent != null) { - el.accept = true + el.hasAcceptMethod = true } } } diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt index 73f8e9e29e5..999830183bd 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/Elements.kt @@ -81,7 +81,7 @@ fun printElements(generationPath: File, model: Model) = sequence { val isRootElement = element.isRootElement val acceptMethodName = "accept" val transformMethodName = "transform" - if (element.accept) { + if (element.hasAcceptMethod) { addFunction(FunSpec.builder(acceptMethodName).apply { addModifiers(if (isRootElement) KModifier.ABSTRACT else KModifier.OVERRIDE) val r = TypeVariableName("R") @@ -114,7 +114,7 @@ fun printElements(generationPath: File, model: Model) = sequence { }.build()) } - if (element.transform) { + if (element.hasTransformMethod) { addFunction(FunSpec.builder(transformMethodName).apply { addModifiers(if (isRootElement) KModifier.ABSTRACT else KModifier.OVERRIDE) val d = TypeVariableName("D") @@ -145,7 +145,7 @@ fun printElements(generationPath: File, model: Model) = sequence { }.build()) } - if (element.ownsChildren && (isRootElement || element.walkableChildren.isNotEmpty())) { + if (element.hasAcceptChildrenMethod) { addFunction(FunSpec.builder("acceptChildren").apply { addModifiers(if (isRootElement) KModifier.ABSTRACT else KModifier.OVERRIDE) val d = TypeVariableName("D") @@ -193,7 +193,7 @@ fun printElements(generationPath: File, model: Model) = sequence { }.build()) } - if (element.ownsChildren && (isRootElement || element.transformableChildren.isNotEmpty())) { + if (element.hasTransformChildrenMethod) { addFunction(FunSpec.builder("transformChildren").apply { addModifiers(if (isRootElement) KModifier.ABSTRACT else KModifier.OVERRIDE) val d = TypeVariableName("D") @@ -233,7 +233,7 @@ fun printElements(generationPath: File, model: Model) = sequence { if (child is SingleField) { @Suppress("UNCHECKED_CAST") val elRef = child.typeRef as GenericElementRef - if (!elRef.element.transform) { + if (!elRef.element.hasTransformMethod) { append(" as %T") if (child.nullable) append("?") args.add(elRef.toPoet()) 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 97881bc02d3..999d5da7912 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 @@ -40,6 +40,10 @@ abstract class AbstractElement : ElementOrRef, F abstract override val allFields: List + abstract override val walkableChildren: List + + abstract override val transformableChildren: List + final override fun get(fieldName: String): Field? { return allFields.firstOrNull { it.name == fieldName } } 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 5aba21a4f89..b18b5173496 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 @@ -8,4 +8,22 @@ package org.jetbrains.kotlin.generators.tree interface FieldContainer { val allFields: List operator fun get(fieldName: String): AbstractField? + + val hasAcceptMethod: Boolean + get() = false + + val hasTransformMethod: Boolean + get() = false + + val hasAcceptChildrenMethod: Boolean + get() = false + + val hasTransformChildrenMethod: Boolean + get() = false + + val walkableChildren: List + get() = emptyList() + + val transformableChildren: List + get() = emptyList() } \ No newline at end of file