[Commonizer] Split CirTreeMerger into composable 'Mergers'
This commit is contained in:
committed by
Space
parent
2f49e8e0af
commit
096e715652
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.commonizer.ResultsConsumer.Status
|
|||||||
import org.jetbrains.kotlin.commonizer.core.CommonizationVisitor
|
import org.jetbrains.kotlin.commonizer.core.CommonizationVisitor
|
||||||
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
||||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.dimension
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.dimension
|
||||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirTreeMerger.CirTreeMergeResult
|
|
||||||
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer
|
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer
|
||||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
@@ -45,11 +44,10 @@ private fun mergeAndCommonize(storageManager: StorageManager, parameters: Common
|
|||||||
CirProvidedClassifiers.by(parameters.dependencyModulesProvider)
|
CirProvidedClassifiers.by(parameters.dependencyModulesProvider)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val mergeResult = CirTreeMerger(storageManager, classifiers, parameters).build()
|
val mergeResult = mergeCirTree(storageManager, classifiers, parameters)
|
||||||
|
|
||||||
// commonize:
|
// commonize:
|
||||||
val mergedTree = mergeResult.root
|
mergeResult.root.accept(CommonizationVisitor(classifiers, mergeResult.root), Unit)
|
||||||
mergedTree.accept(CommonizationVisitor(classifiers, mergedTree), Unit)
|
|
||||||
parameters.progressLogger?.invoke("Commonized declarations")
|
parameters.progressLogger?.invoke("Commonized declarations")
|
||||||
|
|
||||||
return mergeResult
|
return mergeResult
|
||||||
|
|||||||
+51
-347
@@ -5,22 +5,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.commonizer.mergedtree
|
package org.jetbrains.kotlin.commonizer.mergedtree
|
||||||
|
|
||||||
import com.intellij.util.containers.FactoryMap
|
import kotlinx.metadata.KmTypeParameter
|
||||||
import kotlinx.metadata.*
|
|
||||||
import kotlinx.metadata.klib.KlibModuleMetadata
|
|
||||||
import kotlinx.metadata.klib.fqName
|
|
||||||
import kotlinx.metadata.klib.klibEnumEntries
|
|
||||||
import org.jetbrains.kotlin.commonizer.CommonizerParameters
|
import org.jetbrains.kotlin.commonizer.CommonizerParameters
|
||||||
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
|
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
|
||||||
import org.jetbrains.kotlin.commonizer.ModulesProvider.ModuleInfo
|
import org.jetbrains.kotlin.commonizer.ModulesProvider.ModuleInfo
|
||||||
import org.jetbrains.kotlin.commonizer.TargetProvider
|
import org.jetbrains.kotlin.commonizer.mergedtree.mergers.*
|
||||||
import org.jetbrains.kotlin.commonizer.cir.*
|
import org.jetbrains.kotlin.commonizer.mergedtree.mergers.ClassesToProcess
|
||||||
import org.jetbrains.kotlin.commonizer.mergedtree.ClassesToProcess.ClassEntry
|
import org.jetbrains.kotlin.commonizer.mergedtree.mergers.ModuleMerger
|
||||||
import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers
|
import org.jetbrains.kotlin.commonizer.mergedtree.mergers.PropertyMerger
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.mergers.RootMerger
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.mergers.TargetMerger
|
||||||
import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver
|
import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver
|
||||||
import org.jetbrains.kotlin.commonizer.metadata.utils.SerializedMetadataLibraryProvider
|
|
||||||
import org.jetbrains.kotlin.commonizer.prettyName
|
|
||||||
import org.jetbrains.kotlin.commonizer.utils.*
|
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,347 +43,56 @@ import org.jetbrains.kotlin.storage.StorageManager
|
|||||||
* targets (which is not supported yet), or a Native library where one fragment is produced via C-interop tool and the other one
|
* targets (which is not supported yet), or a Native library where one fragment is produced via C-interop tool and the other one
|
||||||
* is compiled from Kotlin/Native source code (not sure this should be supported at all).
|
* is compiled from Kotlin/Native source code (not sure this should be supported at all).
|
||||||
*/
|
*/
|
||||||
class CirTreeMerger(
|
|
||||||
private val storageManager: StorageManager,
|
class CirTreeMergeResult(
|
||||||
private val classifiers: CirKnownClassifiers,
|
val root: CirRootNode,
|
||||||
private val parameters: CommonizerParameters
|
val missingModuleInfos: Map<LeafCommonizerTarget, Collection<ModuleInfo>>
|
||||||
|
)
|
||||||
|
|
||||||
|
internal class CirTargetMergingContext(
|
||||||
|
val storageManager: StorageManager,
|
||||||
|
val classifiers: CirKnownClassifiers,
|
||||||
|
val parameters: CommonizerParameters,
|
||||||
|
val targetIndex: Int,
|
||||||
|
val typeResolver: CirTypeResolver
|
||||||
) {
|
) {
|
||||||
class CirTreeMergeResult(
|
val targets = parameters.targetProviders.size
|
||||||
val root: CirRootNode,
|
}
|
||||||
val missingModuleInfos: Map<LeafCommonizerTarget, Collection<ModuleInfo>>
|
|
||||||
)
|
|
||||||
|
|
||||||
private class CirTreeMergingContext(
|
internal fun CirTargetMergingContext.create(classEntry: ClassesToProcess.ClassEntry): CirTargetMergingContext = when (classEntry) {
|
||||||
val targetIndex: Int,
|
is ClassesToProcess.ClassEntry.RegularClassEntry -> create(classEntry.clazz.typeParameters)
|
||||||
val typeResolver: CirTypeResolver
|
is ClassesToProcess.ClassEntry.EnumEntry -> this
|
||||||
) {
|
}
|
||||||
fun create(classEntry: ClassEntry): CirTreeMergingContext = when (classEntry) {
|
|
||||||
is ClassEntry.RegularClassEntry -> create(classEntry.clazz.typeParameters)
|
|
||||||
is ClassEntry.EnumEntry -> this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun create(typeParameters: List<KmTypeParameter>): CirTreeMergingContext {
|
internal fun CirTargetMergingContext.create(typeParameters: List<KmTypeParameter>): CirTargetMergingContext {
|
||||||
val newTypeResolver = typeResolver.create(typeParameters)
|
val newTypeResolver = typeResolver.create(typeParameters)
|
||||||
return if (newTypeResolver !== typeResolver)
|
return if (newTypeResolver !== typeResolver)
|
||||||
CirTreeMergingContext(targetIndex, newTypeResolver)
|
CirTargetMergingContext(storageManager, classifiers, parameters, targetIndex, newTypeResolver)
|
||||||
else
|
else
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private val leafTargetsSize = parameters.targetProviders.size
|
fun mergeCirTree(
|
||||||
|
storageManager: StorageManager,
|
||||||
fun build(): CirTreeMergeResult {
|
classifiers: CirKnownClassifiers,
|
||||||
val result = processRoot()
|
parameters: CommonizerParameters
|
||||||
System.gc()
|
): CirTreeMergeResult {
|
||||||
return result
|
val rootMerger = RootMerger(
|
||||||
}
|
targetMerger = TargetMerger(
|
||||||
|
moduleMerger = ModuleMerger(
|
||||||
private fun processRoot(): CirTreeMergeResult {
|
packageMerger = PackageMerger(
|
||||||
val rootNode: CirRootNode = buildRootNode(storageManager, leafTargetsSize)
|
propertyMerger = PropertyMerger,
|
||||||
|
functionMerger = FunctionMerger,
|
||||||
val commonModuleNames = parameters.getCommonModuleNames()
|
classMerger = ClassMerger(
|
||||||
val missingModuleInfosByTargets = mutableMapOf<LeafCommonizerTarget, Collection<ModuleInfo>>()
|
classConstructorMerger = ClassConstructorMerger,
|
||||||
|
propertyMerger = PropertyMerger,
|
||||||
parameters.targetProviders.forEachIndexed { targetIndex, targetProvider ->
|
functionMerger = FunctionMerger,
|
||||||
val allModuleInfos = targetProvider.modulesProvider.loadModuleInfos()
|
),
|
||||||
|
typeAliasMerger = TypeAliasMerger
|
||||||
val (commonModuleInfos, missingModuleInfos) = allModuleInfos.partition { it.name in commonModuleNames }
|
|
||||||
processTarget(targetIndex, rootNode, targetProvider, commonModuleInfos)
|
|
||||||
|
|
||||||
missingModuleInfosByTargets[targetProvider.target] = missingModuleInfos
|
|
||||||
|
|
||||||
parameters.progressLogger?.invoke("Loaded declarations for ${targetProvider.target.prettyName}")
|
|
||||||
System.gc()
|
|
||||||
}
|
|
||||||
|
|
||||||
return CirTreeMergeResult(
|
|
||||||
root = rootNode,
|
|
||||||
missingModuleInfos = missingModuleInfosByTargets
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processTarget(
|
|
||||||
targetIndex: Int,
|
|
||||||
rootNode: CirRootNode,
|
|
||||||
targetProvider: TargetProvider,
|
|
||||||
commonModuleInfos: Collection<ModuleInfo>
|
|
||||||
) {
|
|
||||||
rootNode.targetDeclarations[targetIndex] = CirRoot.create(targetProvider.target)
|
|
||||||
|
|
||||||
if (commonModuleInfos.isEmpty())
|
|
||||||
return
|
|
||||||
|
|
||||||
val context = CirTreeMergingContext(
|
|
||||||
targetIndex = targetIndex,
|
|
||||||
// all classifiers "visible" for the target:
|
|
||||||
typeResolver = CirTypeResolver.create(
|
|
||||||
providedClassifiers = CirProvidedClassifiers.of(
|
|
||||||
classifiers.commonDependencies,
|
|
||||||
CirProvidedClassifiers.by(targetProvider.dependencyModulesProvider),
|
|
||||||
CirProvidedClassifiers.by(targetProvider.modulesProvider)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
commonModuleInfos.forEach { moduleInfo ->
|
return rootMerger.processRoot(storageManager, classifiers, parameters)
|
||||||
val metadata = targetProvider.modulesProvider.loadModuleMetadata(moduleInfo.name)
|
|
||||||
val module = KlibModuleMetadata.read(SerializedMetadataLibraryProvider(metadata))
|
|
||||||
processModule(context, rootNode, module)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processModule(
|
|
||||||
context: CirTreeMergingContext,
|
|
||||||
rootNode: CirRootNode,
|
|
||||||
module: KlibModuleMetadata
|
|
||||||
) {
|
|
||||||
val moduleName: CirName = CirName.create(module.name)
|
|
||||||
val moduleNode: CirModuleNode = rootNode.modules.getOrPut(moduleName) {
|
|
||||||
buildModuleNode(storageManager, leafTargetsSize)
|
|
||||||
}
|
|
||||||
moduleNode.targetDeclarations[context.targetIndex] = CirModule.create(moduleName)
|
|
||||||
|
|
||||||
val groupedFragments: Map<CirPackageName, Collection<KmModuleFragment>> = module.fragments.foldToMap { fragment ->
|
|
||||||
fragment.fqName?.let(CirPackageName::create) ?: error("A fragment without FQ name in module $moduleName: $fragment")
|
|
||||||
}
|
|
||||||
|
|
||||||
groupedFragments.forEach { (packageName, fragments) ->
|
|
||||||
processFragments(context, moduleNode, fragments, packageName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processFragments(
|
|
||||||
context: CirTreeMergingContext,
|
|
||||||
moduleNode: CirModuleNode,
|
|
||||||
fragments: Collection<KmModuleFragment>,
|
|
||||||
packageName: CirPackageName
|
|
||||||
) {
|
|
||||||
val packageNode: CirPackageNode = moduleNode.packages.getOrPut(packageName) {
|
|
||||||
buildPackageNode(storageManager, leafTargetsSize)
|
|
||||||
}
|
|
||||||
packageNode.targetDeclarations[context.targetIndex] = CirPackage.create(packageName)
|
|
||||||
|
|
||||||
val classesToProcess = ClassesToProcess()
|
|
||||||
fragments.forEach { fragment ->
|
|
||||||
classesToProcess.addClassesFromFragment(fragment)
|
|
||||||
|
|
||||||
fragment.pkg?.let { pkg ->
|
|
||||||
pkg.properties.forEach { property ->
|
|
||||||
val propertyContext = context.create(property.typeParameters)
|
|
||||||
processProperty(propertyContext, packageNode, property)
|
|
||||||
}
|
|
||||||
pkg.functions.forEach { function ->
|
|
||||||
val functionContext = context.create(function.typeParameters)
|
|
||||||
processFunction(functionContext, packageNode, function)
|
|
||||||
}
|
|
||||||
pkg.typeAliases.forEach { typeAlias ->
|
|
||||||
val typeAliasContext = context.create(typeAlias.typeParameters)
|
|
||||||
processTypeAlias(typeAliasContext, packageNode, typeAlias)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
classesToProcess.forEachClassInScope(parentClassId = null) { classEntry ->
|
|
||||||
val classContext = context.create(classEntry)
|
|
||||||
processClass(classContext, packageNode, classEntry, classesToProcess)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processProperty(
|
|
||||||
context: CirTreeMergingContext,
|
|
||||||
ownerNode: CirNodeWithMembers<*, *>,
|
|
||||||
property: KmProperty
|
|
||||||
) {
|
|
||||||
if (property.isFakeOverride())
|
|
||||||
return
|
|
||||||
|
|
||||||
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
|
||||||
|
|
||||||
val approximationKey = PropertyApproximationKey(property, context.typeResolver)
|
|
||||||
val propertyNode: CirPropertyNode = ownerNode.properties.getOrPut(approximationKey) {
|
|
||||||
buildPropertyNode(storageManager, leafTargetsSize, classifiers, maybeClassOwnerNode?.commonDeclaration)
|
|
||||||
}
|
|
||||||
propertyNode.targetDeclarations[context.targetIndex] = CirDeserializers.property(
|
|
||||||
name = approximationKey.name,
|
|
||||||
source = property,
|
|
||||||
containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
|
|
||||||
typeResolver = context.typeResolver
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processFunction(
|
|
||||||
context: CirTreeMergingContext,
|
|
||||||
ownerNode: CirNodeWithMembers<*, *>,
|
|
||||||
function: KmFunction
|
|
||||||
) {
|
|
||||||
if (function.isFakeOverride()
|
|
||||||
|| function.isKniBridgeFunction()
|
|
||||||
|| function.isTopLevelDeprecatedFunction(isTopLevel = ownerNode !is CirClassNode)
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
|
||||||
|
|
||||||
val approximationKey = FunctionApproximationKey(function, context.typeResolver)
|
|
||||||
val functionNode: CirFunctionNode = ownerNode.functions.getOrPut(approximationKey) {
|
|
||||||
buildFunctionNode(storageManager, leafTargetsSize, classifiers, maybeClassOwnerNode?.commonDeclaration)
|
|
||||||
}
|
|
||||||
functionNode.targetDeclarations[context.targetIndex] = CirDeserializers.function(
|
|
||||||
name = approximationKey.name,
|
|
||||||
source = function,
|
|
||||||
containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
|
|
||||||
typeResolver = context.typeResolver
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processClass(
|
|
||||||
context: CirTreeMergingContext,
|
|
||||||
ownerNode: CirNodeWithMembers<*, *>,
|
|
||||||
classEntry: ClassEntry,
|
|
||||||
classesToProcess: ClassesToProcess
|
|
||||||
) {
|
|
||||||
val classId = classEntry.classId
|
|
||||||
val className = classId.relativeNameSegments.last()
|
|
||||||
|
|
||||||
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
|
||||||
val classNode: CirClassNode = ownerNode.classes.getOrPut(className) {
|
|
||||||
buildClassNode(storageManager, leafTargetsSize, classifiers, maybeClassOwnerNode?.commonDeclaration, classId)
|
|
||||||
}
|
|
||||||
|
|
||||||
val clazz: KmClass?
|
|
||||||
val isEnumEntry: Boolean
|
|
||||||
|
|
||||||
classNode.targetDeclarations[context.targetIndex] = when (classEntry) {
|
|
||||||
is ClassEntry.RegularClassEntry -> {
|
|
||||||
clazz = classEntry.clazz
|
|
||||||
isEnumEntry = Flag.Class.IS_ENUM_ENTRY(clazz.flags)
|
|
||||||
|
|
||||||
CirDeserializers.clazz(className, clazz, context.typeResolver)
|
|
||||||
}
|
|
||||||
is ClassEntry.EnumEntry -> {
|
|
||||||
clazz = null
|
|
||||||
isEnumEntry = true
|
|
||||||
|
|
||||||
CirDeserializers.defaultEnumEntry(
|
|
||||||
name = className,
|
|
||||||
annotations = classEntry.annotations,
|
|
||||||
enumClassId = classEntry.enumClassId,
|
|
||||||
enumClass = classEntry.enumClass,
|
|
||||||
typeResolver = context.typeResolver
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isEnumEntry) {
|
|
||||||
clazz?.constructors?.forEach { constructor ->
|
|
||||||
// TODO: nowhere to read constructor type parameters from
|
|
||||||
//val constructorContext = context.create(constructor.typeParameters)
|
|
||||||
|
|
||||||
processClassConstructor(context, classNode, constructor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clazz?.properties?.forEach { property ->
|
|
||||||
val propertyContext = context.create(property.typeParameters)
|
|
||||||
processProperty(propertyContext, classNode, property)
|
|
||||||
}
|
|
||||||
clazz?.functions?.forEach { function ->
|
|
||||||
val functionContext = context.create(function.typeParameters)
|
|
||||||
processFunction(functionContext, classNode, function)
|
|
||||||
}
|
|
||||||
|
|
||||||
classesToProcess.forEachClassInScope(parentClassId = classId) { nestedClassEntry ->
|
|
||||||
val nestedClassContext = context.create(nestedClassEntry)
|
|
||||||
processClass(nestedClassContext, classNode, nestedClassEntry, classesToProcess)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processClassConstructor(
|
|
||||||
context: CirTreeMergingContext,
|
|
||||||
classNode: CirClassNode,
|
|
||||||
constructor: KmConstructor
|
|
||||||
) {
|
|
||||||
val approximationKey = ConstructorApproximationKey(constructor, context.typeResolver)
|
|
||||||
val constructorNode: CirClassConstructorNode = classNode.constructors.getOrPut(approximationKey) {
|
|
||||||
buildClassConstructorNode(storageManager, leafTargetsSize, classifiers, classNode.commonDeclaration)
|
|
||||||
}
|
|
||||||
constructorNode.targetDeclarations[context.targetIndex] = CirDeserializers.constructor(
|
|
||||||
source = constructor,
|
|
||||||
containingClass = classNode.targetDeclarations[context.targetIndex]!!,
|
|
||||||
typeResolver = context.typeResolver
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processTypeAlias(
|
|
||||||
context: CirTreeMergingContext,
|
|
||||||
packageNode: CirPackageNode,
|
|
||||||
typeAlias: KmTypeAlias
|
|
||||||
) {
|
|
||||||
val typeAliasName = CirName.create(typeAlias.name)
|
|
||||||
val typeAliasId = CirEntityId.create(packageNode.packageName, typeAliasName)
|
|
||||||
|
|
||||||
val typeAliasNode: CirTypeAliasNode = packageNode.typeAliases.getOrPut(typeAliasName) {
|
|
||||||
buildTypeAliasNode(storageManager, leafTargetsSize, classifiers, typeAliasId)
|
|
||||||
}
|
|
||||||
typeAliasNode.targetDeclarations[context.targetIndex] = CirDeserializers.typeAlias(
|
|
||||||
name = typeAliasName,
|
|
||||||
source = typeAlias,
|
|
||||||
typeResolver = context.typeResolver
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ClassesToProcess {
|
|
||||||
sealed class ClassEntry {
|
|
||||||
abstract val classId: CirEntityId
|
|
||||||
|
|
||||||
data class RegularClassEntry(
|
|
||||||
override val classId: CirEntityId,
|
|
||||||
val clazz: KmClass
|
|
||||||
) : ClassEntry()
|
|
||||||
|
|
||||||
data class EnumEntry(
|
|
||||||
override val classId: CirEntityId,
|
|
||||||
val annotations: List<KmAnnotation>,
|
|
||||||
val enumClassId: CirEntityId,
|
|
||||||
val enumClass: KmClass
|
|
||||||
) : ClassEntry()
|
|
||||||
}
|
|
||||||
|
|
||||||
// key = parent class ID (or NON_EXISTING_CLASSIFIER_ID for top-level classes)
|
|
||||||
// value = classes under this parent class (MutableList to preserve order of classes)
|
|
||||||
private val groupedByParentClassId = FactoryMap.create<CirEntityId, MutableList<ClassEntry>> { ArrayList() }
|
|
||||||
|
|
||||||
fun addClassesFromFragment(fragment: KmModuleFragment) {
|
|
||||||
val klibEnumEntries = LinkedHashMap<CirEntityId, ClassEntry.EnumEntry>() // linked hash map to preserve order
|
|
||||||
val regularClassIds = HashSet<CirEntityId>()
|
|
||||||
|
|
||||||
fragment.classes.forEach { clazz ->
|
|
||||||
val classId: CirEntityId = CirEntityId.create(clazz.name)
|
|
||||||
val parentClassId: CirEntityId = classId.getParentEntityId() ?: NON_EXISTING_CLASSIFIER_ID
|
|
||||||
|
|
||||||
if (Flag.Class.IS_ENUM_CLASS(clazz.flags)) {
|
|
||||||
clazz.klibEnumEntries.forEach { entry ->
|
|
||||||
val enumEntryId = classId.createNestedEntityId(CirName.create(entry.name))
|
|
||||||
klibEnumEntries[enumEntryId] = ClassEntry.EnumEntry(enumEntryId, entry.annotations, classId, clazz)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
groupedByParentClassId.getValue(parentClassId) += ClassEntry.RegularClassEntry(classId, clazz)
|
|
||||||
regularClassIds += classId
|
|
||||||
}
|
|
||||||
|
|
||||||
// add enum entries that are not stored in module as KmClass records
|
|
||||||
klibEnumEntries.forEach { (enumEntryId, enumEntry) ->
|
|
||||||
if (enumEntryId !in regularClassIds) {
|
|
||||||
groupedByParentClassId.getValue(enumEntry.enumClassId) += enumEntry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun forEachClassInScope(parentClassId: CirEntityId?, block: (ClassEntry) -> Unit) {
|
|
||||||
groupedByParentClassId[parentClassId ?: NON_EXISTING_CLASSIFIER_ID]?.forEach { classEntry -> block(classEntry) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import kotlinx.metadata.KmConstructor
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirTargetMergingContext
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.buildClassConstructorNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers
|
||||||
|
|
||||||
|
internal object ClassConstructorMerger {
|
||||||
|
fun processClassConstructor(
|
||||||
|
context: CirTargetMergingContext,
|
||||||
|
classNode: CirClassNode,
|
||||||
|
constructor: KmConstructor
|
||||||
|
) = with(context) {
|
||||||
|
val approximationKey = ConstructorApproximationKey(constructor, context.typeResolver)
|
||||||
|
val constructorNode: CirClassConstructorNode = classNode.constructors.getOrPut(approximationKey) {
|
||||||
|
buildClassConstructorNode(storageManager, targets, classifiers, classNode.commonDeclaration)
|
||||||
|
}
|
||||||
|
constructorNode.targetDeclarations[context.targetIndex] = CirDeserializers.constructor(
|
||||||
|
source = constructor,
|
||||||
|
containingClass = classNode.targetDeclarations[context.targetIndex]!!,
|
||||||
|
typeResolver = context.typeResolver
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import kotlinx.metadata.Flag
|
||||||
|
import kotlinx.metadata.KmClass
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirTargetMergingContext
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.buildClassNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers
|
||||||
|
|
||||||
|
internal class ClassMerger(
|
||||||
|
private val classConstructorMerger: ClassConstructorMerger?,
|
||||||
|
private val propertyMerger: PropertyMerger?,
|
||||||
|
private val functionMerger: FunctionMerger?
|
||||||
|
) {
|
||||||
|
fun processClass(
|
||||||
|
context: CirTargetMergingContext,
|
||||||
|
ownerNode: CirNodeWithMembers<*, *>,
|
||||||
|
classEntry: ClassesToProcess.ClassEntry,
|
||||||
|
classesToProcess: ClassesToProcess
|
||||||
|
): Unit = with(context) {
|
||||||
|
val classId = classEntry.classId
|
||||||
|
val className = classId.relativeNameSegments.last()
|
||||||
|
|
||||||
|
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
||||||
|
val classNode: CirClassNode = ownerNode.classes.getOrPut(className) {
|
||||||
|
buildClassNode(storageManager, targets, classifiers, maybeClassOwnerNode?.commonDeclaration, classId)
|
||||||
|
}
|
||||||
|
|
||||||
|
val clazz: KmClass?
|
||||||
|
val isEnumEntry: Boolean
|
||||||
|
|
||||||
|
classNode.targetDeclarations[context.targetIndex] = when (classEntry) {
|
||||||
|
is ClassesToProcess.ClassEntry.RegularClassEntry -> {
|
||||||
|
clazz = classEntry.clazz
|
||||||
|
isEnumEntry = Flag.Class.IS_ENUM_ENTRY(clazz.flags)
|
||||||
|
|
||||||
|
CirDeserializers.clazz(className, clazz, context.typeResolver)
|
||||||
|
}
|
||||||
|
is ClassesToProcess.ClassEntry.EnumEntry -> {
|
||||||
|
clazz = null
|
||||||
|
isEnumEntry = true
|
||||||
|
|
||||||
|
CirDeserializers.defaultEnumEntry(
|
||||||
|
name = className,
|
||||||
|
annotations = classEntry.annotations,
|
||||||
|
enumClassId = classEntry.enumClassId,
|
||||||
|
enumClass = classEntry.enumClass,
|
||||||
|
typeResolver = context.typeResolver
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEnumEntry) {
|
||||||
|
clazz?.constructors?.forEach { constructor ->
|
||||||
|
// TODO: nowhere to read constructor type parameters from
|
||||||
|
//val constructorContext = context.create(constructor.typeParameters)
|
||||||
|
classConstructorMerger?.processClassConstructor(context, classNode, constructor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clazz?.properties?.forEach { property ->
|
||||||
|
val propertyContext = context.create(property.typeParameters)
|
||||||
|
propertyMerger?.processProperty(propertyContext, classNode, property)
|
||||||
|
}
|
||||||
|
clazz?.functions?.forEach { function ->
|
||||||
|
val functionContext = context.create(function.typeParameters)
|
||||||
|
functionMerger?.processFunction(functionContext, classNode, function)
|
||||||
|
}
|
||||||
|
|
||||||
|
classesToProcess.forEachClassInScope(parentClassId = classId) { nestedClassEntry ->
|
||||||
|
val nestedClassContext = context.create(nestedClassEntry)
|
||||||
|
processClass(nestedClassContext, classNode, nestedClassEntry, classesToProcess)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import com.intellij.util.containers.FactoryMap
|
||||||
|
import kotlinx.metadata.Flag
|
||||||
|
import kotlinx.metadata.KmAnnotation
|
||||||
|
import kotlinx.metadata.KmClass
|
||||||
|
import kotlinx.metadata.KmModuleFragment
|
||||||
|
import kotlinx.metadata.klib.klibEnumEntries
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirName
|
||||||
|
import org.jetbrains.kotlin.commonizer.utils.NON_EXISTING_CLASSIFIER_ID
|
||||||
|
|
||||||
|
internal class ClassesToProcess {
|
||||||
|
sealed class ClassEntry {
|
||||||
|
abstract val classId: CirEntityId
|
||||||
|
|
||||||
|
data class RegularClassEntry(
|
||||||
|
override val classId: CirEntityId,
|
||||||
|
val clazz: KmClass
|
||||||
|
) : ClassEntry()
|
||||||
|
|
||||||
|
data class EnumEntry(
|
||||||
|
override val classId: CirEntityId,
|
||||||
|
val annotations: List<KmAnnotation>,
|
||||||
|
val enumClassId: CirEntityId,
|
||||||
|
val enumClass: KmClass
|
||||||
|
) : ClassEntry()
|
||||||
|
}
|
||||||
|
|
||||||
|
// key = parent class ID (or NON_EXISTING_CLASSIFIER_ID for top-level classes)
|
||||||
|
// value = classes under this parent class (MutableList to preserve order of classes)
|
||||||
|
private val groupedByParentClassId = FactoryMap.create<CirEntityId, MutableList<ClassEntry>> { ArrayList() }
|
||||||
|
|
||||||
|
fun addClassesFromFragment(fragment: KmModuleFragment) {
|
||||||
|
val klibEnumEntries = LinkedHashMap<CirEntityId, ClassEntry.EnumEntry>() // linked hash map to preserve order
|
||||||
|
val regularClassIds = HashSet<CirEntityId>()
|
||||||
|
|
||||||
|
fragment.classes.forEach { clazz ->
|
||||||
|
val classId: CirEntityId = CirEntityId.create(clazz.name)
|
||||||
|
val parentClassId: CirEntityId = classId.getParentEntityId() ?: NON_EXISTING_CLASSIFIER_ID
|
||||||
|
|
||||||
|
if (Flag.Class.IS_ENUM_CLASS(clazz.flags)) {
|
||||||
|
clazz.klibEnumEntries.forEach { entry ->
|
||||||
|
val enumEntryId = classId.createNestedEntityId(CirName.create(entry.name))
|
||||||
|
klibEnumEntries[enumEntryId] = ClassEntry.EnumEntry(enumEntryId, entry.annotations, classId, clazz)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
groupedByParentClassId.getValue(parentClassId) += ClassEntry.RegularClassEntry(classId, clazz)
|
||||||
|
regularClassIds += classId
|
||||||
|
}
|
||||||
|
|
||||||
|
// add enum entries that are not stored in module as KmClass records
|
||||||
|
klibEnumEntries.forEach { (enumEntryId, enumEntry) ->
|
||||||
|
if (enumEntryId !in regularClassIds) {
|
||||||
|
groupedByParentClassId.getValue(enumEntry.enumClassId) += enumEntry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forEachClassInScope(parentClassId: CirEntityId?, block: (ClassEntry) -> Unit) {
|
||||||
|
groupedByParentClassId[parentClassId ?: NON_EXISTING_CLASSIFIER_ID]?.forEach { classEntry -> block(classEntry) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import kotlinx.metadata.KmFunction
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirTargetMergingContext
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.buildFunctionNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers
|
||||||
|
import org.jetbrains.kotlin.commonizer.utils.isFakeOverride
|
||||||
|
import org.jetbrains.kotlin.commonizer.utils.isKniBridgeFunction
|
||||||
|
import org.jetbrains.kotlin.commonizer.utils.isTopLevelDeprecatedFunction
|
||||||
|
|
||||||
|
internal object FunctionMerger {
|
||||||
|
fun processFunction(
|
||||||
|
context: CirTargetMergingContext,
|
||||||
|
ownerNode: CirNodeWithMembers<*, *>,
|
||||||
|
function: KmFunction
|
||||||
|
) = with(context) {
|
||||||
|
if (function.isFakeOverride()
|
||||||
|
|| function.isKniBridgeFunction()
|
||||||
|
|| function.isTopLevelDeprecatedFunction(isTopLevel = ownerNode !is CirClassNode)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
||||||
|
|
||||||
|
val approximationKey = FunctionApproximationKey(function, context.typeResolver)
|
||||||
|
val functionNode: CirFunctionNode = ownerNode.functions.getOrPut(approximationKey) {
|
||||||
|
buildFunctionNode(storageManager, targets, classifiers, maybeClassOwnerNode?.commonDeclaration)
|
||||||
|
}
|
||||||
|
functionNode.targetDeclarations[context.targetIndex] = CirDeserializers.function(
|
||||||
|
name = approximationKey.name,
|
||||||
|
source = function,
|
||||||
|
containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
|
||||||
|
typeResolver = context.typeResolver
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import kotlinx.metadata.KmModuleFragment
|
||||||
|
import kotlinx.metadata.klib.KlibModuleMetadata
|
||||||
|
import kotlinx.metadata.klib.fqName
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirModule
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirName
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirPackageName
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirModuleNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirTargetMergingContext
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.buildModuleNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.utils.foldToMap
|
||||||
|
|
||||||
|
internal class ModuleMerger(
|
||||||
|
private val packageMerger: PackageMerger
|
||||||
|
) {
|
||||||
|
fun processModule(
|
||||||
|
context: CirTargetMergingContext,
|
||||||
|
rootNode: CirRootNode,
|
||||||
|
module: KlibModuleMetadata
|
||||||
|
): Unit = with(context) {
|
||||||
|
val moduleName: CirName = CirName.create(module.name)
|
||||||
|
val moduleNode: CirModuleNode = rootNode.modules.getOrPut(moduleName) {
|
||||||
|
buildModuleNode(storageManager, targets)
|
||||||
|
}
|
||||||
|
moduleNode.targetDeclarations[context.targetIndex] = CirModule.create(moduleName)
|
||||||
|
|
||||||
|
val groupedFragments: Map<CirPackageName, Collection<KmModuleFragment>> = module.fragments.foldToMap { fragment ->
|
||||||
|
fragment.fqName?.let(CirPackageName.Companion::create) ?: error("A fragment without FQ name in module $moduleName: $fragment")
|
||||||
|
}
|
||||||
|
|
||||||
|
groupedFragments.forEach { (packageName, fragments) ->
|
||||||
|
packageMerger.processFragments(context, moduleNode, fragments, packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import kotlinx.metadata.KmModuleFragment
|
||||||
|
import kotlinx.metadata.KmTypeParameter
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirPackage
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirPackageName
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirTargetMergingContext
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.buildPackageNode
|
||||||
|
|
||||||
|
internal class PackageMerger(
|
||||||
|
private val propertyMerger: PropertyMerger?,
|
||||||
|
private val functionMerger: FunctionMerger?,
|
||||||
|
private val classMerger: ClassMerger?,
|
||||||
|
private val typeAliasMerger: TypeAliasMerger?
|
||||||
|
) {
|
||||||
|
fun processFragments(
|
||||||
|
context: CirTargetMergingContext,
|
||||||
|
moduleNode: CirModuleNode,
|
||||||
|
fragments: Collection<KmModuleFragment>,
|
||||||
|
packageName: CirPackageName
|
||||||
|
): Unit = with(context) {
|
||||||
|
val packageNode: CirPackageNode = moduleNode.packages.getOrPut(packageName) {
|
||||||
|
buildPackageNode(storageManager, targets)
|
||||||
|
}
|
||||||
|
packageNode.targetDeclarations[context.targetIndex] = CirPackage.create(packageName)
|
||||||
|
|
||||||
|
val classesToProcess = ClassesToProcess()
|
||||||
|
fragments.forEach { fragment ->
|
||||||
|
classesToProcess.addClassesFromFragment(fragment)
|
||||||
|
|
||||||
|
fragment.pkg?.let { pkg ->
|
||||||
|
pkg.properties.forEach { property ->
|
||||||
|
val propertyContext = context.create(property.typeParameters)
|
||||||
|
propertyMerger?.processProperty(propertyContext, packageNode, property)
|
||||||
|
}
|
||||||
|
pkg.functions.forEach { function ->
|
||||||
|
val functionContext = context.create(function.typeParameters)
|
||||||
|
functionMerger?.processFunction(functionContext, packageNode, function)
|
||||||
|
}
|
||||||
|
pkg.typeAliases.forEach { typeAlias ->
|
||||||
|
val typeAliasContext = context.create(typeAlias.typeParameters)
|
||||||
|
typeAliasMerger?.processTypeAlias(typeAliasContext, packageNode, typeAlias)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
classesToProcess.forEachClassInScope(parentClassId = null) { classEntry ->
|
||||||
|
val classContext = context.create(classEntry)
|
||||||
|
classMerger?.processClass(classContext, packageNode, classEntry, classesToProcess)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import kotlinx.metadata.KmProperty
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirTargetMergingContext
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.buildPropertyNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers
|
||||||
|
import org.jetbrains.kotlin.commonizer.utils.isFakeOverride
|
||||||
|
|
||||||
|
internal object PropertyMerger {
|
||||||
|
fun processProperty(
|
||||||
|
context: CirTargetMergingContext,
|
||||||
|
ownerNode: CirNodeWithMembers<*, *>,
|
||||||
|
property: KmProperty
|
||||||
|
) = with(context) {
|
||||||
|
if (property.isFakeOverride())
|
||||||
|
return
|
||||||
|
|
||||||
|
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
||||||
|
|
||||||
|
val approximationKey = PropertyApproximationKey(property, context.typeResolver)
|
||||||
|
val propertyNode: CirPropertyNode = ownerNode.properties.getOrPut(approximationKey) {
|
||||||
|
buildPropertyNode(storageManager, targets, classifiers, maybeClassOwnerNode?.commonDeclaration)
|
||||||
|
}
|
||||||
|
propertyNode.targetDeclarations[context.targetIndex] = CirDeserializers.property(
|
||||||
|
name = approximationKey.name,
|
||||||
|
source = property,
|
||||||
|
containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
|
||||||
|
typeResolver = context.typeResolver
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.commonizer.CommonizerParameters
|
||||||
|
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
|
||||||
|
import org.jetbrains.kotlin.commonizer.ModulesProvider
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.*
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.buildRootNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver
|
||||||
|
import org.jetbrains.kotlin.commonizer.prettyName
|
||||||
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
|
||||||
|
internal class RootMerger(
|
||||||
|
private val targetMerger: TargetMerger
|
||||||
|
) {
|
||||||
|
fun processRoot(
|
||||||
|
storageManager: StorageManager,
|
||||||
|
classifiers: CirKnownClassifiers,
|
||||||
|
parameters: CommonizerParameters
|
||||||
|
): CirTreeMergeResult {
|
||||||
|
val rootNode: CirRootNode = buildRootNode(storageManager, parameters.targetProviders.size)
|
||||||
|
|
||||||
|
val commonModuleNames = parameters.getCommonModuleNames()
|
||||||
|
val missingModuleInfosByTargets = mutableMapOf<LeafCommonizerTarget, Collection<ModulesProvider.ModuleInfo>>()
|
||||||
|
|
||||||
|
parameters.targetProviders.forEachIndexed { targetIndex, targetProvider ->
|
||||||
|
val allModuleInfos = targetProvider.modulesProvider.loadModuleInfos()
|
||||||
|
|
||||||
|
val (commonModuleInfos, missingModuleInfos) = allModuleInfos.partition { it.name in commonModuleNames }
|
||||||
|
val typeResolver = CirTypeResolver.create(
|
||||||
|
providedClassifiers = CirProvidedClassifiers.of(
|
||||||
|
classifiers.commonDependencies,
|
||||||
|
CirProvidedClassifiers.by(targetProvider.dependencyModulesProvider),
|
||||||
|
CirProvidedClassifiers.by(targetProvider.modulesProvider)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
targetMerger.processTarget(
|
||||||
|
CirTargetMergingContext(
|
||||||
|
storageManager, classifiers, parameters, targetIndex, typeResolver
|
||||||
|
), rootNode, targetProvider, commonModuleInfos
|
||||||
|
)
|
||||||
|
|
||||||
|
missingModuleInfosByTargets[targetProvider.target] = missingModuleInfos
|
||||||
|
|
||||||
|
parameters.progressLogger?.invoke("Loaded declarations for ${targetProvider.target.prettyName}")
|
||||||
|
System.gc()
|
||||||
|
}
|
||||||
|
|
||||||
|
return CirTreeMergeResult(
|
||||||
|
root = rootNode,
|
||||||
|
missingModuleInfos = missingModuleInfosByTargets
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import kotlinx.metadata.klib.KlibModuleMetadata
|
||||||
|
import org.jetbrains.kotlin.commonizer.ModulesProvider
|
||||||
|
import org.jetbrains.kotlin.commonizer.TargetProvider
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirRoot
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirTargetMergingContext
|
||||||
|
import org.jetbrains.kotlin.commonizer.metadata.utils.SerializedMetadataLibraryProvider
|
||||||
|
|
||||||
|
internal class TargetMerger(
|
||||||
|
private val moduleMerger: ModuleMerger
|
||||||
|
) {
|
||||||
|
fun processTarget(
|
||||||
|
context: CirTargetMergingContext,
|
||||||
|
rootNode: CirRootNode,
|
||||||
|
targetProvider: TargetProvider,
|
||||||
|
commonModuleInfos: Collection<ModulesProvider.ModuleInfo>
|
||||||
|
): Unit = with(context) {
|
||||||
|
rootNode.targetDeclarations[targetIndex] = CirRoot.create(targetProvider.target)
|
||||||
|
|
||||||
|
if (commonModuleInfos.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
commonModuleInfos.forEach { moduleInfo ->
|
||||||
|
val metadata = targetProvider.modulesProvider.loadModuleMetadata(moduleInfo.name)
|
||||||
|
val module = KlibModuleMetadata.read(SerializedMetadataLibraryProvider(metadata))
|
||||||
|
moduleMerger.processModule(context, rootNode, module)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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.mergedtree.mergers
|
||||||
|
|
||||||
|
import kotlinx.metadata.KmTypeAlias
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.CirName
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirPackageNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirTargetMergingContext
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirTypeAliasNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.buildTypeAliasNode
|
||||||
|
import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers
|
||||||
|
|
||||||
|
internal object TypeAliasMerger {
|
||||||
|
fun processTypeAlias(
|
||||||
|
context: CirTargetMergingContext,
|
||||||
|
packageNode: CirPackageNode,
|
||||||
|
typeAlias: KmTypeAlias
|
||||||
|
) = with(context) {
|
||||||
|
val typeAliasName = CirName.create(typeAlias.name)
|
||||||
|
val typeAliasId = CirEntityId.create(packageNode.packageName, typeAliasName)
|
||||||
|
|
||||||
|
val typeAliasNode: CirTypeAliasNode = packageNode.typeAliases.getOrPut(typeAliasName) {
|
||||||
|
buildTypeAliasNode(storageManager, targets, classifiers, typeAliasId)
|
||||||
|
}
|
||||||
|
typeAliasNode.targetDeclarations[context.targetIndex] = CirDeserializers.typeAlias(
|
||||||
|
name = typeAliasName,
|
||||||
|
source = typeAlias,
|
||||||
|
typeResolver = context.typeResolver
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user