[Commonizer] Rework CommonizedGroup API to make it more usable

This commit is contained in:
Dmitriy Dolovov
2020-06-17 21:56:43 +07:00
parent 63575582c4
commit 5cad8a793c
14 changed files with 46 additions and 60 deletions
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.descriptors.commonizer.builder package org.jetbrains.kotlin.descriptors.commonizer.builder
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.Target 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
@@ -31,7 +28,7 @@ internal class DeclarationsBuilderVisitor1(
check(data.isEmpty()) // root node may not have containing declarations check(data.isEmpty()) // root node may not have containing declarations
check(components.targetComponents.size == node.dimension) check(components.targetComponents.size == node.dimension)
val allTargets = (node.targetDeclarations.toList() + node.commonDeclaration()!!).map { it!!.target } val allTargets = (node.targetDeclarations + node.commonDeclaration()).map { it!!.target }
val modulesByTargets = HashMap<Target, MutableList<ModuleDescriptorImpl>>() val modulesByTargets = HashMap<Target, MutableList<ModuleDescriptorImpl>>()
@@ -56,30 +53,28 @@ internal class DeclarationsBuilderVisitor1(
// build module descriptors: // build module descriptors:
val moduleDescriptorsGroup = CommonizedGroup<ModuleDescriptorImpl>(node.dimension) val moduleDescriptorsGroup = CommonizedGroup<ModuleDescriptorImpl>(node.dimension)
node.buildDescriptors(components, moduleDescriptorsGroup) node.buildDescriptors(components, moduleDescriptorsGroup)
val moduleDescriptors = moduleDescriptorsGroup.toList()
// build package fragments: // build package fragments:
val packageFragmentProviders = CommonizedPackageFragmentProvider.createArray(node.dimension) val packageFragmentProviders = CommonizedPackageFragmentProvider.createArray(node.dimension)
for (packageNode in node.packages.values) { for (packageNode in node.packages.values) {
val packageFragments = packageNode.accept(this, moduleDescriptors).asListContaining<PackageFragmentDescriptor>() val packageFragments = packageNode.accept(this, moduleDescriptorsGroup).asListContaining<PackageFragmentDescriptor>()
packageFragmentProviders += packageFragments packageFragmentProviders += packageFragments
} }
// initialize module descriptors: // initialize module descriptors:
moduleDescriptors.forEachIndexed { index, moduleDescriptor -> moduleDescriptorsGroup.forEachIndexed { index, moduleDescriptor ->
moduleDescriptor?.initialize(packageFragmentProviders[index]) moduleDescriptor?.initialize(packageFragmentProviders[index])
} }
return moduleDescriptors return moduleDescriptorsGroup
} }
override fun visitPackageNode(node: CirPackageNode, data: List<DeclarationDescriptor?>): List<PackageFragmentDescriptor?> { override fun visitPackageNode(node: CirPackageNode, data: List<DeclarationDescriptor?>): List<PackageFragmentDescriptor?> {
val containingDeclarations = data.asListContaining<ModuleDescriptorImpl>() val containingDeclarations = data.asListContaining<ModuleDescriptorImpl>()
// build package fragments: // build package fragments:
val packageFragmentsGroup = CommonizedGroup<CommonizedPackageFragmentDescriptor>(node.dimension) val packageFragments = CommonizedGroup<CommonizedPackageFragmentDescriptor>(node.dimension)
node.buildDescriptors(components, packageFragmentsGroup, containingDeclarations) node.buildDescriptors(components, packageFragments, containingDeclarations)
val packageFragments = packageFragmentsGroup.toList()
// build package members: // build package members:
val packageMemberScopes = CommonizedMemberScope.createArray(node.dimension) val packageMemberScopes = CommonizedMemberScope.createArray(node.dimension)
@@ -105,9 +100,9 @@ internal class DeclarationsBuilderVisitor1(
error("This method should not be called in ${this::class.java}") error("This method should not be called in ${this::class.java}")
override fun visitClassNode(node: CirClassNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> { override fun visitClassNode(node: CirClassNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
val classesGroup = CommonizedGroup<ClassifierDescriptorWithTypeParameters>(node.dimension) val classifiers = CommonizedGroup<ClassifierDescriptorWithTypeParameters>(node.dimension)
node.buildDescriptors(components, classesGroup, data) node.buildDescriptors(components, classifiers, data)
val classes = classesGroup.toList().asListContaining<CommonizedClassDescriptor>() val classes = classifiers.asListContaining<CommonizedClassDescriptor>()
// build class members: // build class members:
val classMemberScopes = CommonizedMemberScope.createArray(node.dimension) val classMemberScopes = CommonizedMemberScope.createArray(node.dimension)
@@ -127,15 +122,14 @@ internal class DeclarationsBuilderVisitor1(
error("This method should not be called in ${this::class.java}") error("This method should not be called in ${this::class.java}")
override fun visitTypeAliasNode(node: CirTypeAliasNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> { override fun visitTypeAliasNode(node: CirTypeAliasNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
val typeAliasesGroup = CommonizedGroup<ClassifierDescriptorWithTypeParameters>(node.dimension) val classifiers = CommonizedGroup<ClassifierDescriptorWithTypeParameters>(node.dimension)
node.buildDescriptors(components, typeAliasesGroup, data) node.buildDescriptors(components, classifiers, data)
val typeAliases = typeAliasesGroup.toList()
val commonClass = typeAliases[node.indexOfCommon] as? CommonizedClassDescriptor? val commonClass = classifiers[node.indexOfCommon] as? CommonizedClassDescriptor?
commonClass?.unsubstitutedMemberScope = CommonizedMemberScope() // empty member scope commonClass?.unsubstitutedMemberScope = CommonizedMemberScope() // empty member scope
commonClass?.initialize(emptyList()) // no constructors commonClass?.initialize(emptyList()) // no constructors
return typeAliases return classifiers
} }
companion object { companion object {
@@ -66,17 +66,17 @@ internal class DeclarationsBuilderVisitor2(
} }
override fun visitPropertyNode(node: CirPropertyNode, data: List<DeclarationDescriptor?>): List<PropertyDescriptor?> { override fun visitPropertyNode(node: CirPropertyNode, data: List<DeclarationDescriptor?>): List<PropertyDescriptor?> {
val propertyDescriptorsGroup = CommonizedGroup<PropertyDescriptor>(node.dimension) val propertyDescriptors = CommonizedGroup<PropertyDescriptor>(node.dimension)
node.buildDescriptors(components, propertyDescriptorsGroup, data) node.buildDescriptors(components, propertyDescriptors, data)
return propertyDescriptorsGroup.toList() return propertyDescriptors
} }
override fun visitFunctionNode(node: CirFunctionNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> { override fun visitFunctionNode(node: CirFunctionNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
val functionDescriptorsGroup = CommonizedGroup<SimpleFunctionDescriptor>(node.dimension) val functionDescriptors = CommonizedGroup<SimpleFunctionDescriptor>(node.dimension)
node.buildDescriptors(components, functionDescriptorsGroup, data) node.buildDescriptors(components, functionDescriptors, data)
return functionDescriptorsGroup.toList() return functionDescriptors
} }
override fun visitClassNode(node: CirClassNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> { override fun visitClassNode(node: CirClassNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
@@ -115,10 +115,10 @@ internal class DeclarationsBuilderVisitor2(
override fun visitClassConstructorNode(node: CirClassConstructorNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> { override fun visitClassConstructorNode(node: CirClassConstructorNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
val containingDeclarations = data.asListContaining<CommonizedClassDescriptor>() val containingDeclarations = data.asListContaining<CommonizedClassDescriptor>()
val constructorsGroup = CommonizedGroup<ClassConstructorDescriptor>(node.dimension) val constructors = CommonizedGroup<ClassConstructorDescriptor>(node.dimension)
node.buildDescriptors(components, constructorsGroup, containingDeclarations) node.buildDescriptors(components, constructors, containingDeclarations)
return constructorsGroup.toList() return constructors
} }
override fun visitTypeAliasNode(node: CirTypeAliasNode, data: List<DeclarationDescriptor?>) = override fun visitTypeAliasNode(node: CirTypeAliasNode, data: List<DeclarationDescriptor?>) =
@@ -25,14 +25,14 @@ internal fun CirClassNode.buildDescriptors(
val commonClass = commonDeclaration() val commonClass = commonDeclaration()
val markAsActual = commonClass != null && commonClass.kind != ClassKind.ENUM_ENTRY val markAsActual = commonClass != null && commonClass.kind != ClassKind.ENUM_ENTRY
targetDeclarations.toList().forEachIndexed { index, clazz -> targetDeclarations.forEachIndexed { index, clazz ->
clazz?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual) clazz?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual)
} }
commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true) commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true)
// log stats // log stats
components.statsCollector?.logStats(output.toList()) components.statsCollector?.logStats(output)
} }
internal fun CirClass.buildDescriptor( internal fun CirClass.buildDescriptor(
@@ -81,14 +81,14 @@ internal fun CirClassConstructorNode.buildDescriptors(
val commonConstructor = commonDeclaration() val commonConstructor = commonDeclaration()
val markAsActual = commonConstructor != null val markAsActual = commonConstructor != null
targetDeclarations.toList().forEachIndexed { index, constructor -> targetDeclarations.forEachIndexed { index, constructor ->
constructor?.buildDescriptor(components, output, index, containingDeclarations, isActual = markAsActual) constructor?.buildDescriptor(components, output, index, containingDeclarations, isActual = markAsActual)
} }
commonConstructor?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = true) commonConstructor?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = true)
// log stats // log stats
components.statsCollector?.logStats(output.toList()) components.statsCollector?.logStats(output)
} }
private fun CirClassConstructor.buildDescriptor( private fun CirClassConstructor.buildDescriptor(
@@ -110,7 +110,7 @@ class DeclarationsBuilderCache(private val dimension: Int) {
companion object { companion object {
private inline fun <reified K, reified V : DeclarationDescriptor> CommonizedGroupMap<K, V>.getOrFail(key: K): List<V?> = private inline fun <reified K, reified V : DeclarationDescriptor> CommonizedGroupMap<K, V>.getOrFail(key: K): List<V?> =
getOrNull(key)?.toList() ?: error("No cached ${V::class.java} with key $key found") getOrNull(key) ?: error("No cached ${V::class.java} with key $key found")
} }
} }
@@ -23,14 +23,14 @@ internal fun CirFunctionNode.buildDescriptors(
val commonFunction = commonDeclaration() val commonFunction = commonDeclaration()
val markAsExpectAndActual = commonFunction != null && commonFunction.kind != CallableMemberDescriptor.Kind.SYNTHESIZED val markAsExpectAndActual = commonFunction != null && commonFunction.kind != CallableMemberDescriptor.Kind.SYNTHESIZED
targetDeclarations.toList().forEachIndexed { index, function -> targetDeclarations.forEachIndexed { index, function ->
function?.buildDescriptor(components, output, index, containingDeclarations, isActual = markAsExpectAndActual) function?.buildDescriptor(components, output, index, containingDeclarations, isActual = markAsExpectAndActual)
} }
commonFunction?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual) commonFunction?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual)
// log stats // log stats
components.statsCollector?.logStats(output.toList()) components.statsCollector?.logStats(output)
} }
private fun CirFunction.buildDescriptor( private fun CirFunction.buildDescriptor(
@@ -15,14 +15,14 @@ internal fun CirModuleNode.buildDescriptors(
components: GlobalDeclarationsBuilderComponents, components: GlobalDeclarationsBuilderComponents,
output: CommonizedGroup<ModuleDescriptorImpl> output: CommonizedGroup<ModuleDescriptorImpl>
) { ) {
targetDeclarations.toList().forEachIndexed { index, module -> targetDeclarations.forEachIndexed { index, module ->
module?.buildDescriptor(components, output, index) module?.buildDescriptor(components, output, index)
} }
commonDeclaration()?.buildDescriptor(components, output, indexOfCommon) commonDeclaration()?.buildDescriptor(components, output, indexOfCommon)
// log stats // log stats
components.statsCollector?.logStats(output.toList()) components.statsCollector?.logStats(output)
} }
private fun CirModule.buildDescriptor( private fun CirModule.buildDescriptor(
@@ -19,7 +19,7 @@ internal fun CirPackageNode.buildDescriptors(
output: CommonizedGroup<CommonizedPackageFragmentDescriptor>, output: CommonizedGroup<CommonizedPackageFragmentDescriptor>,
modules: List<ModuleDescriptorImpl?> modules: List<ModuleDescriptorImpl?>
) { ) {
targetDeclarations.toList().forEachIndexed { index, pkg -> targetDeclarations.forEachIndexed { index, pkg ->
pkg?.buildDescriptor(components, output, index, modules) pkg?.buildDescriptor(components, output, index, modules)
} }
@@ -31,7 +31,7 @@ internal fun CirPropertyNode.buildDescriptors(
&& !isLiftedUp && !isLiftedUp
if (!isLiftedUp) { if (!isLiftedUp) {
targetDeclarations.toList().forEachIndexed { index, property -> targetDeclarations.forEachIndexed { index, property ->
property?.buildDescriptor(components, output, index, containingDeclarations, isActual = markAsExpectAndActual) property?.buildDescriptor(components, output, index, containingDeclarations, isActual = markAsExpectAndActual)
} }
} }
@@ -39,7 +39,7 @@ internal fun CirPropertyNode.buildDescriptors(
commonProperty?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual) commonProperty?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual)
// log stats // log stats
components.statsCollector?.logStats(output.toList()) components.statsCollector?.logStats(output)
} }
private fun CirProperty.buildDescriptor( private fun CirProperty.buildDescriptor(
@@ -28,7 +28,7 @@ internal fun CirTypeAliasNode.buildDescriptors(
val markAsActual = commonClassifier != null val markAsActual = commonClassifier != null
if (!isLiftedUp) { if (!isLiftedUp) {
targetDeclarations.toList().forEachIndexed { index, typeAlias -> targetDeclarations.forEachIndexed { index, typeAlias ->
typeAlias?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual) typeAlias?.buildDescriptor(components, output, index, containingDeclarations, fqName, isActual = markAsActual)
} }
} }
@@ -40,7 +40,7 @@ internal fun CirTypeAliasNode.buildDescriptors(
} }
// log stats // log stats
components.statsCollector?.logStats(output.toList()) components.statsCollector?.logStats(output)
} }
private fun CirTypeAlias.buildDescriptor( private fun CirTypeAlias.buildDescriptor(
@@ -78,7 +78,7 @@ internal class CommonizationVisitor(
if (commonClass != null) { if (commonClass != null) {
// companion object should have the same FQ name for each target class, then it could be set to common class // companion object should have the same FQ name for each target class, then it could be set to common class
val companionObjectFqName = node.targetDeclarations.toList().mapTo(HashSet()) { it!!.companion }.singleOrNull() val companionObjectFqName = node.targetDeclarations.mapTo(HashSet()) { it!!.companion }.singleOrNull()
if (companionObjectFqName != null) { if (companionObjectFqName != null) {
val companionObjectNode = root.cache.classes[companionObjectFqName] val companionObjectNode = root.cache.classes[companionObjectFqName]
?: error("Can't find companion object with FQ name $companionObjectFqName") ?: error("Can't find companion object with FQ name $companionObjectFqName")
@@ -91,7 +91,7 @@ internal class CommonizationVisitor(
// find out common (and commonized) supertypes // find out common (and commonized) supertypes
val supertypesMap = CommonizedGroupMap<String, CirType>(node.targetDeclarations.size) val supertypesMap = CommonizedGroupMap<String, CirType>(node.targetDeclarations.size)
node.targetDeclarations.toList().forEachIndexed { index, clazz -> node.targetDeclarations.forEachIndexed { index, clazz ->
for (supertype in clazz!!.supertypes) { for (supertype in clazz!!.supertypes) {
supertypesMap[supertype.fqNameWithTypeParameters][index] = supertype supertypesMap[supertype.fqNameWithTypeParameters][index] = supertype
} }
@@ -27,7 +27,7 @@ interface CirNode<T : CirDeclaration, R : CirDeclaration> {
append("fqName=").append(node.fqName).append(", ") append("fqName=").append(node.fqName).append(", ")
} }
append("target=") append("target=")
node.targetDeclarations.toList().joinTo(this) node.targetDeclarations.joinTo(this)
append(", common=") append(", common=")
append(if (node.commonDeclaration.isComputed()) node.commonDeclaration() else "<NOT COMPUTED>") append(if (node.commonDeclaration.isComputed()) node.commonDeclaration() else "<NOT COMPUTED>")
} }
@@ -149,7 +149,7 @@ internal fun <T : Any, R> commonize(
targetDeclarations: CommonizedGroup<T>, targetDeclarations: CommonizedGroup<T>,
commonizer: Commonizer<T, R> commonizer: Commonizer<T, R>
): R? { ): R? {
for (targetDeclaration in targetDeclarations.toList()) { for (targetDeclaration in targetDeclarations) {
if (targetDeclaration == null || !commonizer.commonizeWith(targetDeclaration)) if (targetDeclaration == null || !commonizer.commonizeWith(targetDeclaration))
return null return null
} }
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils
/** Fixed-size ordered collection with no extra space that represents a commonized group of same-rank elements */ /** Fixed-size ordered collection with no extra space that represents a commonized group of same-rank elements */
class CommonizedGroup<T : Any>( class CommonizedGroup<T : Any>(
val size: Int, override val size: Int,
initialize: (Int) -> T? initialize: (Int) -> T?
) { ) : AbstractList<T?>() {
constructor(elements: List<T?>) : this(elements.size, elements::get) constructor(elements: List<T?>) : this(elements.size, elements::get)
constructor(size: Int) : this(size, { null }) constructor(size: Int) : this(size, { null })
@@ -18,7 +18,7 @@ class CommonizedGroup<T : Any>(
// so let's use `Any?` instead if `T` here // so let's use `Any?` instead if `T` here
private val elements = Array<Any?>(size, initialize) private val elements = Array<Any?>(size, initialize)
operator fun get(index: Int): T? { override operator fun get(index: Int): T? {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return elements[index] as T? return elements[index] as T?
} }
@@ -29,14 +29,6 @@ class CommonizedGroup<T : Any>(
elements[index] = value elements[index] = value
} }
// TODO: consider removing this method
fun toList(): List<T?> = object : AbstractList<T?>() {
override val size
get() = this@CommonizedGroup.size
override fun get(index: Int): T? = this@CommonizedGroup[index]
}
} }
internal class CommonizedGroupMap<K, V : Any>(val size: Int) : Iterable<Map.Entry<K, CommonizedGroup<V>>> { internal class CommonizedGroupMap<K, V : Any>(val size: Int) : Iterable<Map.Entry<K, CommonizedGroup<V>>> {
@@ -484,7 +484,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
null, null,
fqName fqName
).also { ).also {
classesGroup.toList().forEachIndexed { index, clazz -> classesGroup.forEachIndexed { index, clazz ->
if (clazz != null) { if (clazz != null) {
it.targetDeclarations[index] = CirClassFactory.create(clazz) it.targetDeclarations[index] = CirClassFactory.create(clazz)
} }
@@ -499,7 +499,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
cache, cache,
fqName fqName
).also { ).also {
typeAliasesGroup.toList().forEachIndexed { index, typeAlias -> typeAliasesGroup.forEachIndexed { index, typeAlias ->
if (typeAlias != null) { if (typeAlias != null) {
it.targetDeclarations[index] = CirTypeAliasFactory.create(typeAlias) it.targetDeclarations[index] = CirTypeAliasFactory.create(typeAlias)
} }