[Commonizer] ClassSuperTypeCommonizer: Include transitive supertypes
This commit still has some left-over todos that shall be done in a separate commit. TODOs: - CirClassifierIndex is calculated once too often - Reconsider position of classifierIndices in 'CirKnownClassifiers' - Add documentation/description to complicated 'ClassSuperTypeCommonizer' - Add documentation/description to CirSupertypesResolver ^KT-47430 Verification Pending
This commit is contained in:
committed by
Space
parent
1857096071
commit
dff392f2cd
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.commonizer.cir
|
||||
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.findClass
|
||||
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
|
||||
internal interface CirSupertypesResolver {
|
||||
fun supertypes(type: CirClassType): Set<CirClassType>
|
||||
}
|
||||
|
||||
internal fun CirSupertypesResolver.allSupertypes(type: CirClassType): Set<CirClassType> {
|
||||
return transitiveClosure(type, this::supertypes)
|
||||
}
|
||||
|
||||
internal class SimpleCirSupertypesResolver(
|
||||
private val classifiers: CirClassifierIndex,
|
||||
private val dependencies: CirProvidedClassifiers,
|
||||
) : CirSupertypesResolver {
|
||||
|
||||
override fun supertypes(type: CirClassType): Set<CirClassType> {
|
||||
classifiers.findClass(type.classifierId)?.let { classifier ->
|
||||
return supertypes(type, classifier)
|
||||
}
|
||||
|
||||
dependencies.classifier(type.classifierId)?.let { classifier ->
|
||||
if (classifier is CirProvided.Class) {
|
||||
return supertypes(type, classifier)
|
||||
}
|
||||
}
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
private fun supertypes(type: CirClassType, classifier: CirClass): Set<CirClassType> {
|
||||
return classifier.supertypes.filterIsInstance<CirClassType>()
|
||||
.mapNotNull { superType -> createSupertype(type, superType) }
|
||||
.toSet()
|
||||
}
|
||||
|
||||
private fun supertypes(type: CirClassType, classifier: CirProvided.Class): Set<CirClassType> {
|
||||
return classifier.supertypes.filterIsInstance<CirProvided.ClassType>()
|
||||
.mapNotNull { superType -> superType.toCirClassTypeOrNull() }
|
||||
.mapNotNull { superType -> createSupertype(type, superType) }
|
||||
.toSet()
|
||||
}
|
||||
|
||||
private fun createSupertype(type: CirClassType, supertype: CirClassType): CirClassType? {
|
||||
if (type.arguments.isEmpty() && supertype.arguments.isEmpty()) {
|
||||
return supertype
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun CirProvided.ClassType.toCirClassTypeOrNull(): CirClassType? {
|
||||
return CirClassType.createInterned(
|
||||
classId = this.classId,
|
||||
outerType = this.outerType?.let { it.toCirClassTypeOrNull() ?: return null },
|
||||
isMarkedNullable = this.isMarkedNullable,
|
||||
arguments = this.arguments.map { it.toCirTypeProjection() ?: return null },
|
||||
visibility = Visibilities.Public,
|
||||
)
|
||||
}
|
||||
|
||||
private fun CirProvided.TypeProjection.toCirTypeProjection(): CirTypeProjection? {
|
||||
return when (this) {
|
||||
is CirProvided.StarTypeProjection -> CirStarTypeProjection
|
||||
is CirProvided.RegularTypeProjection -> CirRegularTypeProjection(
|
||||
projectionKind = variance,
|
||||
type = (type as? CirProvided.ClassType)?.toCirClassTypeOrNull() ?: return null
|
||||
)
|
||||
}
|
||||
}
|
||||
+130
-12
@@ -5,27 +5,145 @@
|
||||
|
||||
package org.jetbrains.kotlin.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirClassOrTypeAliasType
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirClassType
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirType
|
||||
import org.jetbrains.kotlin.commonizer.cir.SimpleCirSupertypesResolver
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.findClass
|
||||
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
|
||||
class ClassSuperTypeCommonizer(
|
||||
typealias Supertypes = List<CirType>
|
||||
|
||||
internal class ClassSuperTypeCommonizer(
|
||||
private val classifiers: CirKnownClassifiers
|
||||
) : AssociativeCommonizer<List<CirType>> {
|
||||
) : SingleInvocationCommonizer<List<CirType>> {
|
||||
|
||||
private val typeCommonizer = TypeCommonizer(classifiers)
|
||||
|
||||
override fun commonize(first: List<CirType>, second: List<CirType>): List<CirType> {
|
||||
if (first.isEmpty() || second.isEmpty()) return emptyList()
|
||||
override fun invoke(values: List<Supertypes>): Supertypes {
|
||||
if (values.isEmpty()) return emptyList()
|
||||
if (values.all { it.isEmpty() }) return emptyList()
|
||||
|
||||
val firstGroup = first.filterIsInstance<CirClassOrTypeAliasType>().associateBy { it.classifierId }
|
||||
val secondGroup = second.filterIsInstance<CirClassOrTypeAliasType>().associateBy { it.classifierId }
|
||||
val supertypesTrees = resolveSupertypesTree(values)
|
||||
val supertypesGroups = buildSupertypesGroups(supertypesTrees)
|
||||
|
||||
val commonClassifiers = firstGroup.keys intersect secondGroup.keys
|
||||
|
||||
return commonClassifiers.mapNotNull { classifier ->
|
||||
typeCommonizer.commonize(firstGroup.getValue(classifier), secondGroup.getValue(classifier))
|
||||
return supertypesGroups.mapNotNull { supertypesGroup ->
|
||||
typeCommonizer.asCommonizer().commonize(supertypesGroup.types)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private fun resolveSupertypesTree(values: List<Supertypes>): List<SupertypesTree> {
|
||||
return values.mapIndexed { index: Int, supertypes: Supertypes ->
|
||||
val classifierIndex = classifiers.classifierIndices[index]
|
||||
val resolver = SimpleCirSupertypesResolver(classifiers.classifierIndices[index], classifiers.commonDependencies)
|
||||
val nodes = supertypes.filterIsInstance<CirClassType>().map { type -> createTypeNode(classifierIndex, resolver, type) }
|
||||
SupertypesTree(nodes)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildSupertypesGroups(trees: List<SupertypesTree>): List<SupertypesGroup> {
|
||||
val groups = mutableListOf<SupertypesGroup>()
|
||||
var allowClassTypes = true
|
||||
|
||||
trees.flatMap { tree -> tree.allNodes }.forEach { node ->
|
||||
if (node.assignedGroup != null) return@forEach
|
||||
val candidateGroup = buildTypeGroup(trees, node.type.classifierId) ?: return@forEach
|
||||
if (containsAnyClassKind(candidateGroup)) {
|
||||
if (!allowClassTypes) return@forEach
|
||||
allowClassTypes = false
|
||||
}
|
||||
assignGroupToNodes(candidateGroup)
|
||||
groups.add(candidateGroup)
|
||||
}
|
||||
|
||||
return groups
|
||||
}
|
||||
|
||||
private fun containsAnyClassKind(group: SupertypesGroup): Boolean {
|
||||
return group.nodes.any { node -> isClassKind(node) }
|
||||
}
|
||||
|
||||
private fun isClassKind(node: TypeNode): Boolean {
|
||||
if (node.index.findClass(node.type.classifierId)?.kind == ClassKind.CLASS) return true
|
||||
|
||||
/*
|
||||
Looking into provided dependencies.
|
||||
We do not know if ExportedForwardDeclarations are always Classes, but for sake of safety,
|
||||
we just assume all of those are classes.
|
||||
*/
|
||||
val providedClassifier = classifiers.commonDependencies.classifier(node.type.classifierId) ?: return false
|
||||
return providedClassifier is CirProvided.ExportedForwardDeclarationClass ||
|
||||
(providedClassifier is CirProvided.RegularClass && providedClassifier.kind == ClassKind.CLASS)
|
||||
}
|
||||
|
||||
private fun assignGroupToNodes(group: SupertypesGroup) {
|
||||
val classifiersIds = group.nodes.map { rootNode -> rootNode.allNodes.map { it.type.classifierId }.toSet() }
|
||||
val coveredClassifierIds = classifiersIds.reduce { acc, list -> acc intersect list }
|
||||
|
||||
group.nodes.forEach { rootNode ->
|
||||
rootNode.allNodes.forEach { visitingNode ->
|
||||
if (visitingNode.type.classifierId in coveredClassifierIds) {
|
||||
visitingNode.assignedGroup = group
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildTypeGroup(trees: List<SupertypesTree>, classifierId: CirEntityId): SupertypesGroup? {
|
||||
val nodes = trees.map { otherTree: SupertypesTree ->
|
||||
otherTree.allNodes.find { otherNode -> otherNode.type.classifierId == classifierId } ?: return null
|
||||
}
|
||||
return SupertypesGroup(classifierId, nodes)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTypeNode(index: CirClassifierIndex, resolver: SimpleCirSupertypesResolver, type: CirClassType): TypeNode {
|
||||
return TypeNode(
|
||||
index = index,
|
||||
type = type,
|
||||
supertypes = resolver.supertypes(type).map { supertype -> createTypeNode(index, resolver, supertype) }
|
||||
)
|
||||
}
|
||||
|
||||
private class SupertypesGroup(
|
||||
val classifierId: CirEntityId,
|
||||
val nodes: List<TypeNode>
|
||||
) {
|
||||
val types = nodes.map { it.type }
|
||||
|
||||
init {
|
||||
check(nodes.all { it.type.classifierId == classifierId })
|
||||
}
|
||||
}
|
||||
|
||||
private class SupertypesTree(
|
||||
val nodes: List<TypeNode>
|
||||
) {
|
||||
val allNodes: List<TypeNode> = run {
|
||||
val size = nodes.sumOf { it.allNodes.size }
|
||||
nodes.flatMapTo(ArrayList(size)) { it.allNodes }
|
||||
}
|
||||
}
|
||||
|
||||
private class TypeNode(
|
||||
val index: CirClassifierIndex,
|
||||
val type: CirClassType,
|
||||
val supertypes: List<TypeNode>,
|
||||
var assignedGroup: SupertypesGroup? = null
|
||||
) {
|
||||
val allNodes: List<TypeNode> by lazy {
|
||||
val allSupertypes = transitiveClosure(this, TypeNode::supertypes)
|
||||
ArrayList<TypeNode>(allSupertypes.size + 1).also { list ->
|
||||
list.add(this)
|
||||
list.addAll(allSupertypes)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "TypeNode(${type.classifierId})"
|
||||
}
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.commonizer.core
|
||||
|
||||
interface SingleInvocationCommonizer<T : Any> {
|
||||
operator fun invoke(values: List<T>): T
|
||||
}
|
||||
|
||||
fun <T : Any> SingleInvocationCommonizer<T>.asCommonizer(): Commonizer<T, T> = object : Commonizer<T, T> {
|
||||
private val collectedValues = mutableListOf<T>()
|
||||
|
||||
override val result: T
|
||||
get() = this@asCommonizer.invoke(collectedValues)
|
||||
|
||||
override fun commonizeWith(next: T): Boolean {
|
||||
collectedValues.add(next)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.commonizer
|
||||
import kotlinx.metadata.klib.ChunkedKlibModuleFragmentWriteStrategy
|
||||
import org.jetbrains.kotlin.commonizer.ResultsConsumer.Status
|
||||
import org.jetbrains.kotlin.commonizer.core.CommonizationVisitor
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirCommonizedClassifierNodes
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.indexOfCommon
|
||||
@@ -52,6 +53,7 @@ internal fun commonizeTarget(
|
||||
|
||||
parameters.logger.progress(output, "Commonized declarations from ${inputs.targets}") {
|
||||
val classifiers = CirKnownClassifiers(
|
||||
classifierIndices = availableTrees.toList().map(::CirClassifierIndex), // TODO NOW: Reuse for transformer!!
|
||||
commonizedNodes = CirCommonizedClassifierNodes.default(),
|
||||
commonDependencies = parameters.dependencyClassifiers(output)
|
||||
)
|
||||
|
||||
+33
-7
@@ -10,32 +10,55 @@
|
||||
|
||||
package org.jetbrains.kotlin.commonizer.mergedtree
|
||||
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirClass
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirClassifier
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirTypeAlias
|
||||
import org.jetbrains.kotlin.commonizer.tree.*
|
||||
import org.jetbrains.kotlin.commonizer.utils.compact
|
||||
import org.jetbrains.kotlin.commonizer.utils.compactMapValues
|
||||
|
||||
internal fun CirClassifierIndex(tree: CirTreeRoot): CirClassifierIndex {
|
||||
return CirUnderlyingTypeIndexBuilder().apply { invoke(tree) }.build()
|
||||
fun CirClassifierIndex(tree: CirTreeRoot): CirClassifierIndex {
|
||||
return CirClassifierIndexBuilder().apply { invoke(tree) }.build()
|
||||
}
|
||||
|
||||
internal interface CirClassifierIndex {
|
||||
interface CirClassifierIndex {
|
||||
val allClassifierIds: Set<CirEntityId>
|
||||
fun findClassifier(id: CirEntityId): CirClassifier?
|
||||
fun findTypeAliasesWithUnderlyingType(underlyingClassifier: CirEntityId): List<CirTreeTypeAlias>
|
||||
}
|
||||
|
||||
internal fun CirClassifierIndex.findClass(id: CirEntityId): CirClass? = findClassifier(id) as? CirClass
|
||||
|
||||
internal fun CirClassifierIndex.findTypeAlias(id: CirEntityId): CirTypeAlias? = findClassifier(id) as? CirTypeAlias
|
||||
|
||||
internal fun CirClassifierIndex.getClass(id: CirEntityId): CirClass =
|
||||
findClass(id) ?: throw NoSuchElementException("Missing class $id")
|
||||
|
||||
internal fun CirClassifierIndex.getTypeAlias(id: CirEntityId): CirTypeAlias =
|
||||
findTypeAlias(id) ?: throw NoSuchElementException("Missing type alias $id")
|
||||
|
||||
internal fun CirClassifierIndex.getClassifier(id: CirEntityId): CirClassifier =
|
||||
findClassifier(id) ?: throw NoSuchElementException("Missing classifier $id")
|
||||
|
||||
private class CirClassifierIndexImpl(
|
||||
override val allClassifierIds: Set<CirEntityId>,
|
||||
private val classifiersById: Map<CirEntityId, CirClassifier>,
|
||||
private val typeAliasesByUnderlyingType: Map<CirEntityId, List<CirTreeTypeAlias>>
|
||||
) : CirClassifierIndex {
|
||||
|
||||
override fun findClassifier(id: CirEntityId): CirClassifier? {
|
||||
return classifiersById[id]
|
||||
}
|
||||
|
||||
override fun findTypeAliasesWithUnderlyingType(underlyingClassifier: CirEntityId): List<CirTreeTypeAlias> {
|
||||
return typeAliasesByUnderlyingType[underlyingClassifier].orEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
private class CirUnderlyingTypeIndexBuilder {
|
||||
private val index = mutableMapOf<CirEntityId, MutableList<CirTreeTypeAlias>>()
|
||||
private class CirClassifierIndexBuilder {
|
||||
private val typeAliasesByUnderlyingType = mutableMapOf<CirEntityId, MutableList<CirTreeTypeAlias>>()
|
||||
private val classifiersById = mutableMapOf<CirEntityId, CirClassifier>()
|
||||
private val classifierIds = mutableSetOf<CirEntityId>()
|
||||
|
||||
operator fun invoke(tree: CirTreeRoot) {
|
||||
@@ -53,18 +76,21 @@ private class CirUnderlyingTypeIndexBuilder {
|
||||
|
||||
operator fun invoke(typeAlias: CirTreeTypeAlias) {
|
||||
classifierIds.add(typeAlias.id)
|
||||
index.getOrPut(typeAlias.typeAlias.underlyingType.classifierId) { mutableListOf() }.add(typeAlias)
|
||||
classifiersById[typeAlias.id] = typeAlias.typeAlias
|
||||
typeAliasesByUnderlyingType.getOrPut(typeAlias.typeAlias.underlyingType.classifierId) { mutableListOf() }.add(typeAlias)
|
||||
}
|
||||
|
||||
operator fun invoke(clazz: CirTreeClass) {
|
||||
classifierIds.add(clazz.id)
|
||||
classifiersById[clazz.id] = clazz.clazz
|
||||
clazz.classes.forEach { innerClazz -> this(innerClazz) }
|
||||
}
|
||||
|
||||
fun build(): CirClassifierIndex {
|
||||
return CirClassifierIndexImpl(
|
||||
allClassifierIds = classifierIds.toSet(),
|
||||
typeAliasesByUnderlyingType = index.compactMapValues { (_, list) -> list.compact() }
|
||||
classifiersById = classifiersById.compact(),
|
||||
typeAliasesByUnderlyingType = typeAliasesByUnderlyingType.compactMapValues { (_, list) -> list.compact() }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@ import gnu.trove.THashMap
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirPackageName
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
@@ -39,7 +40,7 @@ object CirFictitiousFunctionClassifiers : CirProvidedClassifiers {
|
||||
}
|
||||
|
||||
val classId = CirEntityId.create(PACKAGE_NAME, CirName.create("$prefix$arity"))
|
||||
val clazz = CirProvided.RegularClass(typeParameters, emptyList(), Visibilities.Public)
|
||||
val clazz = CirProvided.RegularClass(typeParameters, emptyList(), Visibilities.Public, ClassKind.INTERFACE)
|
||||
|
||||
consumer(classId, clazz)
|
||||
}
|
||||
|
||||
+1
@@ -9,6 +9,7 @@ import gnu.trove.THashMap
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
|
||||
|
||||
class CirKnownClassifiers(
|
||||
val classifierIndices: List<CirClassifierIndex>,
|
||||
val commonizedNodes: CirCommonizedClassifierNodes,
|
||||
val commonDependencies: CirProvidedClassifiers
|
||||
)
|
||||
|
||||
+3
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.commonizer.mergedtree
|
||||
import org.jetbrains.kotlin.commonizer.ModulesProvider
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -69,7 +70,8 @@ object CirProvided {
|
||||
data class RegularClass(
|
||||
override val typeParameters: List<TypeParameter>,
|
||||
override val supertypes: List<Type>,
|
||||
override val visibility: Visibility
|
||||
override val visibility: Visibility,
|
||||
val kind: ClassKind
|
||||
) : Class
|
||||
|
||||
data class ExportedForwardDeclarationClass(val syntheticClassId: CirEntityId) : Class {
|
||||
|
||||
+10
-8
@@ -12,10 +12,8 @@ import org.jetbrains.kotlin.commonizer.ModulesProvider.CInteropModuleAttributes
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirPackageName
|
||||
import org.jetbrains.kotlin.commonizer.utils.NON_EXISTING_CLASSIFIER_ID
|
||||
import org.jetbrains.kotlin.commonizer.utils.compactMap
|
||||
import org.jetbrains.kotlin.commonizer.utils.compactMapIndexed
|
||||
import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages
|
||||
import org.jetbrains.kotlin.commonizer.utils.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import org.jetbrains.kotlin.library.metadata.parsePackageFragment
|
||||
@@ -64,7 +62,8 @@ internal class CirProvidedClassifiersByModules private constructor(
|
||||
return CirProvidedClassifiersByModules(hasForwardDeclarations, classifiers)
|
||||
}
|
||||
|
||||
private val FALLBACK_FORWARD_DECLARATION_CLASS = CirProvided.RegularClass(emptyList(), emptyList(), Visibilities.Public)
|
||||
private val FALLBACK_FORWARD_DECLARATION_CLASS =
|
||||
CirProvided.RegularClass(emptyList(), emptyList(), Visibilities.Public, ClassKind.CLASS)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,11 +165,14 @@ private fun readClass(
|
||||
)
|
||||
val typeReadContext = TypeReadContext(classEntry.strings, TypeTable(classProto.typeTable), typeParameterNameToIndex)
|
||||
|
||||
val supertypes = classProto.supertypeList.map { readType(it, typeReadContext) } +
|
||||
classProto.supertypeIdList.map { readType(classProto.typeTable.getType(it), typeReadContext) }
|
||||
val supertypes = (classProto.supertypeList.map { readType(it, typeReadContext) } +
|
||||
classProto.supertypeIdList.map { readType(classProto.typeTable.getType(it), typeReadContext) })
|
||||
.filterNot { type -> type is CirProvided.ClassType && type.classId == ANY_CLASS_ID }
|
||||
|
||||
|
||||
val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(classProto.flags))
|
||||
val clazz = CirProvided.RegularClass(typeParameters, supertypes, visibility)
|
||||
val kind = ProtoEnumFlags.classKind(Flags.CLASS_KIND.get(classProto.flags))
|
||||
val clazz = CirProvided.RegularClass(typeParameters, supertypes, visibility, kind)
|
||||
|
||||
consumer(classId, clazz)
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ expect abstract class A2() : A1 {
|
||||
abstract fun function2(): Int
|
||||
}
|
||||
|
||||
expect class A3() : A2 {
|
||||
expect class A3() : A2, A1 {
|
||||
override val property1: Int
|
||||
override val property2: Int
|
||||
val property3: Int
|
||||
|
||||
@@ -25,6 +25,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
|
||||
fun initialize() {
|
||||
// reset cache
|
||||
classifiers = CirKnownClassifiers(
|
||||
classifierIndices = emptyList(), // TODO NOW
|
||||
commonizedNodes = CirCommonizedClassifierNodes.default(),
|
||||
commonDependencies = object : CirProvidedClassifiers {
|
||||
override fun hasClassifier(classifierId: CirEntityId) = classifierId.packageName.isUnderStandardKotlinPackages
|
||||
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.commonizer.hierarchical
|
||||
|
||||
import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest
|
||||
import org.jetbrains.kotlin.commonizer.assertCommonized
|
||||
import org.junit.Test
|
||||
|
||||
class ClassSuperTypeCommonizationTest : AbstractInlineSourcesCommonizationTest() {
|
||||
|
||||
@Test
|
||||
fun `test common supertype - from dependencies`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a, b)")
|
||||
registerDependency("a", "b", "(a, b)") {
|
||||
source(
|
||||
"""
|
||||
interface A
|
||||
interface B: A
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"a", """
|
||||
class X: A
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"b", """
|
||||
class X: B
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
result.assertCommonized(
|
||||
"(a, b)", """
|
||||
expect class X(): A
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test common supertype - from sources`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a, b)")
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"a", """
|
||||
interface A
|
||||
interface B: A
|
||||
class X: A
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"b", """
|
||||
interface A
|
||||
interface B: A
|
||||
class X: B
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
result.assertCommonized(
|
||||
"(a, b)", """
|
||||
expect interface A
|
||||
expect interface B: A
|
||||
expect class X(): A
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test common supertype - from sources - missing interface in one target`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a, b)")
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"a", """
|
||||
interface A
|
||||
class X: A
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"b", """
|
||||
interface A
|
||||
interface B: A
|
||||
class X: B
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
result.assertCommonized(
|
||||
"(a, b)", """
|
||||
expect interface A
|
||||
expect class X(): A
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test common supertypes - sample 0`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a, b)")
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"a", """
|
||||
interface C
|
||||
interface B
|
||||
interface A: B, C
|
||||
|
||||
class X: A
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"b", """
|
||||
interface C
|
||||
interface B: C
|
||||
interface A
|
||||
|
||||
class X: A, B
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
result.assertCommonized(
|
||||
"(a, b)", """
|
||||
expect interface C
|
||||
expect interface B
|
||||
expect interface A
|
||||
|
||||
expect class X(): A, B, C
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test common supertypes - sample 1`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a, b)")
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"a", """
|
||||
interface C
|
||||
open class B
|
||||
open class A: C, B()
|
||||
|
||||
class X: A()
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"b", """
|
||||
interface C
|
||||
interface B: C
|
||||
open class A
|
||||
|
||||
class X: A(), B
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
result.assertCommonized(
|
||||
"(a, b)", """
|
||||
expect interface C
|
||||
expect open class A()
|
||||
expect class X(): A, C
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test common supertypes - sample 2`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a, b, c)")
|
||||
simpleSingleSourceTarget(
|
||||
"a", """
|
||||
interface C
|
||||
interface B
|
||||
interface A: B, C
|
||||
|
||||
class X: A
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"b", """
|
||||
interface C
|
||||
interface B
|
||||
interface A: B
|
||||
|
||||
class X: A, C
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
simpleSingleSourceTarget(
|
||||
"c", """
|
||||
interface C
|
||||
interface B: C
|
||||
interface A
|
||||
|
||||
class X: A, B
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
result.assertCommonized(
|
||||
"(a, b, c)", """
|
||||
expect interface C
|
||||
expect interface B
|
||||
expect interface A
|
||||
|
||||
expect class X(): A, B, C
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
+1
@@ -15,6 +15,7 @@ class InlineTypeAliasCirNodeTransformerTest {
|
||||
private val storageManager = LockBasedStorageManager("test")
|
||||
|
||||
private val classifiers = CirKnownClassifiers(
|
||||
classifierIndices = emptyList(),
|
||||
commonizedNodes = CirCommonizedClassifierNodes.default(),
|
||||
commonDependencies = CirProvidedClassifiers.EMPTY
|
||||
)
|
||||
|
||||
+1
@@ -88,6 +88,7 @@ abstract class AbstractMergeCirTreeTest : KtInlineSourceCommonizerTestCase() {
|
||||
|
||||
private fun createDefaultKnownClassifiers(): CirKnownClassifiers {
|
||||
return CirKnownClassifiers(
|
||||
emptyList(), // TODO NOW
|
||||
CirCommonizedClassifierNodes.default(),
|
||||
CirProvidedClassifiers.of(
|
||||
CirFictitiousFunctionClassifiers,
|
||||
|
||||
@@ -52,6 +52,7 @@ private fun createValidClassifierId(classifierId: String): CirEntityId {
|
||||
}
|
||||
|
||||
internal val MOCK_CLASSIFIERS = CirKnownClassifiers(
|
||||
classifierIndices = emptyList(),
|
||||
commonizedNodes = object : CirCommonizedClassifierNodes {
|
||||
override fun classNode(classId: CirEntityId) = CirClassNode(
|
||||
classId,
|
||||
|
||||
Reference in New Issue
Block a user