From 108debdcc944257298b84adfd6acd43ec2272591 Mon Sep 17 00:00:00 2001 From: "sebastian.sellmair" Date: Thu, 25 Mar 2021 16:33:36 +0100 Subject: [PATCH] [Commonizer] Implement CirTree and CirTree deserializers and CirTree merging --- .../kotlin/commonizer/CommonizerParameters.kt | 10 +- .../kotlin/commonizer/TargetDependent.kt | 94 ++++++++++++++----- .../kotlin/commonizer/cir/CirProperty.kt | 1 + .../org/jetbrains/kotlin/commonizer/facade.kt | 30 +++--- .../commonizer/konan/LibraryCommonizer.kt | 3 +- .../mergedtree/mergers/ClassesToProcess.kt | 6 +- .../commonizer/metadata/CirTypeResolver.kt | 8 ++ .../kotlin/commonizer/tree/CirTree.kt | 58 ++++++++++++ .../deserializer/ClassCirTreeDeserializer.kt | 72 ++++++++++++++ .../ClassConstructorCirTreeDeserializer.kt | 28 ++++++ .../FunctionCirTreeDeserializer.kt | 40 ++++++++ .../deserializer/ModuleCirTreeDeserializer.kt | 40 ++++++++ .../PackageCirTreeDeserializer.kt | 55 +++++++++++ .../PropertyCirTreeDeserializer.kt | 31 ++++++ .../deserializer/RootCirTreeDeserializer.kt | 42 +++++++++ .../TypeAliasCirTreeDeserializer.kt | 31 ++++++ .../tree/deserializer/deserialize.kt | 30 ++++++ .../kotlin/commonizer/tree/merger/merge.kt | 90 ++++++++++++++++++ .../AbstractCommonizationFromSourcesTest.kt | 10 +- .../kotlin/commonizer/CommonizerFacadeTest.kt | 19 ++-- 20 files changed, 642 insertions(+), 56 deletions(-) create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/CirTree.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ClassCirTreeDeserializer.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ClassConstructorCirTreeDeserializer.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/FunctionCirTreeDeserializer.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ModuleCirTreeDeserializer.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/PackageCirTreeDeserializer.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/PropertyCirTreeDeserializer.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/RootCirTreeDeserializer.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/TypeAliasCirTreeDeserializer.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/deserialize.kt create mode 100644 native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/merger/merge.kt diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt index 853bff1e4ba..9acef6e56d0 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/CommonizerParameters.kt @@ -9,20 +9,20 @@ import org.jetbrains.kotlin.commonizer.konan.NativeManifestDataProvider import org.jetbrains.kotlin.commonizer.stats.StatsCollector class CommonizerParameters( - val targetProviders: List, + val targetProviders: TargetDependent, val resultsConsumer: ResultsConsumer, val commonManifestProvider: NativeManifestDataProvider, val commonDependencyModulesProvider: ModulesProvider? = null, val statsCollector: StatsCollector? = null, val progressLogger: ((String) -> Unit)? = null ) { - internal val commonTarget: SharedCommonizerTarget = SharedCommonizerTarget(targetProviders.map { it.target }.toSet()) + internal val commonTarget: SharedCommonizerTarget = SharedCommonizerTarget(targetProviders.targets.toSet()) internal val manifestDataProvider: TargetDependent - get() = TargetDependent { target -> + get() = TargetDependent(setOf(SharedCommonizerTarget(targetProviders.targets.toSet())) + targetProviders.targets) { target -> if (target == commonTarget) return@TargetDependent commonManifestProvider this.targetProviders.firstOrNull { it.target == target }?.manifestProvider?.let { return@TargetDependent it } - null + throw IllegalStateException("Illegal target $target") } } @@ -30,7 +30,7 @@ class CommonizerParameters( fun CommonizerParameters.getCommonModuleNames(): Set { if (targetProviders.size < 2) return emptySet() // too few targets - val allModuleNames: List> = targetProviders.map { targetProvider -> + val allModuleNames: List> = targetProviders.toList().map { targetProvider -> targetProvider.modulesProvider.loadModuleInfos().mapTo(HashSet()) { it.name } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt index b75e538c485..3f50ae397e1 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/TargetDependent.kt @@ -7,43 +7,95 @@ package org.jetbrains.kotlin.commonizer -sealed interface TargetDependent { - fun getOrNull(target: CommonizerTarget): T? - operator fun get(target: CommonizerTarget): T { - return getOrNull(target) ?: throw NoSuchElementException("Missing element for target ${target.prettyName}") +sealed interface TargetDependent : Iterable { + val size: Int get() = targets.size + val targets: List + fun indexOf(target: CommonizerTarget): Int = targets.indexOf(target) + + fun map(mapper: (target: CommonizerTarget, T) -> R): TargetDependent { + return TargetDependent(targets) { target -> + mapper(target, get(target)) + } + } + + override fun iterator(): Iterator { + return iterator { for (key in targets) yield(this@TargetDependent[key]) } + } + + operator fun get(target: CommonizerTarget): T + + fun getOrNull(target: CommonizerTarget): T? { + return if (target in targets) get(target) else null } } -internal fun Map.toTargetDependent(): TargetDependent { +internal fun TargetDependent.filterNonNull(): TargetDependent { + val nonNullTargets = targets.filter { this[it] != null } + return TargetDependent(nonNullTargets) { target -> this@filterNonNull[target] ?: throw NullPointerException() } +} + +internal fun TargetDependent.toMap(): Map { + return mutableMapOf().apply { + for (key in keys) { + put(key, this@toMap[key]) + } + } +} + +internal fun Map.toTargetDependent(): TargetDependent { return TargetDependent(toMap()) } -internal fun Map.asTargetDependent(): TargetDependent { - return TargetDependent(this) +internal fun TargetDependent.mapValue(mapper: (T) -> R): TargetDependent { + return TargetDependent(targets) { target -> this@mapValue.get(target).let(mapper) } } -internal fun TargetDependent.map(mapper: (T) -> R): TargetDependent { - return TargetDependent { target -> this@map.getOrNull(target)?.let(mapper) } +internal fun TargetDependent.mapTargets(mapper: (CommonizerTarget) -> R): TargetDependent { + return TargetDependent(targets) { target -> mapper(target) } } -internal fun TargetDependent(map: Map): TargetDependent { + +internal fun TargetDependent(map: Map): TargetDependent { return MapBasedTargetDependent(map) } -internal fun TargetDependent(factory: (target: CommonizerTarget) -> T?): TargetDependent { - return FactoryBasedTargetDependent(factory) +internal fun TargetDependent(keys: Iterable, factory: (target: CommonizerTarget) -> T): TargetDependent { + return FactoryBasedTargetDependent(keys.toList(), factory) } -private class MapBasedTargetDependent(private val map: Map) : TargetDependent { - override fun getOrNull(target: CommonizerTarget): T? = map[target] +private class MapBasedTargetDependent(private val map: Map) : TargetDependent { + override val targets: List = map.keys.toList() + override fun get(target: CommonizerTarget): T = map.getValue(target) } -private class FactoryBasedTargetDependent(private val factory: (target: CommonizerTarget) -> T?) : TargetDependent { - private val values = mutableMapOf() - override fun getOrNull(target: CommonizerTarget): T? { - @Suppress("unchecked_cast") - return values.getOrPut(target) { factory(target) ?: Null }.takeIf { it != Null }?.run { this as T } +/** + * Not thread safe! + */ +private class FactoryBasedTargetDependent( + override val targets: List, + private var factory: ((target: CommonizerTarget) -> T)? +) : TargetDependent { + + private object Uninitialized + + private val values: Array = Array(targets.size) { Uninitialized } + + @Suppress("UNCHECKED_CAST") + override fun get(target: CommonizerTarget): T { + val indexOfTarget = indexOf(target) + if (indexOfTarget < 0) throw NoSuchElementException("Missing target $target") + val storedValue = values[indexOfTarget] + if (storedValue == Uninitialized) { + val producedValue = factory?.invoke(target) + values[indexOfTarget] = producedValue + + /* All values initialized. Factory can be released */ + if (values.none { it === Uninitialized }) { + factory = null + } + return producedValue as T + } + + return storedValue as T } - - private object Null } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/cir/CirProperty.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/cir/CirProperty.kt index 01a82097f21..97772577e96 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/cir/CirProperty.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/cir/CirProperty.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.commonizer.cir +import org.jetbrains.kotlin.commonizer.mergedtree.PropertyApproximationKey import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibility diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt index c6d311455ae..2de63c0acfd 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/facade.kt @@ -12,6 +12,8 @@ import org.jetbrains.kotlin.commonizer.core.CommonizationVisitor import org.jetbrains.kotlin.commonizer.mergedtree.* import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.dimension import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer +import org.jetbrains.kotlin.commonizer.tree.deserializer.deserialize +import org.jetbrains.kotlin.commonizer.tree.merger.mergeCirTree import org.jetbrains.kotlin.library.SerializedMetadata import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.StorageManager @@ -24,18 +26,17 @@ fun runCommonization(parameters: CommonizerParameters) { val storageManager = LockBasedStorageManager("Declarations commonization") - val mergeResult = mergeAndCommonize(storageManager, parameters) - val mergedTree = mergeResult.root + val mergedTree = mergeAndCommonize(storageManager, parameters) // build resulting declarations: for (targetIndex in 0 until mergedTree.dimension) { - serializeTarget(mergeResult, targetIndex, parameters) + serializeTarget(mergedTree, targetIndex, parameters) } parameters.resultsConsumer.allConsumed(Status.DONE) } -private fun mergeAndCommonize(storageManager: StorageManager, parameters: CommonizerParameters): CirTreeMergeResult { +private fun mergeAndCommonize(storageManager: StorageManager, parameters: CommonizerParameters): CirRootNode { // build merged tree: val classifiers = CirKnownClassifiers( commonizedNodes = CirCommonizedClassifierNodes.default(), @@ -44,17 +45,18 @@ private fun mergeAndCommonize(storageManager: StorageManager, parameters: Common CirProvidedClassifiers.by(parameters.commonDependencyModulesProvider) ) ) - val mergeResult = mergeCirTree(storageManager, classifiers, parameters) - // commonize: - mergeResult.root.accept(CommonizationVisitor(classifiers, mergeResult.root), Unit) + val targetTrees = parameters.targetProviders.mapValue { target -> deserialize(parameters, target) } + parameters.progressLogger?.invoke("Deserialized targets") + + val mergedTree = mergeCirTree(storageManager, classifiers, targetTrees) + mergedTree.accept(CommonizationVisitor(classifiers, mergedTree), Unit) parameters.progressLogger?.invoke("Commonized declarations") - return mergeResult + return mergedTree } -private fun serializeTarget(mergeResult: CirTreeMergeResult, targetIndex: Int, parameters: CommonizerParameters) { - val mergedTree = mergeResult.root +private fun serializeTarget(mergedTree: CirRootNode, targetIndex: Int, parameters: CommonizerParameters) { val target = mergedTree.getTarget(targetIndex) CirTreeSerializer.serializeSingleTarget(mergedTree, targetIndex, parameters.statsCollector) { metadataModule -> @@ -66,10 +68,10 @@ private fun serializeTarget(mergeResult: CirTreeMergeResult, targetIndex: Int, p parameters.resultsConsumer.consume(target, ModuleResult.Commonized(libraryName, serializedMetadata, manifestData)) } - if (target is LeafCommonizerTarget) { - mergeResult.missingModuleInfos.getValue(target).forEach { - parameters.resultsConsumer.consume(target, ModuleResult.Missing(it.originalLocation)) - } + if (target in parameters.targetProviders.targets) { + parameters.targetProviders[target].modulesProvider.loadModuleInfos() + .filter { it.name !in parameters.getCommonModuleNames() } + .forEach { missingModule -> parameters.resultsConsumer.consume(target, ModuleResult.Missing(missingModule.originalLocation)) } } parameters.resultsConsumer.targetConsumed(target) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/LibraryCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/LibraryCommonizer.kt index fd3d781bcea..f6e06498092 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/LibraryCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/konan/LibraryCommonizer.kt @@ -42,7 +42,8 @@ internal class LibraryCommonizer internal constructor( private fun commonizeAndSaveResults(allLibraries: TargetDependent) { val parameters = CommonizerParameters( - targetProviders = commonTarget.targets.mapNotNull { target -> createTargetProvider(target, allLibraries[target]) }, + targetProviders = TargetDependent(commonTarget.targets) { target -> createTargetProvider(target, allLibraries[target]) } + .filterNonNull(), resultsConsumer = resultsConsumer, commonManifestProvider = CommonNativeManifestDataProvider(commonTarget.targets.map { allLibraries[it] }), commonDependencyModulesProvider = DefaultModulesProvider.create(dependencies.getLibraries(commonTarget)), diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/mergers/ClassesToProcess.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/mergers/ClassesToProcess.kt index 891e8a4411e..86b0b544d14 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/mergers/ClassesToProcess.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/mergers/ClassesToProcess.kt @@ -63,7 +63,11 @@ internal class ClassesToProcess { } } + fun classesInScope(parentClassId: CirEntityId?): List { + return groupedByParentClassId[parentClassId ?: NON_EXISTING_CLASSIFIER_ID].orEmpty() + } + fun forEachClassInScope(parentClassId: CirEntityId?, block: (ClassEntry) -> Unit) { - groupedByParentClassId[parentClassId ?: NON_EXISTING_CLASSIFIER_ID]?.forEach { classEntry -> block(classEntry) } + classesInScope(parentClassId).forEach { classEntry -> block(classEntry) } } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirTypeResolver.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirTypeResolver.kt index f63bbfeecfe..591fc0133e1 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirTypeResolver.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirTypeResolver.kt @@ -10,6 +10,7 @@ import kotlinx.metadata.KmTypeParameter import org.jetbrains.kotlin.commonizer.cir.CirEntityId import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers +import org.jetbrains.kotlin.commonizer.mergedtree.mergers.ClassesToProcess typealias TypeParameterId = Int typealias TypeParameterIndex = Int @@ -71,6 +72,13 @@ abstract class CirTypeResolver : CirTypeParameterResolver { Nested(this, mapping) } + internal fun create(classEntry: ClassesToProcess.ClassEntry): CirTypeResolver { + return when (classEntry) { + is ClassesToProcess.ClassEntry.RegularClassEntry -> create(classEntry.clazz.typeParameters) + is ClassesToProcess.ClassEntry.EnumEntry -> this + } + } + companion object { fun create(providedClassifiers: CirProvidedClassifiers): CirTypeResolver = TopLevel(providedClassifiers) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/CirTree.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/CirTree.kt new file mode 100644 index 00000000000..de25f157b77 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/CirTree.kt @@ -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.tree + +import org.jetbrains.kotlin.commonizer.cir.* +import org.jetbrains.kotlin.commonizer.mergedtree.ConstructorApproximationKey +import org.jetbrains.kotlin.commonizer.mergedtree.FunctionApproximationKey +import org.jetbrains.kotlin.commonizer.mergedtree.PropertyApproximationKey + +data class CirTreeRoot( + val modules: List +) + +data class CirTreeModule( + val module: CirModule, + val packages: List +) + +data class CirTreePackage( + val pkg: CirPackage, + val properties: List, + val functions: List, + val classes: List, + val typeAliases: List +) + +data class CirTreeProperty( + val approximationKey: PropertyApproximationKey, + val property: CirProperty +) + +data class CirTreeFunction( + val approximationKey: FunctionApproximationKey, + val function: CirFunction +) + +data class CirTreeTypeAlias( + val id: CirEntityId, + val typeAlias: CirTypeAlias +) + +data class CirTreeClass( + val id: CirEntityId, + val clazz: CirClass, + val properties: List, + val functions: List, + val constructors: List, + val classes: List, +) + +class CirTreeClassConstructor( + val approximationKey: ConstructorApproximationKey, + val constructor: CirClassConstructor +) + diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ClassCirTreeDeserializer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ClassCirTreeDeserializer.kt new file mode 100644 index 00000000000..668e9701141 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ClassCirTreeDeserializer.kt @@ -0,0 +1,72 @@ +/* + * 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.tree.deserializer + +import kotlinx.metadata.Flag +import kotlinx.metadata.KmClass +import org.jetbrains.kotlin.commonizer.mergedtree.mergers.ClassesToProcess +import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers +import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver +import org.jetbrains.kotlin.commonizer.tree.CirTreeClass + +internal class ClassCirTreeDeserializer( + private val propertyDeserializer: PropertyCirTreeDeserializer, + private val functionDeserializer: FunctionCirTreeDeserializer, + private val constructorDeserializer: ClassConstructorCirTreeDeserializer, +) { + operator fun invoke( + classEntry: ClassesToProcess.ClassEntry, classesToProcess: ClassesToProcess, typeResolver: CirTypeResolver + ): CirTreeClass { + val classTypeResolver = typeResolver.create(classEntry) + val classId = classEntry.classId + val className = classId.relativeNameSegments.last() + + val clazz: KmClass? + val isEnumEntry: Boolean + + val cirClass = when (classEntry) { + is ClassesToProcess.ClassEntry.RegularClassEntry -> { + clazz = classEntry.clazz + isEnumEntry = Flag.Class.IS_ENUM_ENTRY(clazz.flags) + CirDeserializers.clazz(className, clazz, classTypeResolver) + } + is ClassesToProcess.ClassEntry.EnumEntry -> { + clazz = null + isEnumEntry = true + + CirDeserializers.defaultEnumEntry( + name = className, + annotations = classEntry.annotations, + enumClassId = classEntry.enumClassId, + enumClass = classEntry.enumClass, + typeResolver = classTypeResolver + ) + } + } + + val constructors = clazz?.constructors + ?.takeIf { !isEnumEntry } + ?.map { constructor -> constructorDeserializer(constructor, cirClass, classTypeResolver) } + .orEmpty() + + val properties = clazz?.properties?.mapNotNull { property -> propertyDeserializer(property, cirClass, classTypeResolver) } + + val functions = clazz?.functions?.mapNotNull { function -> functionDeserializer(function, cirClass, classTypeResolver) } + + val classes = classesToProcess.classesInScope(classId).map { nestedClassEntry -> + this(nestedClassEntry, classesToProcess, classTypeResolver) + } + + return CirTreeClass( + id = classId, + clazz = cirClass, + properties = properties.orEmpty(), + functions = functions.orEmpty(), + constructors = constructors, + classes = classes + ) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ClassConstructorCirTreeDeserializer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ClassConstructorCirTreeDeserializer.kt new file mode 100644 index 00000000000..e060e750c3a --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ClassConstructorCirTreeDeserializer.kt @@ -0,0 +1,28 @@ +/* + * 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.tree.deserializer + +import kotlinx.metadata.KmConstructor +import org.jetbrains.kotlin.commonizer.cir.CirContainingClass +import org.jetbrains.kotlin.commonizer.mergedtree.ConstructorApproximationKey +import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers +import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver +import org.jetbrains.kotlin.commonizer.tree.CirTreeClassConstructor + +internal object ClassConstructorCirTreeDeserializer { + operator fun invoke( + constructor: KmConstructor, containingClass: CirContainingClass, typeResolver: CirTypeResolver + ): CirTreeClassConstructor { + return CirTreeClassConstructor( + approximationKey = ConstructorApproximationKey(constructor, typeResolver), + constructor = CirDeserializers.constructor( + source = constructor, + containingClass = containingClass, + typeResolver = typeResolver + ) + ) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/FunctionCirTreeDeserializer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/FunctionCirTreeDeserializer.kt new file mode 100644 index 00000000000..f78d47a1c07 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/FunctionCirTreeDeserializer.kt @@ -0,0 +1,40 @@ +/* + * 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.tree.deserializer + +import kotlinx.metadata.KmFunction +import org.jetbrains.kotlin.commonizer.cir.CirClass +import org.jetbrains.kotlin.commonizer.cir.CirContainingClass +import org.jetbrains.kotlin.commonizer.mergedtree.FunctionApproximationKey +import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers +import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver +import org.jetbrains.kotlin.commonizer.tree.CirTreeFunction +import org.jetbrains.kotlin.commonizer.utils.isFakeOverride +import org.jetbrains.kotlin.commonizer.utils.isKniBridgeFunction +import org.jetbrains.kotlin.commonizer.utils.isTopLevelDeprecatedFunction + +object FunctionCirTreeDeserializer { + operator fun invoke(function: KmFunction, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirTreeFunction? { + val functionTypeResolver = typeResolver.create(function.typeParameters) + if (function.isFakeOverride() + || function.isKniBridgeFunction() + || function.isTopLevelDeprecatedFunction(isTopLevel = containingClass !is CirClass) + ) { + return null + } + + val approximationKey = FunctionApproximationKey(function, functionTypeResolver) + return CirTreeFunction( + approximationKey = approximationKey, + function = CirDeserializers.function( + name = approximationKey.name, + source = function, + containingClass = containingClass, + typeResolver = functionTypeResolver + ) + ) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ModuleCirTreeDeserializer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ModuleCirTreeDeserializer.kt new file mode 100644 index 00000000000..947770a5119 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/ModuleCirTreeDeserializer.kt @@ -0,0 +1,40 @@ +/* + * 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.tree.deserializer + +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.metadata.CirTypeResolver +import org.jetbrains.kotlin.commonizer.metadata.utils.SerializedMetadataLibraryProvider +import org.jetbrains.kotlin.commonizer.tree.CirTreeModule +import org.jetbrains.kotlin.commonizer.utils.foldToMap +import org.jetbrains.kotlin.library.SerializedMetadata + +internal class ModuleCirTreeDeserializer( + private val packageDeserializer: PackageCirTreeDeserializer +) { + operator fun invoke(metadata: SerializedMetadata, typeResolver: CirTypeResolver): CirTreeModule { + val module = KlibModuleMetadata.read(SerializedMetadataLibraryProvider(metadata)) + + val fragmentsByPackage: Map> = module.fragments.foldToMap { fragment -> + fragment.fqName?.let(CirPackageName.Companion::create) + ?: error("A fragment without FQ name in module ${module.name}: $fragment") + } + + val packages = fragmentsByPackage.map { (packageName, fragments) -> + packageDeserializer(packageName, fragments, typeResolver) + } + + return CirTreeModule( + module = CirModule.create(CirName.create(module.name)), + packages = packages + ) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/PackageCirTreeDeserializer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/PackageCirTreeDeserializer.kt new file mode 100644 index 00000000000..e81b32a510d --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/PackageCirTreeDeserializer.kt @@ -0,0 +1,55 @@ +/* + * 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.tree.deserializer + +import kotlinx.metadata.KmModuleFragment +import org.jetbrains.kotlin.commonizer.cir.CirPackage +import org.jetbrains.kotlin.commonizer.cir.CirPackageName +import org.jetbrains.kotlin.commonizer.mergedtree.mergers.ClassesToProcess +import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver +import org.jetbrains.kotlin.commonizer.tree.CirTreePackage + +internal class PackageCirTreeDeserializer( + private val propertyDeserializer: PropertyCirTreeDeserializer, + private val functionDeserializer: FunctionCirTreeDeserializer, + private val typeAliasDeserializer: TypeAliasCirTreeDeserializer, + private val classDeserializer: ClassCirTreeDeserializer, +) { + operator fun invoke( + packageName: CirPackageName, + fragments: Collection, + typeResolver: CirTypeResolver + ): CirTreePackage { + val pkg = CirPackage.create(packageName) + + val properties = fragments.asSequence().mapNotNull { it.pkg } + .flatMap { it.properties } + .mapNotNull { property -> propertyDeserializer(property, null, typeResolver) } + .toList() + + val functions = fragments.asSequence().mapNotNull { it.pkg } + .flatMap { it.functions } + .mapNotNull { function -> functionDeserializer(function, null, typeResolver) } + .toList() + + val typeAliases = fragments.asSequence().mapNotNull { it.pkg } + .flatMap { it.typeAliases } + .mapNotNull { typeAlias -> typeAliasDeserializer(typeAlias, pkg.packageName, typeResolver) } + .toList() + + val classes = ClassesToProcess() + .apply { fragments.forEach { fragment -> addClassesFromFragment(fragment) } } + .run { classesInScope(parentClassId = null).map { classEntry -> classDeserializer(classEntry, this, typeResolver) } } + + return CirTreePackage( + pkg = pkg, + properties = properties, + functions = functions, + typeAliases = typeAliases, + classes = classes + ) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/PropertyCirTreeDeserializer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/PropertyCirTreeDeserializer.kt new file mode 100644 index 00000000000..1c2e81861c3 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/PropertyCirTreeDeserializer.kt @@ -0,0 +1,31 @@ +/* + * 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.tree.deserializer + +import kotlinx.metadata.KmProperty +import org.jetbrains.kotlin.commonizer.cir.CirContainingClass +import org.jetbrains.kotlin.commonizer.mergedtree.PropertyApproximationKey +import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers +import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver +import org.jetbrains.kotlin.commonizer.tree.CirTreeProperty +import org.jetbrains.kotlin.commonizer.utils.isFakeOverride + +object PropertyCirTreeDeserializer { + operator fun invoke(property: KmProperty, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirTreeProperty? { + if (property.isFakeOverride()) return null + val propertyTypeResolver = typeResolver.create(property.typeParameters) + val approximationKey = PropertyApproximationKey(property, propertyTypeResolver) + return CirTreeProperty( + approximationKey = PropertyApproximationKey(property, propertyTypeResolver), + property = CirDeserializers.property( + name = approximationKey.name, + source = property, + containingClass = containingClass, + typeResolver = propertyTypeResolver + ) + ) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/RootCirTreeDeserializer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/RootCirTreeDeserializer.kt new file mode 100644 index 00000000000..262cdda121c --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/RootCirTreeDeserializer.kt @@ -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.tree.deserializer + +import org.jetbrains.kotlin.commonizer.CommonizerParameters +import org.jetbrains.kotlin.commonizer.TargetProvider +import org.jetbrains.kotlin.commonizer.getCommonModuleNames +import org.jetbrains.kotlin.commonizer.mergedtree.CirFictitiousFunctionClassifiers +import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers +import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver +import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot + +internal class RootCirTreeDeserializer( + private val moduleDeserializer: ModuleCirTreeDeserializer +) { + operator fun invoke(parameters: CommonizerParameters, targetProvider: TargetProvider): CirTreeRoot { + + val commonModuleInfos = targetProvider.modulesProvider.loadModuleInfos() + .filter { moduleInfo -> moduleInfo.name in parameters.getCommonModuleNames() } + + val typeResolver = CirTypeResolver.create( + providedClassifiers = CirProvidedClassifiers.of( + CirProvidedClassifiers.by(targetProvider.modulesProvider), + CirProvidedClassifiers.by(targetProvider.dependencyModulesProvider), + CirProvidedClassifiers.of( + CirFictitiousFunctionClassifiers, + CirProvidedClassifiers.by(parameters.commonDependencyModulesProvider) + ) + ) + ) + + return CirTreeRoot( + modules = commonModuleInfos.map { moduleInfo -> + val metadata = targetProvider.modulesProvider.loadModuleMetadata(moduleInfo.name) + moduleDeserializer(metadata, typeResolver) + } + ) + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/TypeAliasCirTreeDeserializer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/TypeAliasCirTreeDeserializer.kt new file mode 100644 index 00000000000..061b6e77649 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/TypeAliasCirTreeDeserializer.kt @@ -0,0 +1,31 @@ +/* + * 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.tree.deserializer + +import kotlinx.metadata.KmTypeAlias +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.metadata.CirDeserializers +import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver +import org.jetbrains.kotlin.commonizer.tree.CirTreeTypeAlias + + +internal object TypeAliasCirTreeDeserializer { + operator fun invoke(typeAlias: KmTypeAlias, packageName: CirPackageName, typeResolver: CirTypeResolver): CirTreeTypeAlias { + val typeAliasTypeResolver = typeResolver.create(typeAlias.typeParameters) + val typeAliasName = CirName.create(typeAlias.name) + return CirTreeTypeAlias( + id = CirEntityId.create(packageName, typeAliasName), + typeAlias = CirDeserializers.typeAlias( + name = typeAliasName, + source = typeAlias, + typeResolver = typeAliasTypeResolver + ) + ) + } +} + diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/deserialize.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/deserialize.kt new file mode 100644 index 00000000000..c8625d6029f --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/deserializer/deserialize.kt @@ -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.tree.deserializer + +import org.jetbrains.kotlin.commonizer.CommonizerParameters +import org.jetbrains.kotlin.commonizer.TargetProvider +import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot + + +private val defaultRootCirTreeDeserializer = RootCirTreeDeserializer( + ModuleCirTreeDeserializer( + packageDeserializer = PackageCirTreeDeserializer( + propertyDeserializer = PropertyCirTreeDeserializer, + functionDeserializer = FunctionCirTreeDeserializer, + typeAliasDeserializer = TypeAliasCirTreeDeserializer, + classDeserializer = ClassCirTreeDeserializer( + propertyDeserializer = PropertyCirTreeDeserializer, + functionDeserializer = FunctionCirTreeDeserializer, + constructorDeserializer = ClassConstructorCirTreeDeserializer + ) + ) + ) +) + +internal fun deserialize(parameters: CommonizerParameters, target: TargetProvider): CirTreeRoot { + return defaultRootCirTreeDeserializer(parameters, target) +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/merger/merge.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/merger/merge.kt new file mode 100644 index 00000000000..36b1d9cbc62 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/tree/merger/merge.kt @@ -0,0 +1,90 @@ +/* + * 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.tree.merger + +import org.jetbrains.kotlin.commonizer.TargetDependent +import org.jetbrains.kotlin.commonizer.cir.CirRoot +import org.jetbrains.kotlin.commonizer.mergedtree.* +import org.jetbrains.kotlin.commonizer.tree.* +import org.jetbrains.kotlin.storage.StorageManager + +internal data class TargetBuildingContext( + val storageManager: StorageManager, val classifiers: CirKnownClassifiers, val targets: Int, val targetIndex: Int +) + +internal fun mergeCirTree( + storageManager: StorageManager, classifiers: CirKnownClassifiers, roots: TargetDependent +): CirRootNode { + val node = buildRootNode(storageManager, roots.size) + roots.targets.withIndex().forEach { (targetIndex, target) -> + node.targetDeclarations[targetIndex] = CirRoot.create(target) + node.buildModules(TargetBuildingContext(storageManager, classifiers, roots.size, targetIndex), roots[target].modules) + } + return node +} + +internal fun CirRootNode.buildModules(context: TargetBuildingContext, modules: List) { + modules.forEach { module -> buildModule(context, module) } +} + +internal fun CirRootNode.buildModule(context: TargetBuildingContext, treeModule: CirTreeModule) { + val moduleNode = modules.getOrPut(treeModule.module.name) { + buildModuleNode(context.storageManager, context.targets) + } + moduleNode.targetDeclarations[context.targetIndex] = treeModule.module + treeModule.packages.forEach { pkg -> moduleNode.buildPackage(context, pkg) } +} + +internal fun CirModuleNode.buildPackage(context: TargetBuildingContext, treePackage: CirTreePackage) { + val packageNode = packages.getOrPut(treePackage.pkg.packageName) { + buildPackageNode(context.storageManager, context.targets) + } + packageNode.targetDeclarations[context.targetIndex] = treePackage.pkg + treePackage.functions.forEach { function -> packageNode.buildFunction(context, function) } + treePackage.properties.forEach { property -> packageNode.buildProperty(context, property) } + treePackage.typeAliases.forEach { typeAlias -> packageNode.buildTypeAlias(context, typeAlias) } + treePackage.classes.forEach { clazz -> packageNode.buildClass(context, clazz) } +} + +internal fun CirNodeWithMembers<*, *>.buildClass(context: TargetBuildingContext, treeClass: CirTreeClass) { + val classNode = classes.getOrPut(treeClass.clazz.name) { + buildClassNode(context.storageManager, context.targets, context.classifiers, treeClass.id) + } + classNode.targetDeclarations[context.targetIndex] = treeClass.clazz + treeClass.functions.forEach { function -> classNode.buildFunction(context, function) } + treeClass.properties.forEach { property -> classNode.buildProperty(context, property) } + treeClass.constructors.forEach { constructor -> classNode.buildConstructor(context, constructor) } + treeClass.classes.forEach { clazz -> classNode.buildClass(context, clazz) } +} + +internal fun CirNodeWithMembers<*, *>.buildFunction(context: TargetBuildingContext, treeFunction: CirTreeFunction) { + val functionNode = functions.getOrPut(treeFunction.approximationKey) { + buildFunctionNode(context.storageManager, context.targets, context.classifiers) + } + functionNode.targetDeclarations[context.targetIndex] = treeFunction.function +} + +internal fun CirNodeWithMembers<*, *>.buildProperty(context: TargetBuildingContext, treeProperty: CirTreeProperty) { + val propertyNode = properties.getOrPut(treeProperty.approximationKey) { + buildPropertyNode(context.storageManager, context.targets, context.classifiers) + } + propertyNode.targetDeclarations[context.targetIndex] = treeProperty.property +} + +internal fun CirClassNode.buildConstructor(context: TargetBuildingContext, treeConstructor: CirTreeClassConstructor) { + val constructorNode = constructors.getOrPut(treeConstructor.approximationKey) { + buildClassConstructorNode(context.storageManager, context.targets, context.classifiers) + } + constructorNode.targetDeclarations[context.targetIndex] = treeConstructor.constructor +} + +internal fun CirPackageNode.buildTypeAlias(context: TargetBuildingContext, treeTypeAlias: CirTreeTypeAlias) { + val typeAliasNode = typeAliases.getOrPut(treeTypeAlias.typeAlias.name) { + buildTypeAliasNode(context.storageManager, context.targets, context.classifiers, treeTypeAlias.id) + } + typeAliasNode.targetDeclarations[context.targetIndex] = treeTypeAlias.typeAlias +} + diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/AbstractCommonizationFromSourcesTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/AbstractCommonizationFromSourcesTest.kt index 195e93574a3..bf60281883e 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/AbstractCommonizationFromSourcesTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/AbstractCommonizationFromSourcesTest.kt @@ -16,15 +16,15 @@ import org.jetbrains.kotlin.backend.common.serialization.metadata.impl.ExportedF import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.config.CommonConfigurationKeys -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.languageVersionSettings -import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.commonizer.ResultsConsumer.ModuleResult import org.jetbrains.kotlin.commonizer.ResultsConsumer.Status import org.jetbrains.kotlin.commonizer.SourceModuleRoot.Companion.SHARED_TARGET_NAME import org.jetbrains.kotlin.commonizer.konan.NativeManifestDataProvider import org.jetbrains.kotlin.commonizer.utils.* +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl @@ -208,7 +208,7 @@ private class AnalyzedModules( resultsConsumer: ResultsConsumer, manifestDataProvider: NativeManifestDataProvider = MockNativeManifestDataProvider() ) = CommonizerParameters( - targetProviders = leafTargets.map { leafTarget -> + targetProviders = TargetDependent(leafTargets) { leafTarget -> TargetProvider( target = leafTarget, modulesProvider = MockModulesProvider.create(originalModules.getValue(leafTarget)), diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CommonizerFacadeTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CommonizerFacadeTest.kt index 8cfff714c99..953acbe6f14 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CommonizerFacadeTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CommonizerFacadeTest.kt @@ -8,9 +8,9 @@ package org.jetbrains.kotlin.commonizer import org.jetbrains.kotlin.commonizer.ResultsConsumer.ModuleResult import org.jetbrains.kotlin.commonizer.ResultsConsumer.Status import org.jetbrains.kotlin.commonizer.konan.NativeManifestDataProvider -import org.jetbrains.kotlin.commonizer.utils.MockResultsConsumer import org.jetbrains.kotlin.commonizer.utils.MockModulesProvider import org.jetbrains.kotlin.commonizer.utils.MockNativeManifestDataProvider +import org.jetbrains.kotlin.commonizer.utils.MockResultsConsumer import org.junit.Test import kotlin.contracts.ExperimentalContracts import kotlin.test.assertEquals @@ -69,14 +69,15 @@ class CommonizerFacadeTest { resultsConsumer: ResultsConsumer, manifestDataProvider: NativeManifestDataProvider = MockNativeManifestDataProvider() ) = CommonizerParameters( - targetProviders = map { (targetName, moduleNames) -> - TargetProvider( - target = LeafCommonizerTarget(targetName), - modulesProvider = MockModulesProvider.create(moduleNames), - dependencyModulesProvider = null, - manifestProvider = manifestDataProvider, - ) - }, + targetProviders = mapKeys { (targetName, _) -> LeafCommonizerTarget(targetName) }.toTargetDependent() + .map { target, moduleNames -> + TargetProvider( + target = target, + modulesProvider = MockModulesProvider.create(moduleNames), + dependencyModulesProvider = null, + manifestProvider = manifestDataProvider, + ) + }, resultsConsumer = resultsConsumer, commonManifestProvider = manifestDataProvider )