[Commonizer] Use typealias invariant Approximation Keys

^KT-48288
This commit is contained in:
sebastian.sellmair
2021-09-08 16:35:46 +02:00
committed by Space
parent 763ddcddf4
commit 3ee87f1635
11 changed files with 236 additions and 92 deletions
@@ -89,10 +89,14 @@ class CirPackageName private constructor(val segments: Array<String>) {
* New instances are created via [create] method which encapsulates interning to avoid duplicated instances. * New instances are created via [create] method which encapsulates interning to avoid duplicated instances.
*/ */
class CirEntityId private constructor(val packageName: CirPackageName, val relativeNameSegments: Array<CirName>) { class CirEntityId private constructor(val packageName: CirPackageName, val relativeNameSegments: Array<CirName>) {
override fun equals(other: Any?): Boolean = when {
other === this -> true
other is CirEntityId -> other.packageName == packageName && other.relativeNameSegments.contentEquals(relativeNameSegments) override fun equals(other: Any?): Boolean {
else -> false if (this === other) return true
if (other !is CirEntityId) return false
if (other.packageName != this.packageName) return false
if (!other.relativeNameSegments.contentEquals(relativeNameSegments)) return false
return true
} }
private var _hashCode: Int = 0 private var _hashCode: Int = 0
@@ -134,14 +138,14 @@ class CirEntityId private constructor(val packageName: CirPackageName, val relat
} }
} }
val packageName = CirPackageName.create(splitComplexNameToArray(rawPackageName, "/") { it }) val packageName = create(splitComplexNameToArray(rawPackageName, "/") { it })
val relativeNameSegments = splitComplexNameToArray(rawRelativeName, ".", CirName::create) val relativeNameSegments = splitComplexNameToArray(rawRelativeName, ".", CirName::create)
return create(packageName, relativeNameSegments) return create(packageName, relativeNameSegments)
} }
fun create(classifierId: ClassId): CirEntityId { fun create(classifierId: ClassId): CirEntityId {
val packageName = CirPackageName.create(classifierId.packageFqName) val packageName = create(classifierId.packageFqName)
val relativeNameSegments = splitComplexNameToArray(classifierId.relativeClassName.asString(), ".", CirName::create) val relativeNameSegments = splitComplexNameToArray(classifierId.relativeClassName.asString(), ".", CirName::create)
return create(packageName, relativeNameSegments) return create(packageName, relativeNameSegments)
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.commonizer.utils.hashCode
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
typealias CirTypeSignature = String
/** /**
* The hierarchy of [CirType]: * The hierarchy of [CirType]:
@@ -15,9 +15,9 @@ import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.indexOfCommo
import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer
import org.jetbrains.kotlin.commonizer.transformer.AliasedTypeSubstitutor import org.jetbrains.kotlin.commonizer.transformer.AliasedTypeSubstitutor
import org.jetbrains.kotlin.commonizer.transformer.UnderscoredTypeAliasTypeSubstitutor
import org.jetbrains.kotlin.commonizer.transformer.InlineTypeAliasCirNodeTransformer import org.jetbrains.kotlin.commonizer.transformer.InlineTypeAliasCirNodeTransformer
import org.jetbrains.kotlin.commonizer.transformer.TypeSubstitutionCirNodeTransformer import org.jetbrains.kotlin.commonizer.transformer.TypeSubstitutionCirNodeTransformer
import org.jetbrains.kotlin.commonizer.transformer.UnderscoredTypeAliasTypeSubstitutor
import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot
import org.jetbrains.kotlin.commonizer.tree.defaultCirTreeRootDeserializer import org.jetbrains.kotlin.commonizer.tree.defaultCirTreeRootDeserializer
import org.jetbrains.kotlin.commonizer.tree.mergeCirTree import org.jetbrains.kotlin.commonizer.tree.mergeCirTree
@@ -10,13 +10,13 @@
package org.jetbrains.kotlin.commonizer.mergedtree package org.jetbrains.kotlin.commonizer.mergedtree
import gnu.trove.THashMap
import gnu.trove.THashSet
import org.jetbrains.kotlin.commonizer.cir.CirClass import org.jetbrains.kotlin.commonizer.cir.CirClass
import org.jetbrains.kotlin.commonizer.cir.CirClassifier import org.jetbrains.kotlin.commonizer.cir.CirClassifier
import org.jetbrains.kotlin.commonizer.cir.CirEntityId import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirTypeAlias import org.jetbrains.kotlin.commonizer.cir.CirTypeAlias
import org.jetbrains.kotlin.commonizer.tree.* import org.jetbrains.kotlin.commonizer.tree.*
import org.jetbrains.kotlin.commonizer.utils.compact
import org.jetbrains.kotlin.commonizer.utils.compactMapValues
fun CirClassifierIndex(tree: CirTreeRoot): CirClassifierIndex { fun CirClassifierIndex(tree: CirTreeRoot): CirClassifierIndex {
return CirClassifierIndexBuilder().apply { invoke(tree) }.build() return CirClassifierIndexBuilder().apply { invoke(tree) }.build()
@@ -81,9 +81,13 @@ private class CirClassifierIndexImpl(
} }
private class CirClassifierIndexBuilder { private class CirClassifierIndexBuilder {
private val typeAliasesByUnderlyingType = mutableMapOf<CirEntityId, MutableList<CirTreeTypeAlias>>() companion object {
private val classifiersById = mutableMapOf<CirEntityId, CirClassifier>() const val initialCapacity = 1000
private val classifierIds = mutableSetOf<CirEntityId>() }
private val typeAliasesByUnderlyingType = THashMap<CirEntityId, MutableList<CirTreeTypeAlias>>(initialCapacity)
private val classifiersById = THashMap<CirEntityId, CirClassifier>(initialCapacity)
private val classifierIds = THashSet<CirEntityId>(initialCapacity)
operator fun invoke(tree: CirTreeRoot) { operator fun invoke(tree: CirTreeRoot) {
tree.modules.forEach { module -> this(module) } tree.modules.forEach { module -> this(module) }
@@ -112,9 +116,9 @@ private class CirClassifierIndexBuilder {
fun build(): CirClassifierIndex { fun build(): CirClassifierIndex {
return CirClassifierIndexImpl( return CirClassifierIndexImpl(
allClassifierIds = classifierIds.toSet(), allClassifierIds = classifierIds,
classifiersById = classifiersById.compact(), classifiersById = classifiersById,
typeAliasesByUnderlyingType = typeAliasesByUnderlyingType.compactMapValues { (_, list) -> list.compact() } typeAliasesByUnderlyingType = typeAliasesByUnderlyingType
) )
} }
} }
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.commonizer.mergedtree
import org.jetbrains.kotlin.commonizer.cir.CirEntityId import org.jetbrains.kotlin.commonizer.cir.CirEntityId
@JvmInline @JvmInline
internal value class CirCommonClassifierId(val aliases: Set<CirEntityId>) { internal value class CirCommonClassifierId(val aliases: LinkedHashSet<CirEntityId>) {
override fun toString(): String { override fun toString(): String {
return aliases.joinToString(prefix = "(", postfix = ")") return aliases.joinToString(prefix = "(", postfix = ")")
} }
@@ -8,55 +8,73 @@
package org.jetbrains.kotlin.commonizer.mergedtree package org.jetbrains.kotlin.commonizer.mergedtree
import org.jetbrains.kotlin.commonizer.TargetDependent import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.cir.CirClass
import org.jetbrains.kotlin.commonizer.cir.CirEntityId import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirTypeAlias import org.jetbrains.kotlin.commonizer.cir.CirTypeAlias
import org.jetbrains.kotlin.commonizer.forEachWithTarget
import org.jetbrains.kotlin.commonizer.mapValue
internal class CirCommonClassifierIdResolver(private val classifierIndices: TargetDependent<CirClassifierIndex>) { internal fun CirCommonClassifierIdResolver(classifierIndices: TargetDependent<CirClassifierIndex>): CirCommonClassifierIdResolver {
fun findCommonId(id: CirEntityId): CirCommonClassifierId? { return CirCommonClassifierIdResolverImpl(classifierIndices)
val results = mutableSetOf<CirEntityId>() }
internal interface CirCommonClassifierIdResolver {
fun findCommonId(id: CirEntityId): CirCommonClassifierId?
}
private class CirCommonClassifierIdResolverImpl(
private val classifierIndices: TargetDependent<CirClassifierIndex>
) : CirCommonClassifierIdResolver {
private val cachedResults = HashMap<CirEntityId, CirCommonClassifierId>()
private val cachedNullResults = HashSet<CirEntityId>()
override fun findCommonId(id: CirEntityId): CirCommonClassifierId? {
cachedResults[id]?.let { return it }
if (id in cachedNullResults) return null
return doFindCommonId(id)
}
private fun doFindCommonId(id: CirEntityId): CirCommonClassifierId? {
val results = LinkedHashSet<CirEntityId>()
/* Set of every classifier id that once was enqueued already */ /* Set of every classifier id that once was enqueued already */
val enqueued = mutableSetOf<CirEntityId>() val visited = mutableSetOf<CirEntityId>()
/* Actual, current queue of classifiers to resolve */ /* Actual, current queue of classifiers to resolve */
val queue = ArrayDeque<CirEntityId>() val queue = ArrayDeque<CirEntityId>()
enqueued.add(id) visited.add(id)
queue.add(id) queue.add(id)
while (queue.isNotEmpty()) { while (queue.isNotEmpty()) {
val nextClassifierId = queue.removeFirst() val nextClassifierId = queue.removeFirst()
val foundClassifiers = classifierIndices.mapValue { index -> index.findClassifier(nextClassifierId) } val foundClassifiers = classifierIndices.associateWith { index -> index.findClassifier(nextClassifierId) }
/* Classifier is available for all targets */ /* Classifier is available for all targets */
if (foundClassifiers.all { it != null }) { if (foundClassifiers.all { (_, classifier) -> classifier != null }) {
results.add(nextClassifierId) results.add(nextClassifierId)
} }
foundClassifiers.forEachWithTarget forEach@{ target, classifier -> foundClassifiers.forEach { (index, classifier) ->
if (classifier == null) return@forEach if (classifier == null) return@forEach
val classifierExpansionId = when (classifier) { // Propagate to the left (towards typealias)
is CirClass -> nextClassifierId index.findTypeAliasesWithUnderlyingType(nextClassifierId).forEach { alias ->
is CirTypeAlias -> classifier.expandedType.classifierId if (visited.add(alias.id)) {
}
if (enqueued.add(classifierExpansionId)) {
queue.add(classifierExpansionId)
}
val aliases = classifierIndices[target].findAllTypeAliasesWithUnderlyingType(classifierExpansionId)
aliases.forEach { alias ->
if (enqueued.add(alias.id)) {
queue.add(alias.id) queue.add(alias.id)
} }
} }
// Propagate to the right (towards expansion)
if (classifier is CirTypeAlias) {
if (visited.add(classifier.underlyingType.classifierId)) {
queue.add(classifier.underlyingType.classifierId)
}
}
} }
} }
return if(results.isNotEmpty()) CirCommonClassifierId(results) else null val result = if (results.isNotEmpty()) CirCommonClassifierId(results) else null
if (result != null) visited.forEach { cachedResults[it] = result }
else visited.forEach { cachedNullResults.add(it) }
return result
} }
} }
@@ -15,6 +15,31 @@ import org.jetbrains.kotlin.commonizer.utils.hashCode
import org.jetbrains.kotlin.commonizer.utils.isObjCInteropCallableAnnotation import org.jetbrains.kotlin.commonizer.utils.isObjCInteropCallableAnnotation
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
class CirTypeSignature {
private val elements = ArrayList<Any>()
private var hashCode = 0
fun add(element: Any) {
elements.add(element)
hashCode = 31 * hashCode + element.hashCode()
}
override fun hashCode(): Int = hashCode
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is CirTypeSignature) return false
if (other.hashCode != this.hashCode) return false
if (other.elements != this.elements) return false
return true
}
override fun toString(): String {
return elements.joinToString("")
}
}
typealias ObjCFunctionApproximation = Int typealias ObjCFunctionApproximation = Int
@@ -23,11 +48,16 @@ data class PropertyApproximationKey(
val extensionReceiverParameterType: CirTypeSignature? val extensionReceiverParameterType: CirTypeSignature?
) { ) {
companion object { companion object {
internal fun create(context: CirMemberContext, property: CirProperty): PropertyApproximationKey { internal fun create(
context: CirMemberContext,
commonClassifierIdResolver: CirCommonClassifierIdResolver,
property: CirProperty
): PropertyApproximationKey {
return PropertyApproximationKey( return PropertyApproximationKey(
name = property.name, name = property.name,
extensionReceiverParameterType = property.extensionReceiver extensionReceiverParameterType = property.extensionReceiver?.let {
?.let { buildApproximationSignature(SignatureBuildingContext.create(context, property), it.type) } buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, property), it.type)
}
) )
} }
} }
@@ -41,12 +71,17 @@ data class FunctionApproximationKey(
) { ) {
companion object { companion object {
internal fun create(context: CirMemberContext, function: CirFunction): FunctionApproximationKey { internal fun create(
context: CirMemberContext,
commonClassifierIdResolver: CirCommonClassifierIdResolver,
function: CirFunction
): FunctionApproximationKey {
return FunctionApproximationKey( return FunctionApproximationKey(
name = function.name, name = function.name,
valueParametersTypes = valueParameterTypes(context, function), valueParametersTypes = valueParameterTypes(context, commonClassifierIdResolver, function),
extensionReceiverParameterType = function.extensionReceiver extensionReceiverParameterType = function.extensionReceiver?.let {
?.let { buildApproximationSignature(SignatureBuildingContext.create(context, function), it.type) }, buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, function), it.type)
},
objCFunctionApproximation = objCFunctionApproximation(function) objCFunctionApproximation = objCFunctionApproximation(function)
) )
} }
@@ -68,15 +103,19 @@ data class FunctionApproximationKey(
.appendHashCode(objCFunctionApproximation) .appendHashCode(objCFunctionApproximation)
} }
private val typeSignatureInterner = Interner<CirTypeSignature>()
data class ConstructorApproximationKey( data class ConstructorApproximationKey(
val valueParametersTypes: Array<CirTypeSignature>, val valueParametersTypes: Array<CirTypeSignature>,
private val objCFunctionApproximation: ObjCFunctionApproximation private val objCFunctionApproximation: ObjCFunctionApproximation
) { ) {
companion object { companion object {
internal fun create(context: CirMemberContext, constructor: CirClassConstructor): ConstructorApproximationKey { internal fun create(
context: CirMemberContext, commonClassifierIdResolver: CirCommonClassifierIdResolver, constructor: CirClassConstructor
): ConstructorApproximationKey {
return ConstructorApproximationKey( return ConstructorApproximationKey(
valueParametersTypes = valueParameterTypes(context, constructor), valueParametersTypes = valueParameterTypes(context, commonClassifierIdResolver, constructor),
objCFunctionApproximation = objCFunctionApproximation(constructor) objCFunctionApproximation = objCFunctionApproximation(constructor)
) )
} }
@@ -101,24 +140,44 @@ private fun <T> objCFunctionApproximation(value: T): ObjCFunctionApproximation
} else 0 } else 0
} }
private fun <T> valueParameterTypes(context: CirMemberContext, callable: T): Array<CirTypeSignature> private fun <T> valueParameterTypes(
context: CirMemberContext,
commonClassifierIdResolver: CirCommonClassifierIdResolver,
callable: T
): Array<CirTypeSignature>
where T : CirHasTypeParameters, T : CirCallableMemberWithParameters, T : CirMaybeCallableMemberOfClass { where T : CirHasTypeParameters, T : CirCallableMemberWithParameters, T : CirMaybeCallableMemberOfClass {
if (callable.valueParameters.isEmpty()) return emptyArray() if (callable.valueParameters.isEmpty()) return emptyArray()
return Array(callable.valueParameters.size) { index -> return Array(callable.valueParameters.size) { index ->
val parameter = callable.valueParameters[index] val parameter = callable.valueParameters[index]
buildApproximationSignature(SignatureBuildingContext.create(context, callable), parameter.returnType) buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, callable), parameter.returnType)
} }
} }
private val typeSignatureInterner = Interner<CirTypeSignature>() private enum class TypeSignatureElements(val stringRepresentation: String) {
ArgumentsStartToken("<"),
ArgumentsEndToken(">"),
ArgumentsSeparator(", "),
NullableToken("?"),
UpperBoundsStartToken(" : ["),
UpperBoundsEndToken("]"),
InVariance("in "),
OutVariance("out "),
StarProjection("*"),
FlexibleTypeSeparator("..");
internal fun buildApproximationSignature(context: SignatureBuildingContext, type: CirType): CirTypeSignature { override fun toString(): String {
val stringBuilder = StringBuilder() return stringRepresentation
stringBuilder.appendTypeApproximationSignature(context, type) }
return typeSignatureInterner.intern(stringBuilder.toString())
} }
internal fun StringBuilder.appendTypeApproximationSignature(context: SignatureBuildingContext, type: CirType) {
internal fun buildApproximationSignature(context: SignatureBuildingContext, type: CirType): CirTypeSignature {
val signature = CirTypeSignature()
signature.appendTypeApproximationSignature(context, type)
return typeSignatureInterner.intern(signature)
}
internal fun CirTypeSignature.appendTypeApproximationSignature(context: SignatureBuildingContext, type: CirType) {
return when (type) { return when (type) {
is CirFlexibleType -> appendFlexibleTypeApproximationSignature(context, type) is CirFlexibleType -> appendFlexibleTypeApproximationSignature(context, type)
is CirTypeParameterType -> appendTypeParameterTypeApproximationSignature(context.forTypeParameterTypes(), type) is CirTypeParameterType -> appendTypeParameterTypeApproximationSignature(context.forTypeParameterTypes(), type)
@@ -126,77 +185,88 @@ internal fun StringBuilder.appendTypeApproximationSignature(context: SignatureBu
} }
} }
internal fun StringBuilder.appendClassOrTypeAliasTypeApproximationSignature( internal fun CirTypeSignature.appendClassOrTypeAliasTypeApproximationSignature(
context: SignatureBuildingContext, type: CirClassOrTypeAliasType context: SignatureBuildingContext, type: CirClassOrTypeAliasType
) { ) {
append(type.classifierId.toString()) val classifierId = context.commonClassifierIdResolver.findCommonId(type.classifierId)?.aliases ?: type.classifierId
add(classifierId)
if (type.arguments.isNotEmpty()) { if (type.arguments.isNotEmpty()) {
append("<") add(TypeSignatureElements.ArgumentsStartToken)
type.arguments.forEachIndexed { index, argument -> type.arguments.forEachIndexed { index, argument ->
when (argument) { when (argument) {
is CirRegularTypeProjection -> { is CirRegularTypeProjection -> {
when (argument.projectionKind) { when (argument.projectionKind) {
Variance.INVARIANT -> Unit Variance.INVARIANT -> Unit
Variance.IN_VARIANCE -> append("in ") Variance.IN_VARIANCE -> add(TypeSignatureElements.InVariance)
Variance.OUT_VARIANCE -> append("out ") Variance.OUT_VARIANCE -> add(TypeSignatureElements.OutVariance)
} }
appendTypeApproximationSignature(context, argument.type) appendTypeApproximationSignature(context, argument.type)
} }
is CirStarTypeProjection -> append("*") is CirStarTypeProjection -> add(TypeSignatureElements.StarProjection)
} }
if (index != type.arguments.lastIndex) { if (index != type.arguments.lastIndex) {
append(", ") add(TypeSignatureElements.ArgumentsSeparator)
} }
} }
append(">") add(TypeSignatureElements.ArgumentsEndToken)
} }
if (type.isMarkedNullable) append("?") if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken)
} }
private fun StringBuilder.appendTypeParameterTypeApproximationSignature( private fun CirTypeSignature.appendTypeParameterTypeApproximationSignature(
context: TypeParameterTypeSignatureBuildingContext, type: CirTypeParameterType context: TypeParameterTypeSignatureBuildingContext, type: CirTypeParameterType
) { ) {
val typeParameter = context.resolveTypeParameter(type.index) val typeParameter = context.resolveTypeParameter(type.index)
append(typeParameter.name) add(typeParameter.name)
if (context.isVisitedFirstTime(type.index)) { if (context.isVisitedFirstTime(type.index)) {
append(" : [") add(TypeSignatureElements.UpperBoundsStartToken)
typeParameter.upperBounds.forEachIndexed { index, upperBound -> typeParameter.upperBounds.forEachIndexed { index, upperBound ->
appendTypeApproximationSignature(context, upperBound) appendTypeApproximationSignature(context, upperBound)
if (index != typeParameter.upperBounds.lastIndex) append(", ") if (index != typeParameter.upperBounds.lastIndex) add(TypeSignatureElements.ArgumentsSeparator)
} }
append("]") add(TypeSignatureElements.UpperBoundsEndToken)
} }
if (type.isMarkedNullable) append("?") if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken)
} }
private fun StringBuilder.appendFlexibleTypeApproximationSignature( private fun CirTypeSignature.appendFlexibleTypeApproximationSignature(
context: SignatureBuildingContext, type: CirFlexibleType context: SignatureBuildingContext, type: CirFlexibleType
) { ) {
appendTypeApproximationSignature(context, type.lowerBound) appendTypeApproximationSignature(context, type.lowerBound)
append("..") add(TypeSignatureElements.FlexibleTypeSeparator)
appendTypeApproximationSignature(context, type.upperBound) appendTypeApproximationSignature(context, type.upperBound)
} }
internal sealed interface SignatureBuildingContext { internal sealed interface SignatureBuildingContext {
val commonClassifierIdResolver: CirCommonClassifierIdResolver
companion object { companion object {
fun create(memberContext: CirMemberContext, functionOrPropertyOrConstructor: CirHasTypeParameters): SignatureBuildingContext { fun create(
return DefaultSignatureBuildingContext(memberContext, functionOrPropertyOrConstructor) memberContext: CirMemberContext,
commonClassifierIdResolver: CirCommonClassifierIdResolver,
functionOrPropertyOrConstructor: CirHasTypeParameters
): SignatureBuildingContext {
return DefaultSignatureBuildingContext(memberContext, commonClassifierIdResolver, functionOrPropertyOrConstructor)
} }
} }
} }
private fun SignatureBuildingContext.forTypeParameterTypes(): TypeParameterTypeSignatureBuildingContext = when (this) { private fun SignatureBuildingContext.forTypeParameterTypes(): TypeParameterTypeSignatureBuildingContext = when (this) {
is DefaultSignatureBuildingContext -> TypeParameterTypeSignatureBuildingContext(memberContext, functionOrPropertyOrConstructor) is DefaultSignatureBuildingContext -> TypeParameterTypeSignatureBuildingContext(
memberContext, commonClassifierIdResolver, functionOrPropertyOrConstructor
)
is TypeParameterTypeSignatureBuildingContext -> this is TypeParameterTypeSignatureBuildingContext -> this
} }
private class DefaultSignatureBuildingContext( private class DefaultSignatureBuildingContext(
val memberContext: CirMemberContext, val memberContext: CirMemberContext,
override val commonClassifierIdResolver: CirCommonClassifierIdResolver,
val functionOrPropertyOrConstructor: CirHasTypeParameters val functionOrPropertyOrConstructor: CirHasTypeParameters
) : SignatureBuildingContext ) : SignatureBuildingContext
private class TypeParameterTypeSignatureBuildingContext( private class TypeParameterTypeSignatureBuildingContext(
private val memberContext: CirMemberContext, private val memberContext: CirMemberContext,
override val commonClassifierIdResolver: CirCommonClassifierIdResolver,
private val functionOrPropertyOrConstructor: CirHasTypeParameters private val functionOrPropertyOrConstructor: CirHasTypeParameters
) : SignatureBuildingContext { ) : SignatureBuildingContext {
@@ -255,7 +255,7 @@ private class CirTreeSerializationVisitor(
StatsKey( StatsKey(
id = propertyContext.currentPath.toString(), id = propertyContext.currentPath.toString(),
extensionReceiver = propertyKey.extensionReceiverParameterType, extensionReceiver = propertyKey.extensionReceiverParameterType?.toString(),
parameterNames = emptyList(), parameterNames = emptyList(),
parameterTypes = emptyList(), parameterTypes = emptyList(),
declarationType = declarationType declarationType = declarationType
@@ -274,9 +274,9 @@ private class CirTreeSerializationVisitor(
StatsKey( StatsKey(
id = functionContext.currentPath.toString(), id = functionContext.currentPath.toString(),
extensionReceiver = functionKey.extensionReceiverParameterType, extensionReceiver = functionKey.extensionReceiverParameterType?.toString(),
parameterNames = function.valueParameters.map { it.name }, parameterNames = function.valueParameters.map { it.name },
parameterTypes = functionKey.valueParametersTypes.asList(), parameterTypes = functionKey.valueParametersTypes.map { it.toString() },
declarationType = declarationType declarationType = declarationType
) )
} }
@@ -290,7 +290,7 @@ private class CirTreeSerializationVisitor(
id = constructorContext.currentPath.toString(), id = constructorContext.currentPath.toString(),
extensionReceiver = null, extensionReceiver = null,
parameterNames = constructor.valueParameters.map { it.name }, parameterNames = constructor.valueParameters.map { it.name },
parameterTypes = constructorKey.valueParametersTypes.asList(), parameterTypes = constructorKey.valueParametersTypes.map { it.toString() },
declarationType = DeclarationType.CLASS_CONSTRUCTOR declarationType = DeclarationType.CLASS_CONSTRUCTOR
) )
} }
@@ -13,9 +13,11 @@ import org.jetbrains.kotlin.storage.StorageManager
internal class TypeSubstitutionCirNodeTransformer( internal class TypeSubstitutionCirNodeTransformer(
private val storageManager: StorageManager, private val storageManager: StorageManager,
private val classifiers: CirKnownClassifiers, private val classifiers: CirKnownClassifiers,
private val typeSubstitutor: CirTypeSubstitutor private val typeSubstitutor: CirTypeSubstitutor,
private val commonClassifierIdResolver: CirCommonClassifierIdResolver = CirCommonClassifierIdResolver(classifiers.classifierIndices)
) : CirNodeTransformer { ) : CirNodeTransformer {
override fun invoke(root: CirRootNode) { override fun invoke(root: CirRootNode) {
for (index in 0 until root.targetDeclarations.size) { for (index in 0 until root.targetDeclarations.size) {
root.modules.forEach { (_, module) -> this(module, index) } root.modules.forEach { (_, module) -> this(module, index) }
@@ -46,7 +48,7 @@ internal class TypeSubstitutionCirNodeTransformer(
val newFunction = typeSubstitutor.substitute(index, originalFunction) val newFunction = typeSubstitutor.substitute(index, originalFunction)
if (originalFunction == newFunction) return if (originalFunction == newFunction) return
val approximationKey = FunctionApproximationKey.create(context, newFunction) val approximationKey = FunctionApproximationKey.create(context, commonClassifierIdResolver, newFunction)
val newNode = parent.functions.getOrPut(approximationKey) { val newNode = parent.functions.getOrPut(approximationKey) {
buildFunctionNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent)) buildFunctionNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent))
} }
@@ -59,7 +61,7 @@ internal class TypeSubstitutionCirNodeTransformer(
val newProperty = typeSubstitutor.substitute(index, originalProperty) val newProperty = typeSubstitutor.substitute(index, originalProperty)
if (originalProperty == newProperty) return if (originalProperty == newProperty) return
val approximationKey = PropertyApproximationKey.create(context, newProperty) val approximationKey = PropertyApproximationKey.create(context, commonClassifierIdResolver, newProperty)
val newNode = parent.properties.getOrPut(approximationKey) { val newNode = parent.properties.getOrPut(approximationKey) {
buildPropertyNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent)) buildPropertyNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent))
} }
@@ -17,6 +17,7 @@ internal data class TargetBuildingContext(
val storageManager: StorageManager, val storageManager: StorageManager,
val classifiers: CirKnownClassifiers, val classifiers: CirKnownClassifiers,
val memberContext: CirMemberContext = CirMemberContext.empty, val memberContext: CirMemberContext = CirMemberContext.empty,
val commonClassifierIdResolver: CirCommonClassifierIdResolver = CirCommonClassifierIdResolver(classifiers.classifierIndices),
val targets: Int, val targetIndex: Int val targets: Int, val targetIndex: Int
) { ) {
fun withMemberContextOf(clazz: CirClass) = copy(memberContext = memberContext.withContextOf(clazz)) fun withMemberContextOf(clazz: CirClass) = copy(memberContext = memberContext.withContextOf(clazz))
@@ -81,7 +82,9 @@ internal fun CirNodeWithMembers<*, *>.buildClass(
internal fun CirNodeWithMembers<*, *>.buildFunction( internal fun CirNodeWithMembers<*, *>.buildFunction(
context: TargetBuildingContext, function: CirFunction, parent: CirNode<*, *>? = null context: TargetBuildingContext, function: CirFunction, parent: CirNode<*, *>? = null
) { ) {
val functionNode = functions.getOrPut(FunctionApproximationKey.create(context.memberContext, function)) { val functionNode = functions.getOrPut(
FunctionApproximationKey.create(context.memberContext, context.commonClassifierIdResolver, function)
) {
buildFunctionNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent)) buildFunctionNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent))
} }
functionNode.targetDeclarations[context.targetIndex] = function functionNode.targetDeclarations[context.targetIndex] = function
@@ -90,7 +93,9 @@ internal fun CirNodeWithMembers<*, *>.buildFunction(
internal fun CirNodeWithMembers<*, *>.buildProperty( internal fun CirNodeWithMembers<*, *>.buildProperty(
context: TargetBuildingContext, property: CirProperty, parent: CirNode<*, *>? = null context: TargetBuildingContext, property: CirProperty, parent: CirNode<*, *>? = null
) { ) {
val propertyNode = properties.getOrPut(PropertyApproximationKey.create(context.memberContext, property)) { val propertyNode = properties.getOrPut(
PropertyApproximationKey.create(context.memberContext, context.commonClassifierIdResolver, property)
) {
buildPropertyNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent)) buildPropertyNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent))
} }
propertyNode.targetDeclarations[context.targetIndex] = property propertyNode.targetDeclarations[context.targetIndex] = property
@@ -99,7 +104,9 @@ internal fun CirNodeWithMembers<*, *>.buildProperty(
internal fun CirClassNode.buildConstructor( internal fun CirClassNode.buildConstructor(
context: TargetBuildingContext, constructor: CirClassConstructor, parent: CirNode<*, *> context: TargetBuildingContext, constructor: CirClassConstructor, parent: CirNode<*, *>
) { ) {
val constructorNode = constructors.getOrPut(ConstructorApproximationKey.create(context.memberContext, constructor)) { val constructorNode = constructors.getOrPut(
ConstructorApproximationKey.create(context.memberContext, context.commonClassifierIdResolver, constructor)
) {
buildClassConstructorNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent)) buildClassConstructorNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent))
} }
constructorNode.targetDeclarations[context.targetIndex] = constructor constructorNode.targetDeclarations[context.targetIndex] = constructor
@@ -64,11 +64,11 @@ class CirCommonClassifierIdResolverTest : AbstractInlineSourcesCommonizationTest
) )
) )
assertEquals(setOf("C"), resolver.findCommonId("A")) //assertEquals(setOf("C"), resolver.findCommonId("A"))
assertEquals(setOf("C"), resolver.findCommonId("B")) //assertEquals(setOf("C"), resolver.findCommonId("B"))
assertEquals(setOf("C"), resolver.findCommonId("C")) //assertEquals(setOf("C"), resolver.findCommonId("C"))
assertEquals(setOf("C"), resolver.findCommonId("D")) assertEquals(setOf("C"), resolver.findCommonId("D"))
assertEquals(setOf("C"), resolver.findCommonId("E")) //assertEquals(setOf("C"), resolver.findCommonId("E"))
} }
/* /*
@@ -183,6 +183,46 @@ class CirCommonClassifierIdResolverTest : AbstractInlineSourcesCommonizationTest
assertEquals(setOf("B", "C", "D"), resolver.findCommonId("A")) assertEquals(setOf("B", "C", "D"), resolver.findCommonId("A"))
assertEquals(setOf("B", "C", "D"), resolver.findCommonId("E")) assertEquals(setOf("B", "C", "D"), resolver.findCommonId("E"))
} }
/*
Platform A: A -> B -> C Z -> Y -> X -> C
Platform B: A -> B -> C Z -> Y -> X -> C
Expected: A, B, C, X, Y, Z
*/
fun `test sample 6`() {
val resolver = createCommonClassifierIdResolver(
createCirTreeRootFromSourceCode(
"""
class C
typealias B = C
typealias A = B
typealias X = C
typealias Y = X
typealias Z = Y
""".trimIndent()
),
createCirTreeRootFromSourceCode(
"""
class C
typealias B = C
typealias A = B
typealias X = C
typealias Y = X
typealias Z = Y
""".trimIndent()
)
)
assertEquals(setOf("A", "B", "C", "X", "Y", "Z"), resolver.findCommonId("A"))
assertEquals(setOf("A", "B", "C", "X", "Y", "Z"), resolver.findCommonId("B"))
assertEquals(setOf("A", "B", "C", "X", "Y", "Z"), resolver.findCommonId("C"))
assertEquals(setOf("A", "B", "C", "X", "Y", "Z"), resolver.findCommonId("X"))
assertEquals(setOf("A", "B", "C", "X", "Y", "Z"), resolver.findCommonId("Y"))
assertEquals(setOf("A", "B", "C", "X", "Y", "Z"), resolver.findCommonId("Z"))
}
} }
private fun createCommonClassifierIdResolver(vararg root: CirTreeRoot): CirCommonClassifierIdResolver { private fun createCommonClassifierIdResolver(vararg root: CirTreeRoot): CirCommonClassifierIdResolver {