diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFieldConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFieldConfigurator.kt index 2fd14cbd3fe..868a8d04a63 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFieldConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFieldConfigurator.kt @@ -86,4 +86,4 @@ abstract class AbstractFieldConfigurator(private val builder.init() builder.applyConfigurations() } -} \ No newline at end of file +} diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFirTreeBuilder.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFirTreeBuilder.kt index 90bc982e9a5..85dc1bde1c5 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFirTreeBuilder.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/context/AbstractFirTreeBuilder.kt @@ -35,6 +35,17 @@ abstract class AbstractFirTreeBuilder { elements += it } + protected fun sealedElement( + name: String, + kind: Element.Kind, + vararg dependencies: Element, + init: Element.() -> Unit = {} + ): Element { + return element(name, kind, *dependencies, init = init).apply { + isSealed = true + } + } + val configurations: MutableMap Unit> = mutableMapOf() fun applyConfigurations() { @@ -62,4 +73,4 @@ fun type(klass: KClass<*>): Type { val fqn = klass.qualifiedName!! val name = klass.simpleName!! return type(fqn.dropLast(name.length + 1), name, exactPackage = true) -} \ No newline at end of file +} 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 e5472f1264c..8b3fc0f4337 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 @@ -35,10 +35,22 @@ interface AbstractElement : FieldContainer, KindOwner { val overridenFields: Map> val useNullableForReplace: Set + val isSealed: Boolean + get() = false + override val allParents: List get() = parents } class Element(val name: String, kind: Kind) : AbstractElement { + companion object { + private val allowedKinds = setOf( + Implementation.Kind.Interface, + Implementation.Kind.SealedInterface, + Implementation.Kind.AbstractClass, + Implementation.Kind.SealedClass + ) + } + override val fields = mutableSetOf() override val type: String = "Fir$name" override val packageName: String = BASE_PACKAGE + kind.packageName.let { if (it.isBlank()) it else "." + it } @@ -50,13 +62,15 @@ class Element(val name: String, kind: Kind) : AbstractElement { override val parentsArguments = mutableMapOf>() override var kind: Implementation.Kind? = null set(value) { - if (value != Implementation.Kind.Interface && value != Implementation.Kind.AbstractClass) { + if (value !in allowedKinds) { throw IllegalArgumentException(value.toString()) } field = value } var _needTransformOtherChildren: Boolean = false + override var isSealed: Boolean = false + override var baseTransformerType: Element? = null override 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 08408b95a62..5d79bb02cd6 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 @@ -79,6 +79,8 @@ class Implementation(val element: Element, val name: String?) : FieldContainer, FinalClass("class", true), OpenClass("open class", true), AbstractClass("abstract class", false), + SealedClass("sealed class", false), + SealedInterface("sealed interface", false), Object("object", false) } } 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 1c3a8ac2e75..2de0a352c22 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 @@ -7,6 +7,7 @@ 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.* +import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType import org.jetbrains.kotlin.fir.tree.generator.util.get import org.jetbrains.kotlin.util.SmartPrinter @@ -35,7 +36,7 @@ fun Element.generateCode(generationPath: File): GeneratedFile { fun SmartPrinter.printElement(element: Element) { with(element) { - val isInterface = kind == Implementation.Kind.Interface + val isInterface = kind == Kind.Interface || kind == Kind.SealedInterface fun abstract() { if (!isInterface) { @@ -53,7 +54,7 @@ fun SmartPrinter.printElement(element: Element) { if (typeArguments.isNotEmpty()) { print(typeArguments.joinToString(", ", "<", ">") { it.toString() }) } - val needPureAbstractElement = !isInterface && !allParents.any { it.kind == Implementation.Kind.AbstractClass } + val needPureAbstractElement = !isInterface && !allParents.any { it.kind == Kind.AbstractClass || it.kind == Kind.SealedClass } if (parents.isNotEmpty() || needPureAbstractElement) { print(" : ") 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 4f34095c3a4..5e1e2fb84fa 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 @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.tree.generator.printer import org.jetbrains.kotlin.fir.tree.generator.model.* +import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType import org.jetbrains.kotlin.util.SmartPrinter import org.jetbrains.kotlin.util.withIndent @@ -57,8 +58,8 @@ fun SmartPrinter.printImplementation(implementation: Implementation) { print("${kind!!.title} $type") print(element.typeParameters) - val isInterface = kind == Implementation.Kind.Interface - val isAbstract = kind == Implementation.Kind.AbstractClass + val isInterface = kind == Kind.Interface || kind == Kind.SealedInterface + val isAbstract = kind == Kind.AbstractClass || kind == Kind.SealedClass fun abstract() { if (isAbstract) { @@ -80,7 +81,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) { } print(" : ") - if (!isInterface && !allParents.any { it.kind == Implementation.Kind.AbstractClass }) { + if (!isInterface && !allParents.any { it.kind == Kind.AbstractClass || it.kind == Kind.SealedClass }) { print("${pureAbstractElementType.type}(), ") } print(allParents.joinToString { "${it.typeWithArguments}${it.kind.braces()}" }) 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 e3fb46e33ca..0063b0be343 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 @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.tree.generator.printer 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.model.Implementation.Kind import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType import java.io.File @@ -85,7 +86,7 @@ private fun List.filterRedundantImports( val KindOwner.needPureAbstractElement: Boolean - get() = (kind != Implementation.Kind.Interface) && !allParents.any { it.kind == Implementation.Kind.AbstractClass } + get() = (kind != Kind.Interface && kind != Kind.SealedInterface) && !allParents.any { it.kind == Kind.AbstractClass || it.kind == Kind.SealedClass } val Field.isVal: Boolean get() = this is FieldList || (this is FieldWithDefault && origin is FieldList) || !isMutable @@ -126,9 +127,9 @@ fun Element.multipleUpperBoundsList(): String { } ?: " " } -fun Implementation.Kind?.braces(): String = when (this) { - Implementation.Kind.Interface -> "" - Implementation.Kind.OpenClass, Implementation.Kind.AbstractClass -> "()" +fun Kind?.braces(): String = when (this) { + Kind.Interface, Kind.SealedInterface -> "" + Kind.OpenClass, Kind.AbstractClass, Kind.SealedClass -> "()" else -> throw IllegalStateException(this.toString()) } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/InterfaceAbstractClassSolver.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/InterfaceAbstractClassSolver.kt index 714ac4541d9..a1396c0c634 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/InterfaceAbstractClassSolver.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/InterfaceAbstractClassSolver.kt @@ -18,6 +18,7 @@ fun configureInterfacesAndAbstractClasses(builder: AbstractFirTreeBuilder) { val solution = solve2sat(elements, elementMapping) processRequirementsFromConfig(solution, elementMapping) updateKinds(solution, elementMapping) + updateSealedKinds(elements) } private class ElementMapping(elements: Collection) { @@ -73,6 +74,20 @@ private fun updateKinds(solution: List, elementMapping: ElementMapping) } } +private fun updateSealedKinds(elements: Collection) { + for (element in elements) { + if (element is Element) { + if (element.isSealed) { + element.kind = when (element.kind) { + Implementation.Kind.AbstractClass -> Implementation.Kind.SealedClass + Implementation.Kind.Interface -> Implementation.Kind.SealedInterface + else -> error("element $element with kind ${element.kind} can not be sealed") + } + } + } + } +} + private fun processRequirementsFromConfig(solution: MutableList, elementMapping: ElementMapping) { fun processParents(element: KindOwner) { val origin = element.origin @@ -177,4 +192,4 @@ private fun buildGraphs(elements: Collection, elementMapping: Element return g to gt } -private val KindOwner.origin: KindOwner get() = if (this is ImplementationWithArg) implementation else this \ No newline at end of file +private val KindOwner.origin: KindOwner get() = if (this is ImplementationWithArg) implementation else this