diff --git a/compiler/fir/tree/tree-generator/build.gradle.kts b/compiler/fir/tree/tree-generator/build.gradle.kts index 7324a7e7cfd..79b273788ac 100644 --- a/compiler/fir/tree/tree-generator/build.gradle.kts +++ b/compiler/fir/tree/tree-generator/build.gradle.kts @@ -11,6 +11,7 @@ val compileOnly by configurations runtimeOnly.extendsFrom(compileOnly) dependencies { + implementation(project(":generators")) implementation(project(":core:compiler.common")) implementation(project(":compiler:frontend.common")) implementation(project(":compiler:fir:cones")) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Main.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Main.kt index 922cf17a26d..3570055ea64 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Main.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Main.kt @@ -5,8 +5,9 @@ package org.jetbrains.kotlin.fir.tree.generator -import org.jetbrains.kotlin.fir.tree.generator.printer.printElements +import org.jetbrains.kotlin.fir.tree.generator.printer.generateElements import org.jetbrains.kotlin.fir.tree.generator.util.* +import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil import java.io.File @@ -19,8 +20,9 @@ fun main(args: Array) { ImplementationConfigurator.configureImplementations() configureInterfacesAndAbstractClasses(FirTreeBuilder) BuilderConfigurator.configureBuilders() - removePreviousGeneratedFiles(generationPath) - printElements(FirTreeBuilder, generationPath) -// printFieldUsageTable(FirTreeBuilder) -// printHierarchyGraph(FirTreeBuilder) + val previouslyGeneratedFiles = collectPreviouslyGeneratedFiles(generationPath) + val generatedFiles = generateElements(FirTreeBuilder, generationPath) + generatedFiles.forEach { GeneratorsFileUtil.writeFileIfContentChanged(it.file, it.newText, logNotChanged = false) } + removeExtraFilesFromPreviousGeneration(previouslyGeneratedFiles, generatedFiles.map { it.file }) } + diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt index 25bd5c33832..0469f8c03ad 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/builder.kt @@ -9,11 +9,11 @@ import org.jetbrains.kotlin.fir.tree.generator.declarationAttributesType import org.jetbrains.kotlin.fir.tree.generator.model.* import java.io.File -fun Builder.generateCode(generationPath: File) { +fun Builder.generateCode(generationPath: File): GeneratedFile { val dir = generationPath.resolve(packageName.replace(".", "/")) - dir.mkdirs() val file = File(dir, "$type.kt") - file.useSmartPrinter { + val stringBuilder = StringBuilder() + SmartPrinter(stringBuilder).apply { printCopyright() println("package $packageName") println() @@ -25,6 +25,7 @@ fun Builder.generateCode(generationPath: File) { printGeneratedMessage() printBuilder(this@generateCode) } + return GeneratedFile(file, stringBuilder.toString()) } private fun SmartPrinter.printBuilder(builder: Builder) { 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 ed18ca26e6f..6dd34ae87a2 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 @@ -12,11 +12,11 @@ import org.jetbrains.kotlin.fir.tree.generator.util.get import java.io.File -fun Element.generateCode(generationPath: File) { +fun Element.generateCode(generationPath: File): GeneratedFile { val dir = generationPath.resolve(packageName.replace(".", "/")) - dir.mkdirs() val file = File(dir, "$type.kt") - file.useSmartPrinter { + val stringBuilder = StringBuilder() + SmartPrinter(stringBuilder).apply { printCopyright() println("package $packageName") println() @@ -28,6 +28,7 @@ fun Element.generateCode(generationPath: File) { printGeneratedMessage() printElement(this@generateCode) } + return GeneratedFile(file, stringBuilder.toString()) } fun SmartPrinter.printElement(element: Element) { 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 031d4fe7e24..5008e12f2e7 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 @@ -10,11 +10,11 @@ import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType import java.io.File -fun Implementation.generateCode(generationPath: File) { +fun Implementation.generateCode(generationPath: File): GeneratedFile { val dir = generationPath.resolve(packageName.replace(".", "/")) - dir.mkdirs() val file = File(dir, "$type.kt") - file.useSmartPrinter { + val stringBuilder = StringBuilder() + SmartPrinter(stringBuilder).apply { printCopyright() println("package $packageName") println() @@ -26,6 +26,7 @@ fun Implementation.generateCode(generationPath: File) { printGeneratedMessage() printImplementation(this@generateCode) } + return GeneratedFile(file, stringBuilder.toString()) } fun SmartPrinter.printImplementation(implementation: Implementation) { diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/main.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/main.kt index d2881db706a..bea66e0830c 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/main.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/main.kt @@ -19,15 +19,17 @@ val GENERATED_MESSAGE = """ */ """.trimIndent() -fun printElements(builder: AbstractFirTreeBuilder, generationPath: File) { - builder.elements.forEach { it.generateCode(generationPath) } - builder.elements.flatMap { it.allImplementations }.forEach { it.generateCode(generationPath) } - builder.elements.flatMap { it.allImplementations }.mapNotNull { it.builder }.forEach { it.generateCode(generationPath) } - builder.intermediateBuilders.forEach { it.generateCode(generationPath) } +fun generateElements(builder: AbstractFirTreeBuilder, generationPath: File): List { + val generatedFiles = mutableListOf() + builder.elements.mapTo(generatedFiles) { it.generateCode(generationPath) } + builder.elements.flatMap { it.allImplementations }.mapTo(generatedFiles) { it.generateCode(generationPath) } + builder.elements.flatMap { it.allImplementations }.mapNotNull { it.builder }.mapTo(generatedFiles) { it.generateCode(generationPath) } + builder.intermediateBuilders.mapTo(generatedFiles) { it.generateCode(generationPath) } - printVisitor(builder.elements, generationPath) - printVisitorVoid(builder.elements, generationPath) - printTransformer(builder.elements, generationPath) + generatedFiles += printVisitor(builder.elements, generationPath) + generatedFiles += printVisitorVoid(builder.elements, generationPath) + generatedFiles += printTransformer(builder.elements, generationPath) + return generatedFiles } fun SmartPrinter.printCopyright() { diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/transformer.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/transformer.kt index b9e8bd8f538..2b9565e36d4 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/transformer.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/transformer.kt @@ -11,10 +11,11 @@ import org.jetbrains.kotlin.fir.tree.generator.model.Element import java.io.File -fun printTransformer(elements: List, generationPath: File) { +fun printTransformer(elements: List, generationPath: File): GeneratedFile { val dir = File(generationPath, VISITOR_PACKAGE.replace(".", "/")) - dir.mkdirs() - File(dir, "FirTransformer.kt").useSmartPrinter { + val file = File(dir, "FirTransformer.kt") + val stringBuilder = StringBuilder() + SmartPrinter(stringBuilder).apply { printCopyright() println("package $VISITOR_PACKAGE") println() @@ -62,4 +63,5 @@ fun printTransformer(elements: List, generationPath: File) { } println("}") } + return GeneratedFile(file, stringBuilder.toString()) } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/utils.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/utils.kt index 59e535efbda..2a2c1947e75 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/utils.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/utils.kt @@ -10,6 +10,10 @@ import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder import org.jetbrains.kotlin.fir.tree.generator.firImplementationDetailType import org.jetbrains.kotlin.fir.tree.generator.model.* import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType +import org.jetbrains.kotlin.utils.addToStdlib.runIf +import java.io.File + +class GeneratedFile(val file: File, val newText: String) enum class ImportKind(val postfix: String) { Element(""), Implementation(".impl"), Builder(".builder") diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/visitor.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/visitor.kt index bad81737cc2..8d1fc2162be 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/visitor.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/visitor.kt @@ -7,14 +7,13 @@ package org.jetbrains.kotlin.fir.tree.generator.printer import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder import org.jetbrains.kotlin.fir.tree.generator.model.Element - import java.io.File -import java.io.PrintWriter -fun printVisitor(elements: List, generationPath: File) { +fun printVisitor(elements: List, generationPath: File): GeneratedFile { val dir = File(generationPath, VISITOR_PACKAGE.replace(".", "/")) - dir.mkdirs() - File(dir, "FirVisitor.kt").useSmartPrinter { + val file = File(dir, "FirVisitor.kt") + val stringBuilder = StringBuilder() + SmartPrinter(stringBuilder).apply { printCopyright() println("package $VISITOR_PACKAGE") println() @@ -37,13 +36,15 @@ fun printVisitor(elements: List, generationPath: File) { popIndent() println("}") } + return GeneratedFile(file, stringBuilder.toString()) } -fun printVisitorVoid(elements: List, generationPath: File) { +fun printVisitorVoid(elements: List, generationPath: File): GeneratedFile { val dir = File(generationPath, VISITOR_PACKAGE.replace(".", "/")) - dir.mkdirs() - File(dir, "FirVisitorVoid.kt").useSmartPrinter { + val file = File(dir, "FirVisitorVoid.kt") + val stringBuilder = StringBuilder() + SmartPrinter(stringBuilder).apply { printCopyright() println("package $VISITOR_PACKAGE") println() @@ -83,4 +84,5 @@ fun printVisitorVoid(elements: List, generationPath: File) { } println("}") } + return GeneratedFile(file, stringBuilder.toString()) } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/Cleanuper.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/Cleanuper.kt index 5279ff9c051..bcd5ad8b220 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/Cleanuper.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/Cleanuper.kt @@ -6,12 +6,25 @@ package org.jetbrains.kotlin.fir.tree.generator.util import org.jetbrains.kotlin.fir.tree.generator.printer.GENERATED_MESSAGE +import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil import java.io.File -fun removePreviousGeneratedFiles(generationPath: File) { - generationPath.walkTopDown().forEach { - if (it.isFile && it.readText().contains(GENERATED_MESSAGE)) { - it.delete() +fun collectPreviouslyGeneratedFiles(generationPath: File): List { + return generationPath.walkTopDown().filter { + it.isFile && it.readText().contains(GENERATED_MESSAGE) + }.toList() +} + +fun removeExtraFilesFromPreviousGeneration(previouslyGeneratedFiles: List, generatedFiles: List) { + val generatedFilesPath = generatedFiles.mapTo(mutableSetOf()) { it.absolutePath } + + for (file in previouslyGeneratedFiles) { + if (file.absolutePath !in generatedFilesPath) { + if (GeneratorsFileUtil.isTeamCityBuild) { + GeneratorsFileUtil.assertTeamCityMode() + } + println("Deleted: ${file.absolutePath}") + file.delete() } } -} \ No newline at end of file +} diff --git a/generators/main/GeneratorsFileUtil.kt b/generators/main/GeneratorsFileUtil.kt index 454c51c9b28..b1073fb75e9 100644 --- a/generators/main/GeneratorsFileUtil.kt +++ b/generators/main/GeneratorsFileUtil.kt @@ -11,7 +11,7 @@ import java.io.IOException import kotlin.io.path.* object GeneratorsFileUtil { - private val isTeamCityBuild: Boolean = System.getProperty("TEAMCITY_VERSION") != null + val isTeamCityBuild: Boolean = System.getProperty("TEAMCITY_VERSION") != null @OptIn(ExperimentalPathApi::class) @JvmStatic @@ -47,7 +47,7 @@ object GeneratorsFileUtil { println() } - private fun assertTeamCityMode(): Nothing { + fun assertTeamCityMode(): Nothing { throw IllegalStateException("You should commit all newly generated files before pushing them to TeamCity") }