From 18ed85c26e428d61c09988a07cf272b341f3edd7 Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Tue, 31 Oct 2023 13:19:28 +0100 Subject: [PATCH] [IR generator] Auto-generate `IrElementTransformerVoid` --- .../ir/visitors/IrElementTransformerVoid.kt | 44 +++--- .../kotlin/ir/generator/CommonTypes.kt | 1 + .../org/jetbrains/kotlin/ir/generator/Main.kt | 2 +- .../print/VisitorsAndTransformers.kt | 142 +++++++++++++++++- .../generators/tree/AbstractVisitorPrinter.kt | 3 +- .../generators/tree/printer/printUtils.kt | 13 ++ 6 files changed, 175 insertions(+), 30 deletions(-) rename compiler/ir/ir.tree/{src => gen}/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt (95%) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt b/compiler/ir/ir.tree/gen/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt similarity index 95% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt rename to compiler/ir/ir.tree/gen/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt index ca223db6f8d..3206dc34d7e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt +++ b/compiler/ir/ir.tree/gen/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt @@ -1,19 +1,11 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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. */ +// This file was generated automatically. See compiler/ir/ir.tree/tree-generator/ReadMe.md. +// DO NOT MODIFY IT MANUALLY. + package org.jetbrains.kotlin.ir.visitors import org.jetbrains.kotlin.ir.IrElement @@ -21,6 +13,9 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* +/** + * Auto-generated by [org.jetbrains.kotlin.ir.generator.print.TransformerVoidPrinter] + */ abstract class IrElementTransformerVoid : IrElementTransformer { protected inline fun T.transformPostfix(body: T.() -> Unit): T { @@ -204,19 +199,19 @@ abstract class IrElementTransformerVoid : IrElementTransformer { open fun visitMemberAccess(expression: IrMemberAccessExpression<*>): IrExpression = visitDeclarationReference(expression) - final override fun visitMemberAccess(expression: IrMemberAccessExpression<*>, data: Nothing?): IrExpression = + final override fun visitMemberAccess(expression: IrMemberAccessExpression<*>, data: Nothing?): IrElement = visitMemberAccess(expression) open fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression = visitMemberAccess(expression) - final override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: Nothing?): IrExpression = + final override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: Nothing?): IrElement = visitFunctionAccess(expression) open fun visitConstructorCall(expression: IrConstructorCall): IrExpression = visitFunctionAccess(expression) - final override fun visitConstructorCall(expression: IrConstructorCall, data: Nothing?): IrExpression = + final override fun visitConstructorCall(expression: IrConstructorCall, data: Nothing?): IrElement = visitConstructorCall(expression) open fun visitSingletonReference(expression: IrGetSingletonValue): IrExpression = @@ -288,13 +283,13 @@ abstract class IrElementTransformerVoid : IrElementTransformer { open fun visitCall(expression: IrCall): IrExpression = visitFunctionAccess(expression) - final override fun visitCall(expression: IrCall, data: Nothing?): IrExpression = + final override fun visitCall(expression: IrCall, data: Nothing?): IrElement = visitCall(expression) open fun visitCallableReference(expression: IrCallableReference<*>): IrExpression = visitMemberAccess(expression) - final override fun visitCallableReference(expression: IrCallableReference<*>, data: Nothing?): IrExpression = + final override fun visitCallableReference(expression: IrCallableReference<*>, data: Nothing?): IrElement = visitCallableReference(expression) open fun visitFunctionReference(expression: IrFunctionReference): IrExpression = @@ -312,7 +307,7 @@ abstract class IrElementTransformerVoid : IrElementTransformer { open fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression = visitCallableReference(expression) - final override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference, data: Nothing?): IrExpression = + final override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference, data: Nothing?): IrElement = visitLocalDelegatedPropertyReference(expression) open fun visitClassReference(expression: IrClassReference): IrExpression = @@ -344,9 +339,8 @@ abstract class IrElementTransformerVoid : IrElementTransformer { open fun visitConstantObject(expression: IrConstantObject): IrConstantValue = visitConstantValue(expression) - final override fun visitConstantObject(expression: IrConstantObject, data: Nothing?): IrConstantValue { - return visitConstantObject(expression) - } + final override fun visitConstantObject(expression: IrConstantObject, data: Nothing?): IrConstantValue = + visitConstantObject(expression) open fun visitConstantArray(expression: IrConstantArray): IrConstantValue = visitConstantValue(expression) @@ -357,7 +351,7 @@ abstract class IrElementTransformerVoid : IrElementTransformer { open fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression = visitFunctionAccess(expression) - final override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Nothing?): IrExpression = + final override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Nothing?): IrElement = visitDelegatingConstructorCall(expression) open fun visitDynamicExpression(expression: IrDynamicExpression): IrExpression = @@ -381,7 +375,7 @@ abstract class IrElementTransformerVoid : IrElementTransformer { open fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression = visitFunctionAccess(expression) - final override fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: Nothing?): IrExpression = + final override fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: Nothing?): IrElement = visitEnumConstructorCall(expression) open fun visitErrorExpression(expression: IrErrorExpression): IrExpression = @@ -557,4 +551,4 @@ abstract class IrElementTransformerVoid : IrElementTransformer { fun IrElement.transformChildrenVoid(transformer: IrElementTransformerVoid) { transformChildren(transformer, null) -} \ No newline at end of file +} diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/CommonTypes.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/CommonTypes.kt index ccb0123be46..3aba79b7303 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/CommonTypes.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/CommonTypes.kt @@ -31,6 +31,7 @@ val statementOriginType = type(exprs, "IrStatementOrigin") val elementVisitorType = type(visitors, "IrElementVisitor") val elementVisitorVoidType = type(visitors, "IrElementVisitorVoid") val elementTransformerType = type(visitors, "IrElementTransformer") +val elementTransformerVoidType = type(visitors, "IrElementTransformerVoid", TypeKind.Class) val typeTransformerType = type(visitors, "IrTypeTransformer") val mutableAnnotationContainerType = type(declarations, "IrMutableAnnotationContainer") val irTypeType = type(types, "IrType") 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 f075afbff74..bbc50be5561 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 @@ -29,8 +29,8 @@ fun main(args: Array) { yield(printVisitor(generationPath, model)) yield(printVisitorVoid(generationPath, model)) yield(printTransformer(generationPath, model)) + yield(printTransformerVoid(generationPath, model)) yield(printTypeVisitor(generationPath, model)) - // IrElementTransformerVoid is too random to autogenerate yield(printFactory(generationPath, model)) }.map { GeneratorsFileUtil.writeFileIfContentChanged(it.file, it.newText, logNotChanged = false) diff --git a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/VisitorsAndTransformers.kt b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/VisitorsAndTransformers.kt index 80441d0a1b0..3bbe57bec8b 100644 --- a/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/VisitorsAndTransformers.kt +++ b/compiler/ir/ir.tree/tree-generator/src/org/jetbrains/kotlin/ir/generator/print/VisitorsAndTransformers.kt @@ -5,11 +5,14 @@ package org.jetbrains.kotlin.ir.generator.print +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.generators.tree.* -import org.jetbrains.kotlin.generators.tree.printer.* +import org.jetbrains.kotlin.generators.tree.printer.FunctionParameter +import org.jetbrains.kotlin.generators.tree.printer.GeneratedFile +import org.jetbrains.kotlin.generators.tree.printer.printFunctionDeclaration +import org.jetbrains.kotlin.generators.tree.printer.printGeneratedType import org.jetbrains.kotlin.ir.generator.* import org.jetbrains.kotlin.ir.generator.model.* -import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly import org.jetbrains.kotlin.utils.SmartPrinter import org.jetbrains.kotlin.utils.withIndent @@ -119,6 +122,139 @@ fun printTransformer(generationPath: File, model: Model): GeneratedFile = TransformerPrinter(printer, visitorType, model.rootElement) } +private class TransformerVoidPrinter( + printer: SmartPrinter, + override val visitorType: ClassRef<*>, +) : AbstractVisitorPrinter(printer, visitSuperTypeByDefault = false) { + + override val visitorTypeParameters: List + get() = emptyList() + + override val visitorSuperType: ClassRef + get() = elementTransformerType.withArgs(visitorDataType) + + override val visitorDataType: TypeRef + get() = StandardTypes.nothing.copy(nullable = true) + + // IrPackageFragment is treated as transformByChildren in IrElementTransformerVoid for historical reasons. + private val Element.isPackageFragment: Boolean + get() = name == IrTree.packageFragment.name + + // Despite IrFile and IrExternalPackageFragment being transformByChildren, we treat them differently in IrElementTransformerVoid + // than in IrElementTransformer for historical reasons. We want to preserve the historical semantics here. + private val Element.isPackageFragmentChild: Boolean + get() = elementParents.any { it.element.isPackageFragment } + + private val Element.transformByChildrenVoid: Boolean + get() = element.transformByChildren || isPackageFragment + + override fun visitMethodReturnType(element: Element): Element = + when { + element.isPackageFragment -> element + element.transformByChildren -> element.getTransformExplicitType() + else -> element.parentInVisitor?.let(this::visitMethodReturnType) ?: element + } + + override val allowTypeParametersInVisitorMethods: Boolean + get() = false + + context(ImportCollector) + override fun SmartPrinter.printAdditionalMethods() { + println() + val typeParameter = TypeVariable("T", listOf(IrTree.rootElement)) + printFunctionDeclaration( + name = "transformPostfix", + parameters = listOf(FunctionParameter("body", Lambda(receiver = typeParameter, returnType = StandardTypes.unit))), + returnType = typeParameter, + typeParameters = listOf(typeParameter), + extensionReceiver = typeParameter, + visibility = Visibility.PROTECTED, + isInline = true, + ) + println(" {") + withIndent { + println("transformChildrenVoid()") + println("this.body()") + println("return this") + } + println("}") + println() + printFunctionDeclaration( + name = "transformChildrenVoid", + parameters = emptyList(), + returnType = StandardTypes.unit, + extensionReceiver = IrTree.rootElement, + visibility = Visibility.PROTECTED, + ) + println(" {") + withIndent { + println("transformChildrenVoid(this@", visitorType.simpleName, ")") + } + println("}") + } + + context(ImportCollector) + override fun printMethodsForElement(element: Element) { + val parent = element.parentInVisitor + if (!element.transformByChildrenVoid && parent == null) return + printer.run { + println() + printVisitMethodDeclaration(element, hasDataParameter = false, modality = Modality.OPEN) + if (element.transformByChildrenVoid && !element.isPackageFragmentChild) { + println(" {") + withIndent { + println(element.visitorParameterName, ".transformChildren(this, null)") + println("return ", element.visitorParameterName) + } + println("}") + } else { + println(" =") + withIndent { + print(parent!!.visitFunctionName, "(", element.visitorParameterName, ")") + if (element.isPackageFragmentChild) { + print(" as ", element.render()) + } + println() + } + } + println() + printVisitMethodDeclaration( + element = element, + modality = Modality.FINAL, + override = true, + returnType = element.getTransformExplicitType(), + ) + println(" =") + withIndent { + println(element.visitFunctionName, "(", element.visitorParameterName, ")") + } + } + } +} + +fun printTransformerVoid(generationPath: File, model: Model): GeneratedFile = + printGeneratedType( + generationPath, + TREE_GENERATOR_README, + elementTransformerVoidType.packageName, + elementTransformerVoidType.simpleName, + ) { + TransformerVoidPrinter(this, elementTransformerVoidType).printVisitor(model.elements) + println() + val transformerParameter = FunctionParameter("transformer", elementTransformerVoidType) + printFunctionDeclaration( + name = "transformChildrenVoid", + parameters = listOf(transformerParameter), + returnType = StandardTypes.unit, + extensionReceiver = IrTree.rootElement, + ) + println(" {") + withIndent { + println("transformChildren(", transformerParameter.name, ", null)") + } + println("}") + } + private class TypeTransformerPrinter( printer: SmartPrinter, override val visitorType: ClassRef<*>, @@ -260,7 +396,7 @@ fun printTypeVisitor(generationPath: File, model: Model): GeneratedFile = } private fun Element.getTransformExplicitType(): Element { - return generateSequence(this) { it.parentInVisitor?.element } + return generateSequence(this) { it.parentInVisitor } .firstNotNullOfOrNull { when { it.transformByChildren -> it.transformerReturnType ?: it diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractVisitorPrinter.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractVisitorPrinter.kt index ba7807ef579..b0cc11135b1 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractVisitorPrinter.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/AbstractVisitorPrinter.kt @@ -68,6 +68,7 @@ abstract class AbstractVisitorPrinter, hasDataParameter: Boolean = true, modality: Modality? = null, override: Boolean = false, + returnType: TypeRef = visitMethodReturnType(element), ) { val visitorParameterType = ElementRef( element, @@ -80,7 +81,7 @@ abstract class AbstractVisitorPrinter, printFunctionDeclaration( name = element.visitFunctionName, parameters = parameters, - returnType = visitMethodReturnType(element), + returnType = returnType, typeParameters = if (allowTypeParametersInVisitorMethods) { element.params } else { diff --git a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/printUtils.kt b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/printUtils.kt index 9f8ee54eba2..680dd78d340 100644 --- a/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/printUtils.kt +++ b/generators/tree-generator-common/src/org/jetbrains/kotlin/generators/tree/printer/printUtils.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.utils.SmartPrinter import org.jetbrains.kotlin.generators.tree.ImportCollector import org.jetbrains.kotlin.generators.tree.render import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly import org.jetbrains.kotlin.utils.addToStdlib.joinToWithBuffer import org.jetbrains.kotlin.utils.withIndent @@ -110,10 +111,16 @@ fun SmartPrinter.printFunctionDeclaration( parameters: List, returnType: TypeRef, typeParameters: List = emptyList(), + extensionReceiver: TypeRef? = null, + visibility: Visibility = Visibility.PUBLIC, modality: Modality? = null, override: Boolean = false, + isInline: Boolean = false, allParametersOnSeparateLines: Boolean = false, ) { + if (visibility != Visibility.PUBLIC) { + print(visibility.name.toLowerCaseAsciiOnly(), " ") + } when (modality) { null -> {} Modality.FINAL -> print("final ") @@ -124,8 +131,14 @@ fun SmartPrinter.printFunctionDeclaration( if (override) { print("override ") } + if (isInline) { + print("inline ") + } print("fun ") print(typeParameters.typeParameters(end = " ")) + if (extensionReceiver != null) { + print(extensionReceiver.render(), ".") + } print(name, "(") if (allParametersOnSeparateLines) {