[FIR generator] Move Implementation.Kind to common module

This is a step towards commonizing the code generator between
FIR and IR: KT-61970
This commit is contained in:
Sergej Jaskiewicz
2023-09-04 20:23:25 +02:00
committed by Space Team
parent e62343427d
commit 0dd01279da
13 changed files with 95 additions and 64 deletions
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.fir.tree.generator package org.jetbrains.kotlin.fir.tree.generator
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeImplementationConfigurator import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeImplementationConfigurator
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind.Object import org.jetbrains.kotlin.generators.tree.ImplementationKind.Object
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind.OpenClass import org.jetbrains.kotlin.generators.tree.ImplementationKind.OpenClass
object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() { object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() {
fun configureImplementations() { fun configureImplementations() {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.tree.generator.context package org.jetbrains.kotlin.fir.tree.generator.context
import org.jetbrains.kotlin.fir.tree.generator.model.* import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.generators.tree.ImplementationKind
import org.jetbrains.kotlin.generators.tree.Importable import org.jetbrains.kotlin.generators.tree.Importable
abstract class AbstractFieldConfigurator<T : AbstractFirTreeBuilder>(private val builder: T) { abstract class AbstractFieldConfigurator<T : AbstractFirTreeBuilder>(private val builder: T) {
@@ -67,11 +68,11 @@ abstract class AbstractFieldConfigurator<T : AbstractFirTreeBuilder>(private val
} }
fun shouldBeAnInterface() { fun shouldBeAnInterface() {
element.kind = Implementation.Kind.Interface element.kind = ImplementationKind.Interface
} }
fun shouldBeAbstractClass() { fun shouldBeAbstractClass() {
element.kind = Implementation.Kind.AbstractClass element.kind = ImplementationKind.AbstractClass
} }
} }
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.tree.generator.constructClassLikeTypeImport
import org.jetbrains.kotlin.fir.tree.generator.model.* import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.fir.tree.generator.printer.call import org.jetbrains.kotlin.fir.tree.generator.printer.call
import org.jetbrains.kotlin.fir.tree.generator.standardClassIdsType import org.jetbrains.kotlin.fir.tree.generator.standardClassIdsType
import org.jetbrains.kotlin.generators.tree.ImplementationKind
import org.jetbrains.kotlin.generators.tree.Importable import org.jetbrains.kotlin.generators.tree.Importable
abstract class AbstractFirTreeImplementationConfigurator { abstract class AbstractFirTreeImplementationConfigurator {
@@ -180,7 +181,7 @@ abstract class AbstractFirTreeImplementationConfigurator {
} }
} }
var kind: Implementation.Kind? var kind: ImplementationKind?
get() = implementation.kind get() = implementation.kind
set(value) { set(value) {
implementation.kind = value implementation.kind = value
@@ -9,14 +9,11 @@ import org.jetbrains.kotlin.fir.tree.generator.printer.BASE_PACKAGE
import org.jetbrains.kotlin.fir.tree.generator.printer.typeWithArguments import org.jetbrains.kotlin.fir.tree.generator.printer.typeWithArguments
import org.jetbrains.kotlin.fir.tree.generator.util.set import org.jetbrains.kotlin.fir.tree.generator.util.set
import org.jetbrains.kotlin.generators.tree.FieldContainer import org.jetbrains.kotlin.generators.tree.FieldContainer
import org.jetbrains.kotlin.generators.tree.ImplementationKind
import org.jetbrains.kotlin.generators.tree.Importable import org.jetbrains.kotlin.generators.tree.Importable
import org.jetbrains.kotlin.generators.tree.ImplementationKindOwner
interface KindOwner : Importable { interface AbstractElement : FieldContainer, ImplementationKindOwner {
var kind: Implementation.Kind?
val allParents: List<KindOwner>
}
interface AbstractElement : FieldContainer, KindOwner {
val name: String val name: String
val fields: Set<Field> val fields: Set<Field>
val parents: List<AbstractElement> val parents: List<AbstractElement>
@@ -36,16 +33,16 @@ interface AbstractElement : FieldContainer, KindOwner {
val isSealed: Boolean val isSealed: Boolean
get() = false get() = false
override val allParents: List<KindOwner> get() = parents override val allParents: List<ImplementationKindOwner> get() = parents
} }
class Element(override val name: String, kind: Kind) : AbstractElement { class Element(override val name: String, kind: Kind) : AbstractElement {
companion object { companion object {
private val allowedKinds = setOf( private val allowedKinds = setOf(
Implementation.Kind.Interface, ImplementationKind.Interface,
Implementation.Kind.SealedInterface, ImplementationKind.SealedInterface,
Implementation.Kind.AbstractClass, ImplementationKind.AbstractClass,
Implementation.Kind.SealedClass ImplementationKind.SealedClass
) )
} }
@@ -58,7 +55,7 @@ class Element(override val name: String, kind: Kind) : AbstractElement {
override val customImplementations = mutableListOf<Implementation>() override val customImplementations = mutableListOf<Implementation>()
override val typeArguments = mutableListOf<TypeArgument>() override val typeArguments = mutableListOf<TypeArgument>()
override val parentsArguments = mutableMapOf<AbstractElement, MutableMap<Importable, Importable>>() override val parentsArguments = mutableMapOf<AbstractElement, MutableMap<Importable, Importable>>()
override var kind: Implementation.Kind? = null override var kind: ImplementationKind? = null
set(value) { set(value) {
if (value !in allowedKinds) { if (value !in allowedKinds) {
throw IllegalArgumentException(value.toString()) throw IllegalArgumentException(value.toString())
@@ -5,31 +5,29 @@
package org.jetbrains.kotlin.fir.tree.generator.model package org.jetbrains.kotlin.fir.tree.generator.model
import org.jetbrains.kotlin.generators.tree.ArbitraryImportable import org.jetbrains.kotlin.generators.tree.*
import org.jetbrains.kotlin.generators.tree.FieldContainer
import org.jetbrains.kotlin.generators.tree.Importable
class ImplementationWithArg( class ImplementationWithArg(
val implementation: Implementation, val implementation: Implementation,
val argument: Importable? val argument: Importable?
) : FieldContainer by implementation, KindOwner by implementation { ) : FieldContainer by implementation, ImplementationKindOwner by implementation {
val element: Element get() = implementation.element val element: Element get() = implementation.element
} }
class Implementation(val element: Element, val name: String?) : FieldContainer, KindOwner { class Implementation(val element: Element, val name: String?) : FieldContainer, ImplementationKindOwner {
private val _parents = mutableListOf<ImplementationWithArg>() private val _parents = mutableListOf<ImplementationWithArg>()
val parents: List<ImplementationWithArg> get() = _parents val parents: List<ImplementationWithArg> get() = _parents
override val allParents: List<KindOwner> get() = listOf(element) + parents override val allParents: List<ImplementationKindOwner> get() = listOf(element) + parents
val isDefault = name == null val isDefault = name == null
override val type = name ?: element.type + "Impl" override val type = name ?: element.type + "Impl"
override val allFields = element.allFields.toMutableList().mapTo(mutableListOf()) { override val allFields = element.allFields.toMutableList().mapTo(mutableListOf()) {
FieldWithDefault(it) FieldWithDefault(it)
} }
override var kind: Kind? = null override var kind: ImplementationKind? = null
set(value) { set(value) {
field = value field = value
if (kind != Kind.FinalClass) { if (kind != ImplementationKind.FinalClass) {
isPublic = true isPublic = true
} }
if (value?.hasLeafBuilder == true) { if (value?.hasLeafBuilder == true) {
@@ -78,13 +76,7 @@ class Implementation(val element: Element, val name: String?) : FieldContainer,
val fieldsWithoutDefault by lazy { allFields.filter { it.defaultValueInImplementation == null } } val fieldsWithoutDefault by lazy { allFields.filter { it.defaultValueInImplementation == null } }
val fieldsWithDefault by lazy { allFields.filter { it.defaultValueInImplementation != null } } val fieldsWithDefault by lazy { allFields.filter { it.defaultValueInImplementation != null } }
enum class Kind(val title: String, val hasLeafBuilder: Boolean, val isInterface: Boolean) {
Interface("interface", hasLeafBuilder = false, isInterface = true),
FinalClass("class", hasLeafBuilder = true, isInterface = false),
OpenClass("open class", hasLeafBuilder = true, isInterface = false),
AbstractClass("abstract class", hasLeafBuilder = false, isInterface = false),
SealedClass("sealed class", hasLeafBuilder = false, isInterface = false),
SealedInterface("sealed interface", hasLeafBuilder = false, isInterface = true),
Object("object", hasLeafBuilder = false, isInterface = false),
}
} }
val ImplementationKind.hasLeafBuilder: Boolean
get() = this == ImplementationKind.FinalClass || this == ImplementationKind.OpenClass
@@ -8,7 +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.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.Element import org.jetbrains.kotlin.fir.tree.generator.model.Element
import org.jetbrains.kotlin.fir.tree.generator.model.Field import org.jetbrains.kotlin.fir.tree.generator.model.Field
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind import org.jetbrains.kotlin.generators.tree.ImplementationKind
import org.jetbrains.kotlin.generators.tree.Importable import org.jetbrains.kotlin.generators.tree.Importable
import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType
import org.jetbrains.kotlin.fir.tree.generator.util.get import org.jetbrains.kotlin.fir.tree.generator.util.get
@@ -37,7 +37,7 @@ fun Element.generateCode(generationPath: File): GeneratedFile {
fun SmartPrinter.printElement(element: Element) { fun SmartPrinter.printElement(element: Element) {
with(element) { with(element) {
val isInterface = kind == Kind.Interface || kind == Kind.SealedInterface val isInterface = kind == ImplementationKind.Interface || kind == ImplementationKind.SealedInterface
fun abstract() { fun abstract() {
if (!isInterface) { if (!isInterface) {
print("abstract ") print("abstract ")
@@ -54,7 +54,7 @@ fun SmartPrinter.printElement(element: Element) {
if (typeArguments.isNotEmpty()) { if (typeArguments.isNotEmpty()) {
print(typeArguments.joinToString(", ", "<", ">") { it.toString() }) print(typeArguments.joinToString(", ", "<", ">") { it.toString() })
} }
val needPureAbstractElement = !isInterface && !allParents.any { it.kind == Kind.AbstractClass || it.kind == Kind.SealedClass } val needPureAbstractElement = !isInterface && !allParents.any { it.kind == ImplementationKind.AbstractClass || it.kind == ImplementationKind.SealedClass }
if (parents.isNotEmpty() || needPureAbstractElement) { if (parents.isNotEmpty() || needPureAbstractElement) {
print(" : ") print(" : ")
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.fir.tree.generator.printer package org.jetbrains.kotlin.fir.tree.generator.printer
import org.jetbrains.kotlin.fir.tree.generator.model.* import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind import org.jetbrains.kotlin.generators.tree.ImplementationKind
import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType
import org.jetbrains.kotlin.generators.tree.Importable import org.jetbrains.kotlin.generators.tree.Importable
import org.jetbrains.kotlin.utils.SmartPrinter import org.jetbrains.kotlin.utils.SmartPrinter
@@ -70,8 +70,8 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
print("${kind!!.title} $type") print("${kind!!.title} $type")
print(element.typeParameters) print(element.typeParameters)
val isInterface = kind == Kind.Interface || kind == Kind.SealedInterface val isInterface = kind == ImplementationKind.Interface || kind == ImplementationKind.SealedInterface
val isAbstract = kind == Kind.AbstractClass || kind == Kind.SealedClass val isAbstract = kind == ImplementationKind.AbstractClass || kind == ImplementationKind.SealedClass
fun abstract() { fun abstract() {
if (isAbstract) { if (isAbstract) {
@@ -97,7 +97,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
} }
print(" : ") print(" : ")
if (!isInterface && !allParents.any { it.kind == Kind.AbstractClass || it.kind == Kind.SealedClass }) { if (!isInterface && !allParents.any { it.kind == ImplementationKind.AbstractClass || it.kind == ImplementationKind.SealedClass }) {
print("${pureAbstractElementType.type}(), ") print("${pureAbstractElementType.type}(), ")
} }
print(allParents.joinToString { "${it.typeWithArguments}${it.kind.braces()}" }) print(allParents.joinToString { "${it.typeWithArguments}${it.kind.braces()}" })
@@ -8,9 +8,10 @@ package org.jetbrains.kotlin.fir.tree.generator.printer
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.firImplementationDetailType import org.jetbrains.kotlin.fir.tree.generator.firImplementationDetailType
import org.jetbrains.kotlin.fir.tree.generator.model.* import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation.Kind import org.jetbrains.kotlin.generators.tree.ImplementationKind
import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType import org.jetbrains.kotlin.fir.tree.generator.pureAbstractElementType
import org.jetbrains.kotlin.generators.tree.Importable import org.jetbrains.kotlin.generators.tree.Importable
import org.jetbrains.kotlin.generators.tree.ImplementationKindOwner
import java.io.File import java.io.File
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
@@ -113,8 +114,8 @@ private fun List<String>.filterRedundantImports(
} }
val KindOwner.needPureAbstractElement: Boolean val ImplementationKindOwner.needPureAbstractElement: Boolean
get() = (kind != Kind.Interface && kind != Kind.SealedInterface) && !allParents.any { it.kind == Kind.AbstractClass || it.kind == Kind.SealedClass } get() = (kind != ImplementationKind.Interface && kind != ImplementationKind.SealedInterface) && !allParents.any { it.kind == ImplementationKind.AbstractClass || it.kind == ImplementationKind.SealedClass }
val Field.isVal: Boolean val Field.isVal: Boolean
@@ -159,9 +160,9 @@ fun Element.multipleUpperBoundsList(): String {
} ?: " " } ?: " "
} }
fun Kind?.braces(): String = when (this) { fun ImplementationKind?.braces(): String = when (this) {
Kind.Interface, Kind.SealedInterface -> "" ImplementationKind.Interface, ImplementationKind.SealedInterface -> ""
Kind.OpenClass, Kind.AbstractClass, Kind.SealedClass -> "()" ImplementationKind.OpenClass, ImplementationKind.AbstractClass, ImplementationKind.SealedClass -> "()"
else -> throw IllegalStateException(this.toString()) else -> throw IllegalStateException(this.toString())
} }
@@ -6,14 +6,14 @@
package org.jetbrains.kotlin.fir.tree.generator.util package org.jetbrains.kotlin.fir.tree.generator.util
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation import org.jetbrains.kotlin.generators.tree.ImplementationKind
import java.io.File import java.io.File
// It's used to generate a graph in dot format (it's useful for debugging) // It's used to generate a graph in dot format (it's useful for debugging)
@Suppress("unused") @Suppress("unused")
fun printHierarchyGraph(builder: AbstractFirTreeBuilder) { fun printHierarchyGraph(builder: AbstractFirTreeBuilder) {
fun Implementation.Kind.toColor(): String = when (this) { fun ImplementationKind.toColor(): String = when (this) {
Implementation.Kind.Interface -> "green" ImplementationKind.Interface -> "green"
else -> "red" else -> "red"
} }
@@ -25,7 +25,7 @@ fun printHierarchyGraph(builder: AbstractFirTreeBuilder) {
} }
} }
val (interfaces, classes) = elements.partition { it.kind == Implementation.Kind.Interface } val (interfaces, classes) = elements.partition { it.kind == ImplementationKind.Interface }
println("Interfaces: ${interfaces.size}") println("Interfaces: ${interfaces.size}")
println("Classes: ${classes.size}") println("Classes: ${classes.size}")
@@ -6,14 +6,13 @@
package org.jetbrains.kotlin.fir.tree.generator.util package org.jetbrains.kotlin.fir.tree.generator.util
import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder import org.jetbrains.kotlin.fir.tree.generator.context.AbstractFirTreeBuilder
import org.jetbrains.kotlin.fir.tree.generator.model.Element import org.jetbrains.kotlin.fir.tree.generator.model.*
import org.jetbrains.kotlin.fir.tree.generator.model.Implementation import org.jetbrains.kotlin.generators.tree.ImplementationKindOwner
import org.jetbrains.kotlin.fir.tree.generator.model.ImplementationWithArg import org.jetbrains.kotlin.generators.tree.ImplementationKind
import org.jetbrains.kotlin.fir.tree.generator.model.KindOwner
import org.jetbrains.kotlin.generators.util.Node import org.jetbrains.kotlin.generators.util.Node
import org.jetbrains.kotlin.generators.util.solveGraphForClassVsInterface import org.jetbrains.kotlin.generators.util.solveGraphForClassVsInterface
private class NodeImpl(val element: KindOwner) : Node { private class NodeImpl(val element: ImplementationKindOwner) : Node {
override val parents: List<Node> override val parents: List<Node>
get() = element.allParents.map(::NodeImpl) get() = element.allParents.map(::NodeImpl)
@@ -51,23 +50,23 @@ private fun updateKinds(nodes: List<NodeImpl>, solution: List<Boolean>) {
val element = node.element val element = node.element
val existingKind = element.kind val existingKind = element.kind
if (isClass) { if (isClass) {
if (existingKind == Implementation.Kind.Interface) if (existingKind == ImplementationKind.Interface)
throw IllegalStateException(element.toString()) throw IllegalStateException(element.toString())
if (existingKind == null) { if (existingKind == null) {
element.kind = when (element) { element.kind = when (element) {
is Implementation -> { is Implementation -> {
if (node in allParents) if (node in allParents)
Implementation.Kind.AbstractClass ImplementationKind.AbstractClass
else else
Implementation.Kind.FinalClass ImplementationKind.FinalClass
} }
is Element -> Implementation.Kind.AbstractClass is Element -> ImplementationKind.AbstractClass
else -> throw IllegalStateException() else -> throw IllegalStateException()
} }
} }
} else { } else {
element.kind = Implementation.Kind.Interface element.kind = ImplementationKind.Interface
} }
} }
} }
@@ -78,8 +77,8 @@ private fun updateSealedKinds(nodes: Collection<NodeImpl>) {
if (element is Element) { if (element is Element) {
if (element.isSealed) { if (element.isSealed) {
element.kind = when (element.kind) { element.kind = when (element.kind) {
Implementation.Kind.AbstractClass -> Implementation.Kind.SealedClass ImplementationKind.AbstractClass -> ImplementationKind.SealedClass
Implementation.Kind.Interface -> Implementation.Kind.SealedInterface ImplementationKind.Interface -> ImplementationKind.SealedInterface
else -> error("element $element with kind ${element.kind} can not be sealed") else -> error("element $element with kind ${element.kind} can not be sealed")
} }
} }
@@ -87,4 +86,4 @@ private fun updateSealedKinds(nodes: Collection<NodeImpl>) {
} }
} }
private val KindOwner.origin: KindOwner get() = if (this is ImplementationWithArg) implementation else this private val ImplementationKindOwner.origin: ImplementationKindOwner get() = if (this is ImplementationWithArg) implementation else this
@@ -0,0 +1,19 @@
/*
* 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.
*/
package org.jetbrains.kotlin.generators.tree
enum class ImplementationKind(val title: String, val typeKind: TypeKind) {
Interface("interface", TypeKind.Interface),
FinalClass("class", TypeKind.Class),
OpenClass("open class", TypeKind.Class),
AbstractClass("abstract class", TypeKind.Class),
SealedClass("sealed class", TypeKind.Class),
SealedInterface("sealed interface", TypeKind.Interface),
Object("object", TypeKind.Class);
val isInterface: Boolean
get() = typeKind == TypeKind.Interface
}
@@ -0,0 +1,11 @@
/*
* 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.
*/
package org.jetbrains.kotlin.generators.tree
interface ImplementationKindOwner : Importable {
var kind: ImplementationKind?
val allParents: List<ImplementationKindOwner>
}
@@ -0,0 +1,10 @@
/*
* 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.
*/
package org.jetbrains.kotlin.generators.tree
enum class TypeKind {
Class, Interface
}