[Commonizer] ClassSuperTypeCommonizer: Don't find consumed TypeNodes
This commit will also add some simple documentation to this class and its implementation. ^KT-47430
This commit is contained in:
committed by
Space
parent
1e95717b8d
commit
68e7476765
+60
-6
@@ -16,11 +16,33 @@ import org.jetbrains.kotlin.commonizer.mergedtree.findClass
|
|||||||
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
|
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
|
||||||
typealias Supertypes = List<CirType>
|
private typealias Supertypes = List<CirType>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using the [TypeCommonizer] on all supertypes to find the list of common supertypes across
|
||||||
|
* all platforms. This commonizer will also resolve all transitive supertypes to find potential common supertypes.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* // dependencies
|
||||||
|
* interface A
|
||||||
|
* interface B: A
|
||||||
|
*
|
||||||
|
* // target A
|
||||||
|
* class X: A
|
||||||
|
*
|
||||||
|
* // target B
|
||||||
|
* class X: B
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* will commonize to
|
||||||
|
* ```
|
||||||
|
* class X: A // <- common supertype
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
internal class ClassSuperTypeCommonizer(
|
internal class ClassSuperTypeCommonizer(
|
||||||
private val classifiers: CirKnownClassifiers
|
private val classifiers: CirKnownClassifiers
|
||||||
) : SingleInvocationCommonizer<List<CirType>> {
|
) : SingleInvocationCommonizer<Supertypes> {
|
||||||
|
|
||||||
private val typeCommonizer = TypeCommonizer(classifiers)
|
private val typeCommonizer = TypeCommonizer(classifiers)
|
||||||
|
|
||||||
@@ -36,6 +58,28 @@ internal class ClassSuperTypeCommonizer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For every supertype listed in [values] a full [SupertypesTree] will be resolved.
|
||||||
|
* This tree represents the supertype-hierarchy:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* interface A
|
||||||
|
* interface B: A
|
||||||
|
* interface C: B, A
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* will become a tree like
|
||||||
|
* ```
|
||||||
|
* C
|
||||||
|
* |\
|
||||||
|
* | \
|
||||||
|
* B A
|
||||||
|
* |
|
||||||
|
* A
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
private fun resolveSupertypesTree(values: List<Supertypes>): List<SupertypesTree> {
|
private fun resolveSupertypesTree(values: List<Supertypes>): List<SupertypesTree> {
|
||||||
return values.mapIndexed { index: Int, supertypes: Supertypes ->
|
return values.mapIndexed { index: Int, supertypes: Supertypes ->
|
||||||
val classifierIndex = classifiers.classifierIndices[index]
|
val classifierIndex = classifiers.classifierIndices[index]
|
||||||
@@ -45,12 +89,22 @@ internal class ClassSuperTypeCommonizer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds [SupertypesGroup] (a group representing one type for every platform) that will be enqueued for type commonization.
|
||||||
|
* To find out which types shall be grouped this implementation will go through every single node in all trees (BFS!)
|
||||||
|
* If a certain type can be found on all other platforms, then a group is build.
|
||||||
|
* This types and all transitively "covered" supertypes will be marked as 'consumed' and therefore will be 'effectively removed'
|
||||||
|
* from the tree.
|
||||||
|
*
|
||||||
|
* This grouping implementation will also be very careful about *not* grouping two groups that could effectively
|
||||||
|
* represent a 'ClassKind' (to avoid commonizing with two abstract class supertypes)
|
||||||
|
*/
|
||||||
private fun buildSupertypesGroups(trees: List<SupertypesTree>): List<SupertypesGroup> {
|
private fun buildSupertypesGroups(trees: List<SupertypesTree>): List<SupertypesGroup> {
|
||||||
val groups = mutableListOf<SupertypesGroup>()
|
val groups = mutableListOf<SupertypesGroup>()
|
||||||
var allowClassTypes = true
|
var allowClassTypes = true
|
||||||
|
|
||||||
trees.flatMap { tree -> tree.allNodes }.forEach { node ->
|
trees.flatMap { tree -> tree.allNodes }.forEach { node ->
|
||||||
if (node.assignedGroup != null) return@forEach
|
if (node.isConsumed) return@forEach
|
||||||
val candidateGroup = buildTypeGroup(trees, node.type.classifierId) ?: return@forEach
|
val candidateGroup = buildTypeGroup(trees, node.type.classifierId) ?: return@forEach
|
||||||
if (containsAnyClassKind(candidateGroup)) {
|
if (containsAnyClassKind(candidateGroup)) {
|
||||||
if (!allowClassTypes) return@forEach
|
if (!allowClassTypes) return@forEach
|
||||||
@@ -87,7 +141,7 @@ internal class ClassSuperTypeCommonizer(
|
|||||||
group.nodes.forEach { rootNode ->
|
group.nodes.forEach { rootNode ->
|
||||||
rootNode.allNodes.forEach { visitingNode ->
|
rootNode.allNodes.forEach { visitingNode ->
|
||||||
if (visitingNode.type.classifierId in coveredClassifierIds) {
|
if (visitingNode.type.classifierId in coveredClassifierIds) {
|
||||||
visitingNode.assignedGroup = group
|
visitingNode.isConsumed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +149,7 @@ internal class ClassSuperTypeCommonizer(
|
|||||||
|
|
||||||
private fun buildTypeGroup(trees: List<SupertypesTree>, classifierId: CirEntityId): SupertypesGroup? {
|
private fun buildTypeGroup(trees: List<SupertypesTree>, classifierId: CirEntityId): SupertypesGroup? {
|
||||||
val nodes = trees.map { otherTree: SupertypesTree ->
|
val nodes = trees.map { otherTree: SupertypesTree ->
|
||||||
otherTree.allNodes.find { otherNode -> otherNode.type.classifierId == classifierId } ?: return null
|
otherTree.allNodes.find { otherNode -> otherNode.type.classifierId == classifierId && !otherNode.isConsumed } ?: return null
|
||||||
}
|
}
|
||||||
return SupertypesGroup(classifierId, nodes)
|
return SupertypesGroup(classifierId, nodes)
|
||||||
}
|
}
|
||||||
@@ -133,7 +187,7 @@ private class TypeNode(
|
|||||||
val index: CirClassifierIndex,
|
val index: CirClassifierIndex,
|
||||||
val type: CirClassType,
|
val type: CirClassType,
|
||||||
val supertypes: List<TypeNode>,
|
val supertypes: List<TypeNode>,
|
||||||
var assignedGroup: SupertypesGroup? = null
|
var isConsumed: Boolean = false
|
||||||
) {
|
) {
|
||||||
val allNodes: List<TypeNode> by lazy {
|
val allNodes: List<TypeNode> by lazy {
|
||||||
val allSupertypes = transitiveClosure(this, TypeNode::supertypes)
|
val allSupertypes = transitiveClosure(this, TypeNode::supertypes)
|
||||||
|
|||||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ expect abstract class A2() : A1 {
|
|||||||
abstract fun function2(): Int
|
abstract fun function2(): Int
|
||||||
}
|
}
|
||||||
|
|
||||||
expect class A3() : A2, A1 {
|
expect class A3() : A2 {
|
||||||
override val property1: Int
|
override val property1: Int
|
||||||
override val property2: Int
|
override val property2: Int
|
||||||
val property3: Int
|
val property3: Int
|
||||||
|
|||||||
Reference in New Issue
Block a user