From 480c15277de1c4ec76dbbe0f1c2a948a79e89a7d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 16 Feb 2022 01:13:43 +0100 Subject: [PATCH] FIR tree gen: extract interface/class solver to generators --- .../configureInterfacesAndAbstractClasses.kt | 90 +++++++++++++++++++ .../main}/InterfaceAbstractClassSolver.kt | 84 +---------------- 2 files changed, 91 insertions(+), 83 deletions(-) create mode 100644 compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/configureInterfacesAndAbstractClasses.kt rename {compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util => generators/main}/InterfaceAbstractClassSolver.kt (62%) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/configureInterfacesAndAbstractClasses.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/configureInterfacesAndAbstractClasses.kt new file mode 100644 index 00000000000..aacfaab02ef --- /dev/null +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/configureInterfacesAndAbstractClasses.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2019 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.fir.tree.generator.util + +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.Implementation +import org.jetbrains.kotlin.fir.tree.generator.model.ImplementationWithArg +import org.jetbrains.kotlin.fir.tree.generator.model.KindOwner +import org.jetbrains.kotlin.generators.util.Node +import org.jetbrains.kotlin.generators.util.solveGraphForClassVsInterface + +private class NodeImpl(val element: KindOwner) : Node { + override val parents: List + get() = element.allParents.map(::NodeImpl) + + override val origin: NodeImpl + get() = if (element.origin == element) this else NodeImpl(element.origin) + + override fun equals(other: Any?): Boolean = + other is NodeImpl && element == other.element + + override fun hashCode(): Int = + element.hashCode() +} + +fun configureInterfacesAndAbstractClasses(builder: AbstractFirTreeBuilder) { + val elements = collectElements(builder) + val solution = solveGraphForClassVsInterface( + elements, + elements.filter { it.element.kind?.isInterface == true }, + elements.filter { it.element.kind?.isInterface == false }, + ) + updateKinds(elements, solution) + updateSealedKinds(elements) +} + +private fun collectElements(builder: AbstractFirTreeBuilder): List { + return (builder.elements + builder.elements.flatMap { it.allImplementations }).map { NodeImpl(it.origin) } +} + +private fun updateKinds(nodes: List, solution: List) { + val allParents = nodes.flatMapTo(mutableSetOf()) { element -> element.parents.map { it.origin } } + + for (index in solution.indices) { + val isClass = solution[index] + val node = nodes[index].origin + val element = node.element + val existingKind = element.kind + if (isClass) { + if (existingKind == Implementation.Kind.Interface) + throw IllegalStateException(element.toString()) + + if (existingKind == null) { + element.kind = when (element) { + is Implementation -> { + if (node in allParents) + Implementation.Kind.AbstractClass + else + Implementation.Kind.FinalClass + } + is Element -> Implementation.Kind.AbstractClass + else -> throw IllegalStateException() + } + } + } else { + element.kind = Implementation.Kind.Interface + } + } +} + +private fun updateSealedKinds(nodes: Collection) { + for (node in nodes) { + val element = node.element + 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 val KindOwner.origin: KindOwner get() = if (this is ImplementationWithArg) implementation else this diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/InterfaceAbstractClassSolver.kt b/generators/main/InterfaceAbstractClassSolver.kt similarity index 62% rename from compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/InterfaceAbstractClassSolver.kt rename to generators/main/InterfaceAbstractClassSolver.kt index 6508420d7ee..92e882b04c8 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/util/InterfaceAbstractClassSolver.kt +++ b/generators/main/InterfaceAbstractClassSolver.kt @@ -3,13 +3,7 @@ * 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.fir.tree.generator.util - -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.Implementation -import org.jetbrains.kotlin.fir.tree.generator.model.ImplementationWithArg -import org.jetbrains.kotlin.fir.tree.generator.model.KindOwner +package org.jetbrains.kotlin.generators.util /* * Assume that we have element `E` with parents `P1, P2` @@ -27,31 +21,6 @@ interface Node { val origin: Node } -private class NodeImpl(val element: KindOwner) : Node { - override val parents: List - get() = element.allParents.map(::NodeImpl) - - override val origin: NodeImpl - get() = if (element.origin == element) this else NodeImpl(element.origin) - - override fun equals(other: Any?): Boolean = - other is NodeImpl && element == other.element - - override fun hashCode(): Int = - element.hashCode() -} - -fun configureInterfacesAndAbstractClasses(builder: AbstractFirTreeBuilder) { - val elements = collectElements(builder) - val solution = solveGraphForClassVsInterface( - elements, - elements.filter { it.element.kind?.isInterface == true }, - elements.filter { it.element.kind?.isInterface == false }, - ) - updateKinds(elements, solution) - updateSealedKinds(elements) -} - fun solveGraphForClassVsInterface( elements: List, requiredInterfaces: Collection, requiredClasses: Collection, ): List { @@ -72,55 +41,6 @@ private class ElementMapping(val elements: Collection) { val size: Int = elements.size } -private fun collectElements(builder: AbstractFirTreeBuilder): List { - return (builder.elements + builder.elements.flatMap { it.allImplementations }).map { NodeImpl(it.origin) } -} - -private fun updateKinds(nodes: List, solution: List) { - val allParents = nodes.flatMapTo(mutableSetOf()) { element -> element.parents.map { it.origin } } - - for (index in solution.indices) { - val isClass = solution[index] - val node = nodes[index].origin - val element = node.element - val existingKind = element.kind - if (isClass) { - if (existingKind == Implementation.Kind.Interface) - throw IllegalStateException(element.toString()) - - if (existingKind == null) { - element.kind = when (element) { - is Implementation -> { - if (node in allParents) - Implementation.Kind.AbstractClass - else - Implementation.Kind.FinalClass - } - is Element -> Implementation.Kind.AbstractClass - else -> throw IllegalStateException() - } - } - } else { - element.kind = Implementation.Kind.Interface - } - } -} - -private fun updateSealedKinds(nodes: Collection) { - for (node in nodes) { - val element = node.element - 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, @@ -243,5 +163,3 @@ private fun buildGraphs(elements: Collection, elementMapping: ElementMappi } return g to gt } - -private val KindOwner.origin: KindOwner get() = if (this is ImplementationWithArg) implementation else this