[Commonizer] Respect artificial supertypes when loading dependencies

CirProvided.ExportedForwardDeclarationClass will now correctly
report artificial superclasses.

The InlineTypeAliasCirNodeTransformer does not need to know anything
about artificial supertypes anymore. When inlining any
type alias, it is enough to resolve the type-alias's expansions
supertypes.

^KT-47430
This commit is contained in:
sebastian.sellmair
2021-08-13 10:04:36 +02:00
committed by Space
parent 26ede5d885
commit f64a0efa8b
7 changed files with 249 additions and 158 deletions
@@ -82,6 +82,8 @@ internal fun <T> TargetDependent(keys: Iterable<CommonizerTarget>, factory: (tar
return FactoryBasedTargetDependent(keys.toList(), factory) return FactoryBasedTargetDependent(keys.toList(), factory)
} }
internal fun <T> TargetDependent(vararg pairs: Pair<CommonizerTarget, T>) = pairs.toMap().toTargetDependent()
internal fun <T> EagerTargetDependent(keys: Iterable<CommonizerTarget>, factory: (target: CommonizerTarget) -> T): TargetDependent<T> { internal fun <T> EagerTargetDependent(keys: Iterable<CommonizerTarget>, factory: (target: CommonizerTarget) -> T): TargetDependent<T> {
return keys.associateWith(factory).toTargetDependent() return keys.associateWith(factory).toTargetDependent()
} }
@@ -7,6 +7,10 @@ package org.jetbrains.kotlin.commonizer.mergedtree
import org.jetbrains.kotlin.commonizer.ModulesProvider import org.jetbrains.kotlin.commonizer.ModulesProvider
import org.jetbrains.kotlin.commonizer.cir.CirEntityId import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.mergedtree.ArtificialSupertypes.artificialSupertypes
import org.jetbrains.kotlin.commonizer.utils.CNAMES_STRUCTS_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.OBJCNAMES_CLASSES_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.OBJCNAMES_PROTOCOLS_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
@@ -88,8 +92,7 @@ object CirProvided {
override val typeParameters: List<TypeParameter> get() = emptyList() override val typeParameters: List<TypeParameter> get() = emptyList()
override val visibility: Visibility get() = Visibilities.Public override val visibility: Visibility get() = Visibilities.Public
override val supertypes: List<Type> override val supertypes: List<Type> = syntheticClassId.artificialSupertypes()
get() = emptyList() // TODO!!
} }
data class TypeAlias( data class TypeAlias(
@@ -129,3 +132,28 @@ object CirProvided {
data class RegularTypeProjection(val variance: Variance, val type: Type) : TypeProjection data class RegularTypeProjection(val variance: Variance, val type: Type) : TypeProjection
} }
/**
* Analog to "KlibResolvedModuleDescriptorsFactoryImpl.createForwardDeclarationsModule" which also
* automatically assumes relevant supertypes for forward declarations based upon the package they are in.
*/
private object ArtificialSupertypes {
private fun createType(classId: String): CirProvided.ClassType {
return CirProvided.ClassType(
classId = CirEntityId.create(classId),
outerType = null, arguments = emptyList(), isMarkedNullable = false
)
}
private val cOpaqueType = listOf(createType("kotlinx/cinterop/COpaque"))
private val objcObjectBase = listOf(createType("kotlinx/cinterop/ObjCObjectBase"))
private val objcCObject = listOf(createType("kotlinx/cinterop/ObjCObject"))
fun CirEntityId.artificialSupertypes(): List<CirProvided.Type> {
return when (packageName) {
CNAMES_STRUCTS_PACKAGE -> cOpaqueType
OBJCNAMES_CLASSES_PACKAGE -> objcObjectBase
OBJCNAMES_PROTOCOLS_PACKAGE -> objcCObject
else -> emptyList()
}
}
}
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.metadata.deserialization.*
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
internal class CirProvidedClassifiersByModules private constructor( internal class CirProvidedClassifiersByModules internal constructor(
private val hasForwardDeclarations: Boolean, private val hasForwardDeclarations: Boolean,
private val classifiers: Map<CirEntityId, CirProvided.Classifier>, private val classifiers: Map<CirEntityId, CirProvided.Classifier>,
) : CirProvidedClassifiers { ) : CirProvidedClassifiers {
@@ -33,11 +33,8 @@ internal class CirProvidedClassifiersByModules private constructor(
} }
override fun classifier(classifierId: CirEntityId) = override fun classifier(classifierId: CirEntityId) =
if (classifierId.packageName.isUnderKotlinNativeSyntheticPackages) { classifiers[classifierId] ?: if (hasForwardDeclarations && classifierId.packageName.isUnderKotlinNativeSyntheticPackages)
if (hasForwardDeclarations) FALLBACK_FORWARD_DECLARATION_CLASS else null FALLBACK_FORWARD_DECLARATION_CLASS else null
} else {
classifiers[classifierId]
}
companion object { companion object {
fun load(modulesProvider: ModulesProvider): CirProvidedClassifiers { fun load(modulesProvider: ModulesProvider): CirProvidedClassifiers {
@@ -10,18 +10,13 @@ import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.Composite.Companion.plus import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.Composite.Companion.plus
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.ParentNode import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.ParentNode
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.PreferredNode import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.PreferredNode
import org.jetbrains.kotlin.commonizer.transformer.ArtificialSupertypes.artificialSupertypes
import org.jetbrains.kotlin.commonizer.utils.CNAMES_STRUCTS_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.OBJCNAMES_CLASSES_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.OBJCNAMES_PROTOCOLS_PACKAGE
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
internal class InlineTypeAliasCirNodeTransformer( internal class InlineTypeAliasCirNodeTransformer(
private val storageManager: StorageManager, private val storageManager: StorageManager,
private val classifiers: CirKnownClassifiers private val classifiers: CirKnownClassifiers,
) : CirNodeTransformer { ) : CirNodeTransformer {
override fun invoke(root: CirRootNode) { override fun invoke(root: CirRootNode) {
root.modules.values.forEach(::invoke) root.modules.values.forEach(::invoke)
@@ -70,7 +65,7 @@ internal class InlineTypeAliasCirNodeTransformer(
val intoArtificialClass = ArtificialAliasedCirClass( val intoArtificialClass = ArtificialAliasedCirClass(
pointingTypeAlias = fromTypeAlias, pointingTypeAlias = fromTypeAlias,
pointedClass = fromAliasedClassNode?.targetDeclarations?.get(targetIndex) ?: fromTypeAlias.toArtificialCirClass() pointedClass = fromAliasedClassNode?.targetDeclarations?.get(targetIndex) ?: fromTypeAlias.toArtificialCirClass(targetIndex)
) )
intoClassNode.targetDeclarations[targetIndex] = intoArtificialClass intoClassNode.targetDeclarations[targetIndex] = intoArtificialClass
@@ -125,6 +120,23 @@ internal class InlineTypeAliasCirNodeTransformer(
this.classes[typeAliasNode.classifierName] = classNode this.classes[typeAliasNode.classifierName] = classNode
return classNode return classNode
} }
private fun CirTypeAlias.toArtificialCirClass(targetIndex: Int): CirClass = CirClass.create(
annotations = emptyList(), name = name, typeParameters = typeParameters, supertypes = resolveSupertypes(targetIndex),
visibility = this.visibility, modality = Modality.FINAL, kind = ClassKind.CLASS,
companion = null, isCompanion = false, isData = false, isValue = false, isInner = false, isExternal = false
)
private fun CirTypeAlias.resolveSupertypes(targetIndex: Int): List<CirType> {
if (expandedType.isMarkedNullable) return emptyList()
val resolver = SimpleCirSupertypesResolver(
classifiers = classifiers.classifierIndices[targetIndex],
dependencies = CirProvidedClassifiers.of(
classifiers.commonDependencies, classifiers.targetDependencies[targetIndex]
)
)
return resolver.supertypes(expandedType).toList()
}
} }
private typealias ClassNodeIndex = Map<CirEntityId, CirClassNode> private typealias ClassNodeIndex = Map<CirEntityId, CirClassNode>
@@ -143,38 +155,5 @@ private data class ArtificialAliasedCirClass(
set(_) = throw UnsupportedOperationException("Can't set companion on artificial class (pointed by $pointingTypeAlias)") set(_) = throw UnsupportedOperationException("Can't set companion on artificial class (pointed by $pointingTypeAlias)")
} }
private fun CirTypeAlias.toArtificialCirClass(): CirClass = CirClass.create(
annotations = emptyList(), name = name, typeParameters = typeParameters, supertypes = artificialSupertypes(),
visibility = this.visibility, modality = Modality.FINAL, kind = ClassKind.CLASS,
companion = null, isCompanion = false, isData = false, isValue = false, isInner = false, isExternal = false
)
/**
* Analog to "KlibResolvedModuleDescriptorsFactoryImpl.createForwardDeclarationsModule" which also
* automatically assumes relevant supertypes for forward declarations based upon the package they are in.
*/
private object ArtificialSupertypes {
private fun createType(classId: String): CirClassType {
return CirClassType.createInterned(
classId = CirEntityId.create(classId),
outerType = null, visibility = Visibilities.Public, arguments = emptyList(), isMarkedNullable = false
)
}
private val cOpaqueType = listOf(createType("kotlinx/cinterop/COpaque"))
private val objcObjectBase = listOf(createType("kotlinx/cinterop/ObjCObjectBase"))
private val objcCObject = listOf(createType("kotlinx/cinterop/ObjCObject"))
fun CirTypeAlias.artificialSupertypes(): List<CirType> {
/* Not supported (yet). No real life examples known (yet), that would benefit */
if (this.expandedType.isMarkedNullable) return emptyList()
return when (underlyingType.classifierId.packageName) {
CNAMES_STRUCTS_PACKAGE -> cOpaqueType
OBJCNAMES_CLASSES_PACKAGE -> objcObjectBase
OBJCNAMES_PROTOCOLS_PACKAGE -> objcCObject
else -> emptyList()
}
}
}
@@ -39,7 +39,7 @@ class HierarchicalClassAndTypeAliasCommonizationTest : AbstractInlineSourcesComm
simpleSingleSourceTarget("d", "typealias X = Short") simpleSingleSourceTarget("d", "typealias X = Short")
} }
result.assertCommonized("(a, b)", "expect class X") result.assertCommonized("(a, b)", "expect class X: Number")
result.assertCommonized("(c, d)", "expect class X") result.assertCommonized("(c, d)", "expect class X")
result.assertCommonized("((a, b), (c, d))", "expect class X") result.assertCommonized("((a, b), (c, d))", "expect class X")
} }
@@ -558,7 +558,7 @@ class HierarchicalClassAndTypeAliasCommonizationTest : AbstractInlineSourcesComm
result.assertCommonized( result.assertCommonized(
"(c, d)", """ "(c, d)", """
expect class Proxy expect class Proxy: Number
typealias X = Proxy typealias X = Proxy
expect val x: X expect val x: X
""".trimIndent() """.trimIndent()
@@ -566,7 +566,7 @@ class HierarchicalClassAndTypeAliasCommonizationTest : AbstractInlineSourcesComm
result.assertCommonized( result.assertCommonized(
"(a, b, c, d)", """ "(a, b, c, d)", """
expect class Proxy expect class Proxy: Number
typealias X = Proxy typealias X = Proxy
expect val x: X expect val x: X
""".trimIndent() """.trimIndent()
@@ -1,123 +1,202 @@
package org.jetbrains.kotlin.commonizer.transformer package org.jetbrains.kotlin.commonizer.transformer
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
import org.jetbrains.kotlin.commonizer.TargetDependent import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.cir.* import org.jetbrains.kotlin.commonizer.cir.CirClassType
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.mapValue
import org.jetbrains.kotlin.commonizer.mergedtree.* import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot
import org.jetbrains.kotlin.commonizer.tree.mergeCirTree
import org.jetbrains.kotlin.commonizer.utils.InlineSourceBuilder
import org.jetbrains.kotlin.commonizer.utils.KtInlineSourceCommonizerTestCase
import org.jetbrains.kotlin.commonizer.utils.createCirTree
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
class InlineTypeAliasCirNodeTransformerTest { class InlineTypeAliasCirNodeTransformerTest : KtInlineSourceCommonizerTestCase() {
private val storageManager = LockBasedStorageManager("test") fun `test inlining typealias to common dependencies`() {
private val classifiers = CirKnownClassifiers( fun InlineSourceBuilder.ModuleBuilder.withDependencies() = dependency {
classifierIndices = TargetDependent.empty(), source(
targetDependencies = TargetDependent.empty(), """
commonizedNodes = CirCommonizedClassifierNodes.default(), package dep
commonDependencies = CirProvidedClassifiers.EMPTY class ClassA
) class ClassB: ClassA()
""".trimIndent()
@Test )
fun `test artificial supertypes - regular package`() {
val root = setup(CirEntityId.create("regular/package/__X"))
InlineTypeAliasCirNodeTransformer(storageManager, classifiers).invoke(root)
val artificialXClass = root.assertInlinedXClass
assertEquals(
emptyList(), artificialXClass.supertypes,
"Expected no artificial supertype for artificial class X"
)
}
@Test
fun `test artificial supertypes - cnames structs`() {
val root = setup(CirEntityId.create("cnames/structs/__X"))
InlineTypeAliasCirNodeTransformer(storageManager, classifiers).invoke(root)
val artificialXClass = root.assertInlinedXClass
assertEquals(
setOf(CirEntityId.create("kotlinx/cinterop/COpaque")),
artificialXClass.supertypes.map { it as CirClassType }.map { it.classifierId }.toSet(),
"Expected 'COpaque' supertype being attached automatically"
)
}
@Test
fun `test artificial supertypes - objcnames classes`() {
val root = setup(CirEntityId.create("objcnames/classes/__X"))
InlineTypeAliasCirNodeTransformer(storageManager, classifiers).invoke(root)
val artificialXClass = root.assertInlinedXClass
assertEquals(
setOf(CirEntityId.create("kotlinx/cinterop/ObjCObjectBase")),
artificialXClass.supertypes.map { it as CirClassType }.map { it.classifierId }.toSet(),
"Expected 'ObjCObjectBase' supertype being attached automatically"
)
}
@Test
fun `test artificial supertypes - objcnames protocols`() {
val root = setup(CirEntityId.create("objcnames/protocols/__X"))
InlineTypeAliasCirNodeTransformer(storageManager, classifiers).invoke(root)
val artificialXClass = root.assertInlinedXClass
assertEquals(
setOf(CirEntityId.create("kotlinx/cinterop/ObjCObject")),
artificialXClass.supertypes.map { it as CirClassType }.map { it.classifierId }.toSet(),
"Expected 'ObjCObject' supertype being attached automatically"
)
}
private fun setup(typeAliasPointingTo: CirEntityId): CirRootNode {
val root = buildRootNode(storageManager, CirProvidedClassifiers.EMPTY, 1)
root.modules[CirName.create("test-module")] = buildModuleNode(storageManager, 1).apply {
packages[CirPackageName.create("under.test")] = buildPackageNode(storageManager, 2).apply {
typeAliases[CirName.create("X")] = buildTypeAliasNode(
storageManager, 2, classifiers, CirEntityId.create("under/test/X")
).apply {
val underlyingType = CirClassType.createInterned(
classId = typeAliasPointingTo,
outerType = null, visibility = Visibilities.Public,
arguments = emptyList(), isMarkedNullable = false
)
targetDeclarations[0] = CirTypeAlias.create(
annotations = emptyList(),
name = CirName.create("X"),
typeParameters = emptyList(),
visibility = Visibilities.Public,
underlyingType = underlyingType,
expandedType = underlyingType
)
}
classes[CirName.create("X")] = buildClassNode(
storageManager, 2, classifiers, null, CirEntityId.create("under/test/X")
).apply {
targetDeclarations[1] = CirClass.create(
name = CirName.create("X"), typeParameters = emptyList(),
supertypes = emptyList(), visibility = Visibilities.Public,
companion = null, isCompanion = false, isData = false, isExternal = false,
isInner = false, isValue = false, kind = ClassKind.CLASS,
modality = Modality.FINAL, annotations = emptyList(),
)
}
}
} }
return root val targetARoot = CirTreeRoot(
modules = listOf(
createCirTree {
withDependencies()
source(
"""
package pkg
import dep.*
class X : ClassA()
""".trimIndent()
)
}
)
)
val targetBRoot = CirTreeRoot(
modules = listOf(
createCirTree {
withDependencies()
source(
"""
package pkg
import dep.*
typealias X = ClassB
""".trimIndent()
)
}
)
)
val roots = TargetDependent(
LeafCommonizerTarget("a") to targetARoot,
LeafCommonizerTarget("b") to targetBRoot
)
val classifiers = CirKnownClassifiers(
classifierIndices = roots.mapValue(::CirClassifierIndex),
targetDependencies = roots.mapValue(CirTreeRoot::dependencies),
commonizedNodes = CirCommonizedClassifierNodes.default(),
commonDependencies = CirProvidedClassifiersByModules(
true, mapOf(
CirEntityId.create("dep/ClassA") to CirProvided.RegularClass(
typeParameters = emptyList(),
kind = ClassKind.CLASS,
visibility = Visibilities.Public,
supertypes = emptyList()
),
CirEntityId.create("dep/ClassB") to CirProvided.RegularClass(
typeParameters = emptyList(),
kind = ClassKind.CLASS,
visibility = Visibilities.Public,
supertypes = listOf(
CirProvided.ClassType(
classId = CirEntityId.create("dep/ClassA"),
outerType = null,
arguments = emptyList(),
isMarkedNullable = false
)
)
)
)
)
)
val mergedTree = mergeCirTree(LockBasedStorageManager.NO_LOCKS, classifiers, roots)
InlineTypeAliasCirNodeTransformer(LockBasedStorageManager.NO_LOCKS, classifiers).invoke(mergedTree)
val pkg = mergedTree.modules.values.single().packages.getValue(CirPackageName.create("pkg"))
val xClassNode = kotlin.test.assertNotNull(pkg.classes[CirName.create("X")])
val inlinedXClass = kotlin.test.assertNotNull(xClassNode.targetDeclarations[1])
kotlin.test.assertEquals(
setOf(CirEntityId.create("dep/ClassA")),
inlinedXClass.supertypes.map { (it as? CirClassType)?.classifierId }.toSet()
)
} }
private val CirRootNode.xClassNode: CirClassNode
get() = modules.getValue(CirName.create("test-module"))
.packages.getValue(CirPackageName.create("under.test"))
.classes.getValue(CirName.create("X"))
private val CirRootNode.assertInlinedXClass: CirClass fun `test inlining typealias to target dependencies`() {
get() = assertNotNull(xClassNode.targetDeclarations[0], "Missing inlined class 'X' at index 0")
fun InlineSourceBuilder.ModuleBuilder.withDependencies() = dependency {
source(
"""
package dep
class ClassA
class ClassB: ClassA()
""".trimIndent()
)
}
val targetARoot = CirTreeRoot(
modules = listOf(
createCirTree {
withDependencies()
source(
"""
package pkg
import dep.*
class X : ClassA()
""".trimIndent()
)
}
)
)
val targetBRoot = CirTreeRoot(
dependencies = CirProvidedClassifiersByModules(
true, mapOf(
CirEntityId.create("dep/ClassA") to CirProvided.RegularClass(
typeParameters = emptyList(),
kind = ClassKind.CLASS,
visibility = Visibilities.Public,
supertypes = emptyList()
),
CirEntityId.create("dep/ClassB") to CirProvided.RegularClass(
typeParameters = emptyList(),
kind = ClassKind.CLASS,
visibility = Visibilities.Public,
supertypes = listOf(
CirProvided.ClassType(
classId = CirEntityId.create("dep/ClassA"),
outerType = null,
arguments = emptyList(),
isMarkedNullable = false
)
)
)
)
),
modules = listOf(
createCirTree {
withDependencies()
source(
"""
package pkg
import dep.*
typealias X = ClassB
""".trimIndent()
)
}
)
)
val roots = TargetDependent(
LeafCommonizerTarget("a") to targetARoot,
LeafCommonizerTarget("b") to targetBRoot
)
val classifiers = CirKnownClassifiers(
classifierIndices = roots.mapValue(::CirClassifierIndex),
targetDependencies = roots.mapValue(CirTreeRoot::dependencies),
commonizedNodes = CirCommonizedClassifierNodes.default(),
commonDependencies = CirProvidedClassifiers.EMPTY
)
val mergedTree = mergeCirTree(LockBasedStorageManager.NO_LOCKS, classifiers, roots)
InlineTypeAliasCirNodeTransformer(LockBasedStorageManager.NO_LOCKS, classifiers).invoke(mergedTree)
val pkg = mergedTree.modules.values.single().packages.getValue(CirPackageName.create("pkg"))
val xClassNode = kotlin.test.assertNotNull(pkg.classes[CirName.create("X")])
val inlinedXClass = kotlin.test.assertNotNull(xClassNode.targetDeclarations[1])
kotlin.test.assertEquals(
setOf(CirEntityId.create("dep/ClassA")),
inlinedXClass.supertypes.map { (it as? CirClassType)?.classifierId }.toSet()
)
}
}
}
@@ -8,10 +8,16 @@ package org.jetbrains.kotlin.commonizer.utils
import kotlinx.metadata.klib.KlibModuleMetadata import kotlinx.metadata.klib.KlibModuleMetadata
import kotlinx.metadata.klib.annotations import kotlinx.metadata.klib.annotations
import org.jetbrains.kotlin.commonizer.CommonizerTarget import org.jetbrains.kotlin.commonizer.CommonizerTarget
import org.jetbrains.kotlin.commonizer.cir.CirFunction
import org.jetbrains.kotlin.commonizer.cir.CirProperty
import org.jetbrains.kotlin.commonizer.identityString import org.jetbrains.kotlin.commonizer.identityString
import org.jetbrains.kotlin.commonizer.metadata.utils.MetadataDeclarationsComparator import org.jetbrains.kotlin.commonizer.metadata.utils.MetadataDeclarationsComparator
import org.jetbrains.kotlin.commonizer.metadata.utils.MetadataDeclarationsComparator.* import org.jetbrains.kotlin.commonizer.metadata.utils.MetadataDeclarationsComparator.*
import org.jetbrains.kotlin.commonizer.metadata.utils.SerializedMetadataLibraryProvider import org.jetbrains.kotlin.commonizer.metadata.utils.SerializedMetadataLibraryProvider
import org.jetbrains.kotlin.commonizer.tree.CirTreeClass
import org.jetbrains.kotlin.commonizer.tree.CirTreeModule
import org.jetbrains.kotlin.commonizer.tree.CirTreePackage
import org.jetbrains.kotlin.commonizer.tree.CirTreeTypeAlias
import org.jetbrains.kotlin.library.SerializedMetadata import org.jetbrains.kotlin.library.SerializedMetadata
import java.io.File import java.io.File
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts