[Commonizer] Clean-up in facade API

This commit is contained in:
Dmitriy Dolovov
2019-09-24 21:56:18 +07:00
parent acd146363e
commit 25e5442a13
24 changed files with 143 additions and 180 deletions
+2
View File
@@ -9,6 +9,8 @@ dependencies {
compile(kotlinStdlib()) compile(kotlinStdlib())
compile(project(":kotlin-native:kotlin-native-utils"))
testCompile(commonDep("junit:junit")) testCompile(commonDep("junit:junit"))
testCompile(projectTests(":compiler:tests-common")) testCompile(projectTests(":compiler:tests-common"))
@@ -5,13 +5,15 @@
package org.jetbrains.kotlin.descriptors.commonizer package org.jetbrains.kotlin.descriptors.commonizer
import org.jetbrains.kotlin.konan.target.KonanTarget
// N.B. TargetPlatform/SimplePlatform are non exhaustive enough to address both target platforms such as // N.B. TargetPlatform/SimplePlatform are non exhaustive enough to address both target platforms such as
// JVM, JS and concrete Kotlin/Native targets, e.g. macos_x64, ios_x64, linux_x64. // JVM, JS and concrete Kotlin/Native targets, e.g. macos_x64, ios_x64, linux_x64.
sealed class TargetId sealed class Target
data class ConcreteTargetId(val name: String) : TargetId() data class InputTarget(val name: String, val konanTarget: KonanTarget? = null) : Target()
data class CommonTargetId(val targets: Set<TargetId>) : TargetId() { data class OutputTarget(val targets: Set<Target>) : Target() {
init { init {
require(targets.isNotEmpty()) require(targets.isNotEmpty())
} }
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroup import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroup
import org.jetbrains.kotlin.descriptors.commonizer.TargetId import org.jetbrains.kotlin.descriptors.commonizer.Target
import org.jetbrains.kotlin.descriptors.commonizer.builder.CommonizedMemberScope.Companion.plusAssign import org.jetbrains.kotlin.descriptors.commonizer.builder.CommonizedMemberScope.Companion.plusAssign
import org.jetbrains.kotlin.descriptors.commonizer.builder.CommonizedPackageFragmentProvider.Companion.plusAssign import org.jetbrains.kotlin.descriptors.commonizer.builder.CommonizedPackageFragmentProvider.Companion.plusAssign
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.* import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.*
@@ -21,12 +21,12 @@ import org.jetbrains.kotlin.utils.addIfNotNull
internal class DeclarationsBuilderVisitor( internal class DeclarationsBuilderVisitor(
private val storageManager: StorageManager, private val storageManager: StorageManager,
private val builtIns: KotlinBuiltIns, private val builtIns: KotlinBuiltIns,
private val collector: (TargetId, Collection<ModuleDescriptor>) -> Unit private val collector: (Target, Collection<ModuleDescriptor>) -> Unit
) : NodeVisitor<List<DeclarationDescriptor?>, List<DeclarationDescriptor?>> { ) : NodeVisitor<List<DeclarationDescriptor?>, List<DeclarationDescriptor?>> {
override fun visitRootNode(node: RootNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> { override fun visitRootNode(node: RootNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
val allTargets = (node.target + node.common()!!).map { it.targetId } val allTargets = (node.target + node.common()!!).map { it.target }
val modulesByTargets = HashMap<TargetId, MutableList<ModuleDescriptorImpl>>() val modulesByTargets = HashMap<Target, MutableList<ModuleDescriptorImpl>>()
// collect module descriptors: // collect module descriptors:
for (moduleNode in node.modules) { for (moduleNode in node.modules) {
@@ -45,7 +45,7 @@ internal class DeclarationsBuilderVisitor(
// return result (preserve platforms order): // return result (preserve platforms order):
for (target in allTargets) { for (target in allTargets) {
collector(target, modulesByTargets[target]!!) collector(target, modulesByTargets.getValue(target))
} }
return noReturningDeclarations() return noReturningDeclarations()
@@ -35,7 +35,7 @@ private fun Module.buildDescriptor(
moduleName = name, moduleName = name,
storageManager = storageManager, storageManager = storageManager,
builtIns = builtIns, builtIns = builtIns,
capabilities = emptyMap() // TODO: specify capabilities capabilities = emptyMap() // TODO: preserve capabilities from the original module descriptors, KT-33998
) )
output[index] = moduleDescriptor output[index] = moduleDescriptor
@@ -27,9 +27,6 @@ internal fun PropertyNode.buildDescriptors(
val markAsExpectAndActual = commonProperty != null && commonProperty.kind != CallableMemberDescriptor.Kind.SYNTHESIZED val markAsExpectAndActual = commonProperty != null && commonProperty.kind != CallableMemberDescriptor.Kind.SYNTHESIZED
target.forEachIndexed { index, property -> target.forEachIndexed { index, property ->
// target property is DELEGATION
// AND
// the property it overrides is actual
property?.buildDescriptor(output, index, containingDeclarations, storageManager, isActual = markAsExpectAndActual) property?.buildDescriptor(output, index, containingDeclarations, storageManager, isActual = markAsExpectAndActual)
} }
@@ -31,7 +31,8 @@ private class DefaultModalityCommonizer : ModalityCommonizer {
return !error return !error
} }
private fun getNext(current: Modality, next: Modality): Modality? = when { @Suppress("NOTHING_TO_INLINE")
private inline fun getNext(current: Modality, next: Modality): Modality? = when {
current == Modality.FINAL && next == Modality.OPEN -> Modality.FINAL current == Modality.FINAL && next == Modality.OPEN -> Modality.FINAL
current == Modality.OPEN && next == Modality.FINAL -> Modality.FINAL current == Modality.OPEN && next == Modality.FINAL -> Modality.FINAL
current == next -> current current == next -> current
@@ -106,7 +106,7 @@ private fun areAbbreviatedTypesEqual(
return false return false
// N.B. both lists of arguments are already known to be of the same size // N.B. both lists of arguments are already known to be of the same size
for (i in 0 until a.arguments.size) { for (i in a.arguments.indices) {
val aArg = a.arguments[i] val aArg = a.arguments[i]
val bArg = b.arguments[i] val bArg = b.arguments[i]
@@ -13,26 +13,24 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.mergeRoots
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
class CommonizationParameters { class CommonizationParameters {
private val modulesByTargets = LinkedHashMap<ConcreteTargetId, Collection<ModuleDescriptor>>() // use linked hash map to preserve order
private val modulesByTargets = LinkedHashMap<InputTarget, Collection<ModuleDescriptor>>()
fun addTarget(targetName: String, modules: Collection<ModuleDescriptor>): CommonizationParameters { fun addTarget(target: InputTarget, modules: Collection<ModuleDescriptor>): CommonizationParameters {
val targetId = ConcreteTargetId(targetName) require(target !in modulesByTargets) { "Target $target is already added" }
require(targetId !in modulesByTargets) {
"Target $targetId is already added"
}
val modulesWithUniqueNames = modules.groupingBy { it.name }.eachCount() val modulesWithUniqueNames = modules.groupingBy { it.name }.eachCount()
require(modulesWithUniqueNames.size == modules.size) { require(modulesWithUniqueNames.size == modules.size) {
"Modules with duplicated names found: ${modulesWithUniqueNames.filter { it.value > 1 }}" "Modules with duplicated names found: ${modulesWithUniqueNames.filter { it.value > 1 }}"
} }
modulesByTargets[targetId] = modules modulesByTargets[target] = modules
return this return this
} }
// get them as ordered immutable collection (List) for further processing // get them as ordered immutable collection (List) for further processing
fun getModulesByTargets(): List<Pair<ConcreteTargetId, Collection<ModuleDescriptor>>> = fun getModulesByTargets(): List<Pair<InputTarget, Collection<ModuleDescriptor>>> =
modulesByTargets.map { it.key to it.value } modulesByTargets.map { it.key to it.value }
fun hasIntersection(): Boolean { fun hasIntersection(): Boolean {
@@ -51,9 +49,16 @@ sealed class CommonizationResult
object NothingToCommonize : CommonizationResult() object NothingToCommonize : CommonizationResult()
class CommonizationPerformed( class CommonizationPerformed(
val commonModules: Collection<ModuleDescriptor>, val modulesByTargets: Map<Target, Collection<ModuleDescriptor>>
val modulesByTargets: Map<String, Collection<ModuleDescriptor>> ) : CommonizationResult() {
) : CommonizationResult() val commonTarget: OutputTarget by lazy {
modulesByTargets.keys.filterIsInstance<OutputTarget>().single()
}
val concreteTargets: Set<InputTarget> by lazy {
modulesByTargets.keys.filterIsInstance<InputTarget>().toSet()
}
}
fun runCommonization(parameters: CommonizationParameters): CommonizationResult { fun runCommonization(parameters: CommonizationParameters): CommonizationResult {
if (!parameters.hasIntersection()) if (!parameters.hasIntersection())
@@ -66,24 +71,14 @@ fun runCommonization(parameters: CommonizationParameters): CommonizationResult {
// commonize: // commonize:
mergedTree.accept(CommonizationVisitor(mergedTree), Unit) mergedTree.accept(CommonizationVisitor(mergedTree), Unit)
var commonModules: Collection<ModuleDescriptor>? = null val modulesByTargets = LinkedHashMap<Target, Collection<ModuleDescriptor>>() // use linked hash map to preserve order
val otherModulesByTargets = LinkedHashMap<String, Collection<ModuleDescriptor>>()
// build resulting descriptors: // build resulting descriptors:
val visitor = DeclarationsBuilderVisitor(storageManager, DefaultBuiltIns.Instance) { targetId, commonizedModules -> val visitor = DeclarationsBuilderVisitor(storageManager, DefaultBuiltIns.Instance) { target, commonizedModules ->
when (targetId) { check(target !in modulesByTargets)
is CommonTargetId -> { modulesByTargets[target] = commonizedModules
check(commonModules == null)
commonModules = commonizedModules
}
is ConcreteTargetId -> {
val targetName = targetId.name
check(targetName !in otherModulesByTargets)
otherModulesByTargets[targetName] = commonizedModules
}
}
} }
mergedTree.accept(visitor, DeclarationsBuilderVisitor.noContainingDeclarations()) mergedTree.accept(visitor, DeclarationsBuilderVisitor.noContainingDeclarations())
return CommonizationPerformed(commonModules!!, otherModulesByTargets) return CommonizationPerformed(modulesByTargets)
} }
@@ -5,8 +5,9 @@
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
data class Module( data class Module(val name: Name) : Declaration {
val name: Name constructor(descriptor: ModuleDescriptor) : this(descriptor.name)
) : Declaration }
@@ -7,6 +7,4 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
data class Package( data class Package(val fqName: FqName) : Declaration
val fqName: FqName
) : Declaration
@@ -5,6 +5,6 @@
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
import org.jetbrains.kotlin.descriptors.commonizer.TargetId import org.jetbrains.kotlin.descriptors.commonizer.Target
data class Root(val targetId: TargetId) : Declaration data class Root(val target: Target) : Declaration
@@ -12,39 +12,39 @@ import org.jetbrains.kotlin.descriptors.commonizer.core.*
import org.jetbrains.kotlin.descriptors.commonizer.firstNonNull import org.jetbrains.kotlin.descriptors.commonizer.firstNonNull
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode.ClassifiersCacheImpl import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode.ClassifiersCacheImpl
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.NullableLazyValue import org.jetbrains.kotlin.storage.NullableLazyValue
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
internal fun buildRootNode( internal fun buildRootNode(
targets: List<ConcreteTargetId> storageManager: StorageManager,
targets: List<InputTarget>
): RootNode = RootNode( ): RootNode = RootNode(
target = targets.map { Root(it) }, target = targets.map { Root(it) },
common = LockBasedStorageManager.NO_LOCKS.createNullableLazyValue { common = storageManager.createNullableLazyValue {
Root(CommonTargetId(targets.toSet())) Root(OutputTarget(targets.toSet()))
} }
) )
internal fun buildModuleNode( internal fun buildModuleNode(
moduleName: Name, storageManager: StorageManager,
modules: List<ModuleDescriptor?> modules: List<ModuleDescriptor?>
): ModuleNode = buildNode( ): ModuleNode = buildNode(
storageManager = LockBasedStorageManager.NO_LOCKS, storageManager = storageManager,
descriptors = modules, descriptors = modules,
targetDeclarationProducer = { Module(moduleName) }, targetDeclarationProducer = ::Module,
commonValueProducer = { Module(moduleName) }, commonValueProducer = { Module(it.firstNonNull().name) },
recursionMarker = null, recursionMarker = null,
nodeProducer = ::ModuleNode nodeProducer = ::ModuleNode
) )
internal fun buildPackageNode( internal fun buildPackageNode(
storageManager: StorageManager,
packageFqName: FqName, packageFqName: FqName,
packageMemberScopes: List<MemberScope?> packageMemberScopes: List<MemberScope?>
): PackageNode = buildNode( ): PackageNode = buildNode(
storageManager = LockBasedStorageManager.NO_LOCKS, storageManager = storageManager,
descriptors = packageMemberScopes, descriptors = packageMemberScopes,
targetDeclarationProducer = { Package(packageFqName) }, targetDeclarationProducer = { Package(packageFqName) },
commonValueProducer = { Package(packageFqName) }, commonValueProducer = { Package(packageFqName) },
@@ -22,10 +22,9 @@ import org.jetbrains.kotlin.utils.alwaysTrue
internal fun mergeModules( internal fun mergeModules(
storageManager: StorageManager, storageManager: StorageManager,
cacheRW: RootNode.ClassifiersCacheImpl, cacheRW: RootNode.ClassifiersCacheImpl,
moduleName: Name,
modules: List<ModuleDescriptor?> modules: List<ModuleDescriptor?>
): ModuleNode { ): ModuleNode {
val node = buildModuleNode(moduleName, modules) val node = buildModuleNode(storageManager, modules)
val packageMemberScopesMap = CommonizedGroupMap<FqName, MemberScope>(modules.size) val packageMemberScopesMap = CommonizedGroupMap<FqName, MemberScope>(modules.size)
@@ -24,7 +24,7 @@ internal fun mergePackages(
packageFqName: FqName, packageFqName: FqName,
packageMemberScopes: List<MemberScope?> packageMemberScopes: List<MemberScope?>
): PackageNode { ): PackageNode {
val node = buildPackageNode(packageFqName, packageMemberScopes) val node = buildPackageNode(storageManager, packageFqName, packageMemberScopes)
val propertiesMap = CommonizedGroupMap<PropertyApproximationKey, PropertyDescriptor>(packageMemberScopes.size) val propertiesMap = CommonizedGroupMap<PropertyApproximationKey, PropertyDescriptor>(packageMemberScopes.size)
val functionsMap = CommonizedGroupMap<FunctionApproximationKey, SimpleFunctionDescriptor>(packageMemberScopes.size) val functionsMap = CommonizedGroupMap<FunctionApproximationKey, SimpleFunctionDescriptor>(packageMemberScopes.size)
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroupMap import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroupMap
import org.jetbrains.kotlin.descriptors.commonizer.ConcreteTargetId import org.jetbrains.kotlin.descriptors.commonizer.InputTarget
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildRootNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildRootNode
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -15,9 +15,9 @@ import org.jetbrains.kotlin.storage.StorageManager
internal fun mergeRoots( internal fun mergeRoots(
storageManager: StorageManager, storageManager: StorageManager,
modulesByTargets: List<Pair<ConcreteTargetId, Collection<ModuleDescriptor>>> modulesByTargets: List<Pair<InputTarget, Collection<ModuleDescriptor>>>
): RootNode { ): RootNode {
val node = buildRootNode(modulesByTargets.map { it.first }) val node = buildRootNode(storageManager, modulesByTargets.map { it.first })
val modulesMap = CommonizedGroupMap<Name, ModuleDescriptor>(modulesByTargets.size) val modulesMap = CommonizedGroupMap<Name, ModuleDescriptor>(modulesByTargets.size)
@@ -27,8 +27,8 @@ internal fun mergeRoots(
} }
} }
for ((moduleName, modulesGroup) in modulesMap) { for ((_, modulesGroup) in modulesMap) {
node.modules += mergeModules(storageManager, node.cache, moduleName, modulesGroup.toList()) node.modules += mergeModules(storageManager, node.cache, modulesGroup.toList())
} }
return node return node
@@ -32,12 +32,12 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
} }
fun Collection<ModuleDescriptor>.eachModuleAsTarget() = mapIndexed { index, moduleDescriptor -> fun Collection<ModuleDescriptor>.eachModuleAsTarget() = mapIndexed { index, moduleDescriptor ->
"target_$index" to moduleDescriptor InputTarget("target_$index") to moduleDescriptor
}.toMap().toCommonizationParameters() }.toMap().toCommonizationParameters()
fun Map<String, ModuleDescriptor>.toCommonizationParameters() = CommonizationParameters().also { fun Map<InputTarget, ModuleDescriptor>.toCommonizationParameters() = CommonizationParameters().also {
forEach { (targetName, moduleDescriptor) -> forEach { (target, moduleDescriptor) ->
it.addTarget(targetName, listOf(moduleDescriptor)) it.addTarget(target, listOf(moduleDescriptor))
} }
} }
} }
@@ -71,7 +71,7 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
.also(::assertIsDirectory) .also(::assertIsDirectory)
} }
protected val sourceModuleRoots: Pair<Set<File>, Set<File>> protected val sourceModuleRoots: Triple<Set<File>, Set<File>, File>
get() { get() {
val testDataDir = testDataDir val testDataDir = testDataDir
@@ -89,19 +89,21 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
?.toSet() ?.toSet()
?.also { it.forEach(::assertIsDirectory) } ?.also { it.forEach(::assertIsDirectory) }
val commonRoot = commonizedRoots?.singleOrNull { it.name == "common" }
check( check(
!originalRoots.isNullOrEmpty() && !commonizedRoots.isNullOrEmpty() !originalRoots.isNullOrEmpty() && !commonizedRoots.isNullOrEmpty() && commonRoot != null
&& (originalRoots.map { it.name } + "common").toSet() == commonizedRoots.map { it.name }.toSet() && (originalRoots + commonRoot).map { it.name }.toSet() == commonizedRoots.map { it.name }.toSet()
) { ) {
"Source module misconfiguration in $testDataDir" "Source module misconfiguration in $testDataDir"
} }
return originalRoots to commonizedRoots return Triple(originalRoots, commonizedRoots - commonRoot, commonRoot)
} }
protected val sourceModuleDescriptors: Pair<Map<String, ModuleDescriptor>, Map<String, ModuleDescriptor>> protected val sourceModuleDescriptors: Pair<Map<InputTarget, ModuleDescriptor>, Map<Target, ModuleDescriptor>>
get() { get() {
fun analyzeTarget(targetRoot: File): Pair<String, ModuleDescriptor> { fun analyzeTarget(targetRoot: File): ModuleDescriptor {
val environment = createEnvironment(targetRoot.parentFile.parentFile.name) val environment = createEnvironment(targetRoot.parentFile.parentFile.name)
val psiFactory = KtPsiFactory(environment.project) val psiFactory = KtPsiFactory(environment.project)
@@ -110,7 +112,7 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
.map { psiFactory.createFile(it.name, doLoadFile(it)) } .map { psiFactory.createFile(it.name, doLoadFile(it)) }
.toList() .toList()
val moduleDescriptor = CommonResolverForModuleFactory.analyzeFiles( return CommonResolverForModuleFactory.analyzeFiles(
files = psiFiles, files = psiFiles,
moduleName = environment.moduleName, moduleName = environment.moduleName,
dependOnBuiltIns = true, dependOnBuiltIns = true,
@@ -118,11 +120,19 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
) { content -> ) { content ->
environment.createPackagePartProvider(content.moduleContentScope) environment.createPackagePartProvider(content.moduleContentScope)
}.moduleDescriptor }.moduleDescriptor
return targetRoot.name to moduleDescriptor
} }
return sourceModuleRoots.first.map(::analyzeTarget).toMap() to sourceModuleRoots.second.map(::analyzeTarget).toMap() val originalModules = sourceModuleRoots.first
.map { InputTarget(it.name) to analyzeTarget(it) }
.toMap()
val commonizedModules = sourceModuleRoots.second
.map { InputTarget(it.name) to analyzeTarget(it) }
.toMap()
val commonModule = OutputTarget(commonizedModules.keys) to analyzeTarget(sourceModuleRoots.third)
return originalModules to commonizedModules + commonModule
} }
protected fun doTestSuccessfulCommonization() { protected fun doTestSuccessfulCommonization() {
@@ -131,23 +141,26 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
val result = runCommonization(originalModules.toCommonizationParameters()) val result = runCommonization(originalModules.toCommonizationParameters())
assertCommonizationPerformed(result) assertCommonizationPerformed(result)
val commonModuleAsExpected = commonizedModules.getValue("common") val commonTarget = commonizedModules.keys.filterIsInstance<OutputTarget>().single()
val commonModuleByCommonizer = result.commonModules.single() assertEquals(commonTarget, result.commonTarget)
val commonModuleAsExpected = commonizedModules.getValue(commonTarget)
val commonModuleByCommonizer = result.modulesByTargets.getValue(commonTarget).single()
assertValidModule(commonModuleAsExpected) assertValidModule(commonModuleAsExpected)
assertValidModule(commonModuleByCommonizer) assertValidModule(commonModuleByCommonizer)
assertModulesAreEqual(commonModuleAsExpected, commonModuleByCommonizer, "\"common\" target") assertModulesAreEqual(commonModuleAsExpected, commonModuleByCommonizer, "\"$commonTarget\" target")
val concreteTargetNames = commonizedModules.keys - "common" val concreteTargets = commonizedModules.keys - commonTarget
assertEquals(concreteTargetNames, result.modulesByTargets.keys) assertEquals(concreteTargets, result.concreteTargets)
for (targetName in concreteTargetNames) { for (target in concreteTargets) {
val targetModuleAsExpected = commonizedModules.getValue(targetName) val targetModuleAsExpected = commonizedModules.getValue(target)
val targetModuleByCommonizer = result.modulesByTargets.getValue(targetName).single() val targetModuleByCommonizer = result.modulesByTargets.getValue(target).single()
assertValidModule(targetModuleAsExpected) assertValidModule(targetModuleAsExpected)
assertValidModule(targetModuleByCommonizer) assertValidModule(targetModuleByCommonizer)
assertModulesAreEqual(targetModuleAsExpected, targetModuleByCommonizer, "\"$targetName\" target") assertModulesAreEqual(targetModuleAsExpected, targetModuleByCommonizer, "\"$target\" target")
} }
} }
} }
@@ -37,7 +37,7 @@ class CommonizerFacadeTest {
} }
@Test @Test
fun nothingToCommonize2() { fun commonized() {
val modules = listOf( val modules = listOf(
mockEmptyModule("<foo>"), mockEmptyModule("<foo>"),
mockEmptyModule("<foo>") mockEmptyModule("<foo>")
@@ -47,11 +47,11 @@ class CommonizerFacadeTest {
assertCommonizationPerformed(result) assertCommonizationPerformed(result)
assertSingleModuleForTarget("<foo>", result.commonModules) assertSingleModuleForTarget("<foo>", result.modulesByTargets.getValue(result.commonTarget))
assertEquals(2, result.modulesByTargets.size) assertEquals(2, result.concreteTargets.size)
for (modulesSamePlatform in result.modulesByTargets.values) { for (target in result.concreteTargets) {
assertSingleModuleForTarget("<foo>", modulesSamePlatform) assertSingleModuleForTarget("<foo>", result.modulesByTargets.getValue(target))
} }
} }
@@ -10,10 +10,8 @@ import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.junit.Test import org.junit.Test
@TypeRefinement
class DefaultExtensionReceiverCommonizerTest : AbstractCommonizerTest<ExtensionReceiver?, UnwrappedType?>() { class DefaultExtensionReceiverCommonizerTest : AbstractCommonizerTest<ExtensionReceiver?, UnwrappedType?>() {
@Test @Test
@@ -56,7 +54,6 @@ class DefaultExtensionReceiverCommonizerTest : AbstractCommonizerTest<ExtensionR
override fun createCommonizer() = ExtensionReceiverCommonizer.default(EMPTY_CLASSIFIERS_CACHE) override fun createCommonizer() = ExtensionReceiverCommonizer.default(EMPTY_CLASSIFIERS_CACHE)
} }
@TypeRefinement
private fun mockExtensionReceiver(typeFqName: String) = ExtensionReceiver( private fun mockExtensionReceiver(typeFqName: String) = ExtensionReceiver(
annotations = Annotations.EMPTY, annotations = Annotations.EMPTY,
type = mockClassType(typeFqName).unwrap() type = mockClassType(typeFqName).unwrap()
@@ -19,11 +19,9 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.getAbbreviation import org.jetbrains.kotlin.types.getAbbreviation
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@TypeRefinement
class DefaultTypeCommonizerTest : AbstractCommonizerTest<KotlinType, UnwrappedType>() { class DefaultTypeCommonizerTest : AbstractCommonizerTest<KotlinType, UnwrappedType>() {
private lateinit var cache: ClassifiersCacheImpl private lateinit var cache: ClassifiersCacheImpl
@@ -11,10 +11,8 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.junit.Test import org.junit.Test
@TypeRefinement
class DefaultTypeParameterCommonizerTest : AbstractCommonizerTest<TypeParameter, TypeParameter>() { class DefaultTypeParameterCommonizerTest : AbstractCommonizerTest<TypeParameter, TypeParameter>() {
override fun createCommonizer() = TypeParameterCommonizer.default(EMPTY_CLASSIFIERS_CACHE) override fun createCommonizer() = TypeParameterCommonizer.default(EMPTY_CLASSIFIERS_CACHE)
@@ -7,10 +7,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.junit.Test import org.junit.Test
@TypeRefinement
class DefaultTypeParameterListCommonizerTest : AbstractCommonizerTest<List<TypeParameter>, List<TypeParameter>>() { class DefaultTypeParameterListCommonizerTest : AbstractCommonizerTest<List<TypeParameter>, List<TypeParameter>>() {
@Test @Test
@@ -13,10 +13,8 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ValueParameter
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.junit.Test import org.junit.Test
@TypeRefinement
class DefaultValueParameterCommonizerTest : AbstractCommonizerTest<ValueParameter, ValueParameter>() { class DefaultValueParameterCommonizerTest : AbstractCommonizerTest<ValueParameter, ValueParameter>() {
@Test @Test
@@ -8,10 +8,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE
import org.jetbrains.kotlin.descriptors.commonizer.core.TestValueParameter.Companion.areEqual import org.jetbrains.kotlin.descriptors.commonizer.core.TestValueParameter.Companion.areEqual
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ValueParameter import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ValueParameter
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.junit.Test import org.junit.Test
@TypeRefinement
class DefaultValueParameterListCommonizerTest : AbstractCommonizerTest<List<ValueParameter>, List<ValueParameter>>() { class DefaultValueParameterListCommonizerTest : AbstractCommonizerTest<List<ValueParameter>, List<ValueParameter>>() {
@Test @Test
@@ -174,7 +172,7 @@ class DefaultValueParameterListCommonizerTest : AbstractCommonizerTest<List<Valu
else if (a == null || b == null || a.size != b.size) else if (a == null || b == null || a.size != b.size)
return false return false
for (i in 0 until a.size) { for (i in a.indices) {
if (!areEqual(EMPTY_CLASSIFIERS_CACHE, a[i], b[i])) if (!areEqual(EMPTY_CLASSIFIERS_CACHE, a[i], b[i]))
return false return false
} }
@@ -7,18 +7,15 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.commonizer.builder.CommonizedClassDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.builder.CommonizedTypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.* import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.*
import org.jetbrains.kotlin.descriptors.impl.AbstractTypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.parentOrNull import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import kotlin.random.Random import kotlin.random.Random
// expected special name for module // expected special name for module
@@ -28,57 +25,41 @@ internal fun mockEmptyModule(moduleName: String): ModuleDescriptor {
return module return module
} }
@TypeRefinement
internal fun mockClassType( internal fun mockClassType(
fqName: String, fqName: String,
nullable: Boolean = false nullable: Boolean = false
): KotlinType = LazyWrappedType(LockBasedStorageManager.NO_LOCKS) { ): KotlinType = LazyWrappedType(LockBasedStorageManager.NO_LOCKS) {
val classFqName = FqName(fqName) val classFqName = FqName(fqName)
val classTypeConstructor = object : AbstractClassTypeConstructor(LockBasedStorageManager.NO_LOCKS) { val classDescriptor = CommonizedClassDescriptor(
lateinit var classDescriptor: ClassDescriptor storageManager = LockBasedStorageManager.NO_LOCKS,
override fun getParameters(): List<TypeParameterDescriptor> = emptyList() containingDeclaration = createPackageFragmentForClassifier(classFqName),
override fun computeSupertypes(): List<KotlinType> = emptyList() annotations = Annotations.EMPTY,
override fun isDenotable() = true name = classFqName.shortName(),
override fun getDeclarationDescriptor() = classDescriptor kind = ClassKind.CLASS,
override val supertypeLoopChecker = SupertypeLoopChecker.EMPTY modality = Modality.FINAL,
override fun toString() = "class type constructor ${declarationDescriptor.name}" visibility = Visibilities.PUBLIC,
} isCompanion = false,
isData = false,
isInline = false,
isInner = false,
isExternal = false,
isExpect = false,
isActual = false,
companionObjectName = null,
supertypes = emptyList()
)
val classDescriptor = object : ClassDescriptorBase( classDescriptor.declaredTypeParameters = emptyList()
/*storageManager =*/ LockBasedStorageManager.NO_LOCKS,
/*containingDeclaration =*/ createPackageFragmentForClassifier(classFqName),
/*name =*/ classFqName.shortName(),
/*source =*/ SourceElement.NO_SOURCE,
/*isExternal =*/ false
) {
override fun getStaticScope() = MemberScope.Empty
override fun getConstructors(): List<ClassConstructorDescriptor> = emptyList()
override fun getCompanionObjectDescriptor(): ClassDescriptor? = null
override fun getKind() = ClassKind.CLASS
override fun getModality() = Modality.FINAL
override fun getVisibility() = Visibilities.PUBLIC
override fun isCompanionObject() = false
override fun isData() = false
override fun isInline() = false
override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? = null
override fun isExpect() = false
override fun getUnsubstitutedMemberScope(kotlinTypeRefiner: KotlinTypeRefiner) = MemberScope.Empty
override fun isActual() = false
override fun getSealedSubclasses(): List<ClassDescriptor> = emptyList()
override fun getTypeConstructor() = classTypeConstructor
override fun isInner() = false
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> = emptyList()
override val annotations = Annotations.EMPTY
override fun toString() = "class descriptor $name"
}
classTypeConstructor.classDescriptor = classDescriptor classDescriptor.initialize(
unsubstitutedMemberScope = MemberScope.Empty,
constructors = emptyList()
)
createSimpleType(classTypeConstructor, nullable) classDescriptor.defaultType.makeNullableAsSpecified(nullable)
} }
@TypeRefinement
internal fun mockTAType( internal fun mockTAType(
fqName: String, fqName: String,
nullable: Boolean = false, nullable: Boolean = false,
@@ -88,27 +69,24 @@ internal fun mockTAType(
val rightHandSideType = rightHandSideTypeProvider().lowerIfFlexible() val rightHandSideType = rightHandSideTypeProvider().lowerIfFlexible()
val typeAliasDescriptor = object : AbstractTypeAliasDescriptor( val typeAliasDescriptor = CommonizedTypeAliasDescriptor(
storageManager = LockBasedStorageManager.NO_LOCKS,
containingDeclaration = createPackageFragmentForClassifier(typeAliasFqName), containingDeclaration = createPackageFragmentForClassifier(typeAliasFqName),
annotations = Annotations.EMPTY, annotations = Annotations.EMPTY,
name = typeAliasFqName.shortName(), name = typeAliasFqName.shortName(),
sourceElement = SourceElement.NO_SOURCE, visibility = Visibilities.PUBLIC,
visibilityImpl = Visibilities.PUBLIC isActual = false
) { )
private val myDefaultType by lazy { createSimpleType(typeConstructor, nullable) }
override val storageManager = LockBasedStorageManager.NO_LOCKS
override fun getTypeConstructorTypeParameters(): List<TypeParameterDescriptor> = emptyList()
override val underlyingType by lazy { rightHandSideType.getAbbreviation() ?: rightHandSideType }
override fun getDefaultType() = myDefaultType
override val classDescriptor get() = expandedType.constructor.declarationDescriptor as ClassDescriptor?
override val constructors: Collection<TypeAliasConstructorDescriptor> = emptyList()
override fun substitute(substitutor: TypeSubstitutor) = this
override val expandedType by lazy { rightHandSideType }
}.apply {
initialize(emptyList())
}
(rightHandSideType.getAbbreviatedType()?.expandedType ?: rightHandSideType).withAbbreviation(typeAliasDescriptor.defaultType) typeAliasDescriptor.initialize(
declaredTypeParameters = emptyList(),
underlyingType = rightHandSideType.getAbbreviation() ?: rightHandSideType,
expandedType = rightHandSideType
)
(rightHandSideType.getAbbreviatedType()?.expandedType ?: rightHandSideType)
.withAbbreviation(typeAliasDescriptor.defaultType)
.makeNullableAsSpecified(nullable)
} }
private fun createPackageFragmentForClassifier(classifierFqName: FqName): PackageFragmentDescriptor = private fun createPackageFragmentForClassifier(classifierFqName: FqName): PackageFragmentDescriptor =
@@ -126,16 +104,6 @@ private fun createPackageFragmentForClassifier(classifierFqName: FqName): Packag
override fun toString() = "package $name" override fun toString() = "package $name"
} }
private fun createSimpleType(typeConstructor: TypeConstructor, nullable: Boolean): SimpleType =
KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
annotations = Annotations.EMPTY,
constructor = typeConstructor,
arguments = emptyList(),
nullable = nullable,
memberScope = MemberScope.Empty,
refinedTypeFactory = { null }
)
internal val EMPTY_CLASSIFIERS_CACHE = object : ClassifiersCache { internal val EMPTY_CLASSIFIERS_CACHE = object : ClassifiersCache {
override val classes: Map<FqName, ClassNode> get() = emptyMap() override val classes: Map<FqName, ClassNode> get() = emptyMap()
override val typeAliases: Map<FqName, TypeAliasNode> get() = emptyMap() override val typeAliases: Map<FqName, TypeAliasNode> get() = emptyMap()