[Commonizer] Implement first ReApproximationCirNodeTransformer

^KT-48288
This commit is contained in:
sebastian.sellmair
2021-09-15 15:58:29 +02:00
committed by Space
parent d2627f0a76
commit b68f14960a
9 changed files with 356 additions and 239 deletions
@@ -15,6 +15,8 @@ import org.jetbrains.kotlin.commonizer.mergedtree.CirNode.Companion.indexOfCommo
import org.jetbrains.kotlin.commonizer.mergedtree.CirRootNode
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer
import org.jetbrains.kotlin.commonizer.transformer.InlineTypeAliasCirNodeTransformer
import org.jetbrains.kotlin.commonizer.transformer.ReApproximationCirNodeTransformer
import org.jetbrains.kotlin.commonizer.transformer.ReApproximationCirNodeTransformer.SignatureBuildingContextProvider
import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot
import org.jetbrains.kotlin.commonizer.tree.defaultCirTreeRootDeserializer
import org.jetbrains.kotlin.commonizer.tree.mergeCirTree
@@ -63,6 +65,19 @@ internal fun commonizeTarget(
InlineTypeAliasCirNodeTransformer(parameters.storageManager, classifiers).invoke(mergedTree)
/*
ReApproximationCirNodeTransformer(
parameters.storageManager, classifiers,
SignatureBuildingContextProvider(classifiers, typeAliasInvariant = true, skipArguments = false)
).invoke(mergedTree)
*/
ReApproximationCirNodeTransformer(
parameters.storageManager, classifiers,
SignatureBuildingContextProvider(classifiers, typeAliasInvariant = true, skipArguments = true)
).invoke(mergedTree)
mergedTree.accept(CommonizationVisitor(mergedTree), Unit)
return mergedTree
@@ -0,0 +1,213 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.mergedtree
import gnu.trove.TIntHashSet
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.utils.Interner
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("")
}
companion object {
val interner = Interner<CirTypeSignature>()
}
}
internal fun SignatureBuildingContext(
memberContext: CirMemberContext, functionOrPropertyOrConstructor: CirHasTypeParameters,
classifierSignatureBuildingContext: ClassifierSignatureBuildingContext = ClassifierSignatureBuildingContext.Default,
argumentsSignatureBuildingContext: ArgumentsSignatureBuildingContext = ArgumentsSignatureBuildingContext.Default,
): SignatureBuildingContext {
return DefaultSignatureBuildingContext(
memberContext, classifierSignatureBuildingContext, argumentsSignatureBuildingContext, functionOrPropertyOrConstructor
)
}
internal sealed interface SignatureBuildingContext {
val memberContext: CirMemberContext
val classifierSignatureBuildingContext: ClassifierSignatureBuildingContext
val argumentsSignatureBuildingContext: ArgumentsSignatureBuildingContext
}
internal sealed interface ClassifierSignatureBuildingContext {
fun appendSignature(signature: CirTypeSignature, classifierId: CirEntityId)
object Default : ClassifierSignatureBuildingContext {
override fun appendSignature(signature: CirTypeSignature, classifierId: CirEntityId) = signature.add(classifierId)
}
class TypeAliasInvariant(private val commonIdResolver: CirCommonClassifierIdResolver) : ClassifierSignatureBuildingContext {
override fun appendSignature(signature: CirTypeSignature, classifierId: CirEntityId) {
return signature.add(commonIdResolver.findCommonId(classifierId) ?: classifierId)
}
}
}
internal sealed interface ArgumentsSignatureBuildingContext {
fun appendSignature(signature: CirTypeSignature, context: SignatureBuildingContext, arguments: List<CirTypeProjection>)
object Default : ArgumentsSignatureBuildingContext {
override fun appendSignature(signature: CirTypeSignature, context: SignatureBuildingContext, arguments: List<CirTypeProjection>) {
if (arguments.isEmpty()) return
signature.add(TypeSignatureElements.ArgumentsStartToken)
arguments.forEachIndexed { index, argument ->
when (argument) {
is CirRegularTypeProjection -> {
when (argument.projectionKind) {
Variance.INVARIANT -> Unit
Variance.IN_VARIANCE -> signature.add(TypeSignatureElements.InVariance)
Variance.OUT_VARIANCE -> signature.add(TypeSignatureElements.OutVariance)
}
signature.appendTypeApproximationSignature(context, argument.type)
}
is CirStarTypeProjection -> signature.add(TypeSignatureElements.StarProjection)
}
if (index != arguments.lastIndex) {
signature.add(TypeSignatureElements.ArgumentsSeparator)
}
}
signature.add(TypeSignatureElements.ArgumentsEndToken)
}
}
/**
* Won't render any type arguments
*/
object Skip : ArgumentsSignatureBuildingContext {
override fun appendSignature(
signature: CirTypeSignature, context: SignatureBuildingContext, arguments: List<CirTypeProjection>
) = Unit
}
}
private enum class TypeSignatureElements(val stringRepresentation: String) {
ArgumentsStartToken("<"),
ArgumentsEndToken(">"),
ArgumentsSeparator(", "),
NullableToken("?"),
UpperBoundsStartToken(" : ["),
UpperBoundsEndToken("]"),
InVariance("in "),
OutVariance("out "),
StarProjection("*"),
FlexibleTypeSeparator("..");
override fun toString(): String {
return stringRepresentation
}
}
internal fun buildApproximationSignature(context: SignatureBuildingContext, type: CirType): CirTypeSignature {
val signature = CirTypeSignature()
signature.appendTypeApproximationSignature(context, type)
return CirTypeSignature.interner.intern(signature)
}
internal fun CirTypeSignature.appendTypeApproximationSignature(context: SignatureBuildingContext, type: CirType) {
return when (type) {
is CirFlexibleType -> appendFlexibleTypeApproximationSignature(context, type)
is CirTypeParameterType -> appendTypeParameterTypeApproximationSignature(context.forTypeParameterTypes(), type)
is CirClassOrTypeAliasType -> appendClassOrTypeAliasTypeApproximationSignature(context, type)
}
}
internal fun CirTypeSignature.appendClassOrTypeAliasTypeApproximationSignature(
context: SignatureBuildingContext, type: CirClassOrTypeAliasType
) {
context.classifierSignatureBuildingContext.appendSignature(this, type.classifierId)
context.argumentsSignatureBuildingContext.appendSignature(this, context, type.arguments)
if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken)
}
private fun CirTypeSignature.appendTypeParameterTypeApproximationSignature(
context: TypeParameterTypeSignatureBuildingContext, type: CirTypeParameterType
) {
val typeParameter = context.resolveTypeParameter(type.index)
add(typeParameter.name)
if (context.isVisitedFirstTime(type.index)) {
add(TypeSignatureElements.UpperBoundsStartToken)
typeParameter.upperBounds.forEachIndexed { index, upperBound ->
appendTypeApproximationSignature(context, upperBound)
if (index != typeParameter.upperBounds.lastIndex) add(TypeSignatureElements.ArgumentsSeparator)
}
add(TypeSignatureElements.UpperBoundsEndToken)
}
if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken)
}
private fun CirTypeSignature.appendFlexibleTypeApproximationSignature(
context: SignatureBuildingContext, type: CirFlexibleType
) {
appendTypeApproximationSignature(context, type.lowerBound)
add(TypeSignatureElements.FlexibleTypeSeparator)
appendTypeApproximationSignature(context, type.upperBound)
}
private fun SignatureBuildingContext.forTypeParameterTypes(): TypeParameterTypeSignatureBuildingContext = when (this) {
is DefaultSignatureBuildingContext -> TypeParameterTypeSignatureBuildingContext(
memberContext, classifierSignatureBuildingContext, argumentsSignatureBuildingContext, functionOrPropertyOrConstructor
)
is TypeParameterTypeSignatureBuildingContext -> this
}
private class DefaultSignatureBuildingContext(
override val memberContext: CirMemberContext,
override val classifierSignatureBuildingContext: ClassifierSignatureBuildingContext,
override val argumentsSignatureBuildingContext: ArgumentsSignatureBuildingContext,
val functionOrPropertyOrConstructor: CirHasTypeParameters
) : SignatureBuildingContext
private class TypeParameterTypeSignatureBuildingContext(
override val memberContext: CirMemberContext,
override val classifierSignatureBuildingContext: ClassifierSignatureBuildingContext,
override val argumentsSignatureBuildingContext: ArgumentsSignatureBuildingContext,
private val functionOrPropertyOrConstructor: CirHasTypeParameters
) : SignatureBuildingContext {
private val alreadyVisitedParameterTypeIndices = TIntHashSet()
fun isVisitedFirstTime(typeParameterIndex: Int): Boolean {
return alreadyVisitedParameterTypeIndices.add(typeParameterIndex)
}
fun resolveTypeParameter(index: Int): CirTypeParameter {
var indexOffset = 0
memberContext.classes.forEach { clazz ->
val indexInClass = index - indexOffset
if (indexInClass >= 0 && indexInClass <= clazz.typeParameters.lastIndex) {
return clazz.typeParameters[indexInClass]
}
indexOffset += clazz.typeParameters.size
}
return functionOrPropertyOrConstructor.typeParameters[index - indexOffset]
}
}
@@ -1,45 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.mergedtree
import org.jetbrains.kotlin.commonizer.cir.CirFunction
import org.jetbrains.kotlin.commonizer.cir.CirProperty
import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.cir.CirValueParameter.Companion.copyInterned
interface CirTypeSubstitutor {
fun substitute(targetIndex: Int, type: CirType): CirType
}
fun CirTypeSubstitutor.substitute(index: Int, property: CirProperty): CirProperty {
val newReturnType = substitute(index, property.returnType)
return if (newReturnType != property.returnType) property.copy(returnType = newReturnType) else property
}
fun CirTypeSubstitutor.substitute(index: Int, function: CirFunction): CirFunction {
val newExtensionReceiverType = function.extensionReceiver?.type?.let { substitute(index, it) }
val newExtensionReceiver = if (newExtensionReceiverType != function.extensionReceiver?.type)
function.extensionReceiver?.copy(type = checkNotNull(newExtensionReceiverType))
else function.extensionReceiver
val newValueParameters = function.valueParameters.map { valueParameter ->
val newReturnType = substitute(index, valueParameter.returnType)
if (newReturnType != valueParameter.returnType) valueParameter.copyInterned(returnType = newReturnType) else valueParameter
}
val newReturnType = substitute(index, function.returnType)
return if (
newExtensionReceiver != function.extensionReceiver ||
newValueParameters != function.valueParameters ||
newReturnType != function.returnType
) function.copy(
extensionReceiver = newExtensionReceiver,
valueParameters = newValueParameters,
returnType = newReturnType
) else function
}
@@ -7,38 +7,11 @@
package org.jetbrains.kotlin.commonizer.mergedtree
import gnu.trove.TIntHashSet
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.utils.Interner
import org.jetbrains.kotlin.commonizer.utils.appendHashCode
import org.jetbrains.kotlin.commonizer.utils.hashCode
import org.jetbrains.kotlin.commonizer.utils.isObjCInteropCallableAnnotation
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
@@ -48,14 +21,13 @@ data class PropertyApproximationKey(
) {
companion object {
internal fun create(
context: CirMemberContext,
commonClassifierIdResolver: CirCommonClassifierIdResolver,
property: CirProperty
property: CirProperty,
signatureBuildingContext: SignatureBuildingContext
): PropertyApproximationKey {
return PropertyApproximationKey(
name = property.name,
extensionReceiverParameterType = property.extensionReceiver?.let {
buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, property), it.type)
buildApproximationSignature(signatureBuildingContext, it.type)
}
)
}
@@ -71,15 +43,14 @@ data class FunctionApproximationKey(
companion object {
internal fun create(
context: CirMemberContext,
commonClassifierIdResolver: CirCommonClassifierIdResolver,
function: CirFunction
function: CirFunction,
signatureBuildingContext: SignatureBuildingContext
): FunctionApproximationKey {
return FunctionApproximationKey(
name = function.name,
valueParametersTypes = valueParameterTypes(context, commonClassifierIdResolver, function),
valueParametersTypes = valueParameterTypes(function, signatureBuildingContext),
extensionReceiverParameterType = function.extensionReceiver?.let {
buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, function), it.type)
buildApproximationSignature(signatureBuildingContext, it.type)
},
objCFunctionApproximation = objCFunctionApproximation(function)
)
@@ -102,7 +73,6 @@ data class FunctionApproximationKey(
.appendHashCode(objCFunctionApproximation)
}
private val typeSignatureInterner = Interner<CirTypeSignature>()
data class ConstructorApproximationKey(
val valueParametersTypes: Array<CirTypeSignature>,
@@ -111,10 +81,10 @@ data class ConstructorApproximationKey(
companion object {
internal fun create(
context: CirMemberContext, commonClassifierIdResolver: CirCommonClassifierIdResolver, constructor: CirClassConstructor
constructor: CirClassConstructor, signatureBuildingContext: SignatureBuildingContext
): ConstructorApproximationKey {
return ConstructorApproximationKey(
valueParametersTypes = valueParameterTypes(context, commonClassifierIdResolver, constructor),
valueParametersTypes = valueParameterTypes(constructor, signatureBuildingContext),
objCFunctionApproximation = objCFunctionApproximation(constructor)
)
}
@@ -140,150 +110,13 @@ private fun <T> objCFunctionApproximation(value: T): ObjCFunctionApproximation
}
private fun <T> valueParameterTypes(
context: CirMemberContext,
commonClassifierIdResolver: CirCommonClassifierIdResolver,
callable: T
callable: T,
signatureBuildingContext: SignatureBuildingContext,
): Array<CirTypeSignature>
where T : CirHasTypeParameters, T : CirCallableMemberWithParameters, T : CirMaybeCallableMemberOfClass {
if (callable.valueParameters.isEmpty()) return emptyArray()
return Array(callable.valueParameters.size) { index ->
val parameter = callable.valueParameters[index]
buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, callable), parameter.returnType)
}
}
private enum class TypeSignatureElements(val stringRepresentation: String) {
ArgumentsStartToken("<"),
ArgumentsEndToken(">"),
ArgumentsSeparator(", "),
NullableToken("?"),
UpperBoundsStartToken(" : ["),
UpperBoundsEndToken("]"),
InVariance("in "),
OutVariance("out "),
StarProjection("*"),
FlexibleTypeSeparator("..");
override fun toString(): String {
return stringRepresentation
}
}
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) {
is CirFlexibleType -> appendFlexibleTypeApproximationSignature(context, type)
is CirTypeParameterType -> appendTypeParameterTypeApproximationSignature(context.forTypeParameterTypes(), type)
is CirClassOrTypeAliasType -> appendClassOrTypeAliasTypeApproximationSignature(context, type)
}
}
internal fun CirTypeSignature.appendClassOrTypeAliasTypeApproximationSignature(
context: SignatureBuildingContext, type: CirClassOrTypeAliasType
) {
add(context.commonClassifierIdResolver.findCommonId(type.classifierId) ?: type.classifierId)
if (type.arguments.isNotEmpty()) {
add(TypeSignatureElements.ArgumentsStartToken)
type.arguments.forEachIndexed { index, argument ->
when (argument) {
is CirRegularTypeProjection -> {
when (argument.projectionKind) {
Variance.INVARIANT -> Unit
Variance.IN_VARIANCE -> add(TypeSignatureElements.InVariance)
Variance.OUT_VARIANCE -> add(TypeSignatureElements.OutVariance)
}
appendTypeApproximationSignature(context, argument.type)
}
is CirStarTypeProjection -> add(TypeSignatureElements.StarProjection)
}
if (index != type.arguments.lastIndex) {
add(TypeSignatureElements.ArgumentsSeparator)
}
}
add(TypeSignatureElements.ArgumentsEndToken)
}
if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken)
}
private fun CirTypeSignature.appendTypeParameterTypeApproximationSignature(
context: TypeParameterTypeSignatureBuildingContext, type: CirTypeParameterType
) {
val typeParameter = context.resolveTypeParameter(type.index)
add(typeParameter.name)
if (context.isVisitedFirstTime(type.index)) {
add(TypeSignatureElements.UpperBoundsStartToken)
typeParameter.upperBounds.forEachIndexed { index, upperBound ->
appendTypeApproximationSignature(context, upperBound)
if (index != typeParameter.upperBounds.lastIndex) add(TypeSignatureElements.ArgumentsSeparator)
}
add(TypeSignatureElements.UpperBoundsEndToken)
}
if (type.isMarkedNullable) add(TypeSignatureElements.NullableToken)
}
private fun CirTypeSignature.appendFlexibleTypeApproximationSignature(
context: SignatureBuildingContext, type: CirFlexibleType
) {
appendTypeApproximationSignature(context, type.lowerBound)
add(TypeSignatureElements.FlexibleTypeSeparator)
appendTypeApproximationSignature(context, type.upperBound)
}
internal sealed interface SignatureBuildingContext {
val commonClassifierIdResolver: CirCommonClassifierIdResolver
companion object {
fun create(
memberContext: CirMemberContext,
commonClassifierIdResolver: CirCommonClassifierIdResolver,
functionOrPropertyOrConstructor: CirHasTypeParameters
): SignatureBuildingContext {
return DefaultSignatureBuildingContext(memberContext, commonClassifierIdResolver, functionOrPropertyOrConstructor)
}
}
}
private fun SignatureBuildingContext.forTypeParameterTypes(): TypeParameterTypeSignatureBuildingContext = when (this) {
is DefaultSignatureBuildingContext -> TypeParameterTypeSignatureBuildingContext(
memberContext, commonClassifierIdResolver, functionOrPropertyOrConstructor
)
is TypeParameterTypeSignatureBuildingContext -> this
}
private class DefaultSignatureBuildingContext(
val memberContext: CirMemberContext,
override val commonClassifierIdResolver: CirCommonClassifierIdResolver,
val functionOrPropertyOrConstructor: CirHasTypeParameters
) : SignatureBuildingContext
private class TypeParameterTypeSignatureBuildingContext(
private val memberContext: CirMemberContext,
override val commonClassifierIdResolver: CirCommonClassifierIdResolver,
private val functionOrPropertyOrConstructor: CirHasTypeParameters
) : SignatureBuildingContext {
private val alreadyVisitedParameterTypeIndices = TIntHashSet()
fun isVisitedFirstTime(typeParameterIndex: Int): Boolean {
return alreadyVisitedParameterTypeIndices.add(typeParameterIndex)
}
fun resolveTypeParameter(index: Int): CirTypeParameter {
var indexOffset = 0
memberContext.classes.forEach { clazz ->
val indexInClass = index - indexOffset
if (indexInClass >= 0 && indexInClass <= clazz.typeParameters.lastIndex) {
return clazz.typeParameters[indexInClass]
}
indexOffset += clazz.typeParameters.size
}
return functionOrPropertyOrConstructor.typeParameters[index - indexOffset]
buildApproximationSignature(signatureBuildingContext, parameter.returnType)
}
}
@@ -0,0 +1,103 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.transformer
import org.jetbrains.kotlin.commonizer.cir.CirHasTypeParameters
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.ParentNode
import org.jetbrains.kotlin.commonizer.mergedtree.ClassifierSignatureBuildingContext.TypeAliasInvariant
import org.jetbrains.kotlin.commonizer.utils.fastForEach
import org.jetbrains.kotlin.storage.StorageManager
internal class ReApproximationCirNodeTransformer(
private val storageManager: StorageManager,
private val classifiers: CirKnownClassifiers,
private val signatureBuildingContextProvider: SignatureBuildingContextProvider
) : CirNodeTransformer {
internal class SignatureBuildingContextProvider(
private val classifiers: CirKnownClassifiers,
private val typeAliasInvariant: Boolean,
private val skipArguments: Boolean
) {
operator fun invoke(member: CirMemberContext, functionOrPropertyOrConstructor: CirHasTypeParameters): SignatureBuildingContext {
return SignatureBuildingContext(
memberContext = member, functionOrPropertyOrConstructor = functionOrPropertyOrConstructor,
classifierSignatureBuildingContext = if (typeAliasInvariant) TypeAliasInvariant(classifiers.commonClassifierIdResolver)
else ClassifierSignatureBuildingContext.Default,
argumentsSignatureBuildingContext = if (skipArguments) ArgumentsSignatureBuildingContext.Skip
else ArgumentsSignatureBuildingContext.Default
)
}
}
override fun invoke(root: CirRootNode) {
for (index in 0 until root.targetDeclarations.size) {
root.modules.forEach { (_, module) -> this(module, index) }
}
}
private operator fun invoke(module: CirModuleNode, index: Int) {
module.packages.forEach { (_, pkg) -> this(pkg, index) }
}
private operator fun invoke(pkg: CirPackageNode, index: Int) {
pkg.functions.values.toTypedArray().fastForEach { function -> this(pkg, function, index, CirMemberContext.empty) }
pkg.properties.values.toTypedArray().fastForEach { property -> this(pkg, property, index, CirMemberContext.empty) }
pkg.classes.values.toTypedArray().fastForEach { clazz -> this(clazz, index, CirMemberContext.empty) }
}
private operator fun invoke(clazz: CirClassNode, index: Int, context: CirMemberContext) {
val contextWithClass = context.withContextOf(clazz.targetDeclarations[index] ?: return)
clazz.functions.values.toTypedArray().fastForEach { function -> this(clazz, function, index, contextWithClass) }
clazz.properties.values.toTypedArray().fastForEach { property -> this(clazz, property, index, contextWithClass) }
clazz.constructors.values.toTypedArray().fastForEach { constructor -> this(clazz, constructor, index, contextWithClass) }
clazz.classes.values.toTypedArray().fastForEach { innerClass -> this(innerClass, index, contextWithClass) }
}
private operator fun invoke(parent: CirNodeWithMembers<*, *>, function: CirFunctionNode, index: Int, context: CirMemberContext) {
/* Only perform re-approximation to nodes that are not 'complete' */
if (function.targetDeclarations.none { it == null }) return
val functionAtIndex = function.targetDeclarations[index] ?: return
val approximationKey = FunctionApproximationKey.create(functionAtIndex, signatureBuildingContextProvider(context, functionAtIndex))
val newNode = parent.functions.getOrPut(approximationKey) {
buildFunctionNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent))
}
newNode.targetDeclarations.setIfAbsent(index, functionAtIndex)
}
private operator fun invoke(parent: CirNodeWithMembers<*, *>, property: CirPropertyNode, index: Int, context: CirMemberContext) {
/* Only perform re-approximation to nodes that are not 'complete' */
if (property.targetDeclarations.none { it == null }) return
val propertyAtIndex = property.targetDeclarations[index] ?: return
val approximationKey = PropertyApproximationKey.create(propertyAtIndex, signatureBuildingContextProvider(context, propertyAtIndex))
val newNode = parent.properties.getOrPut(approximationKey) {
buildPropertyNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent))
}
newNode.targetDeclarations.setIfAbsent(index, propertyAtIndex)
}
private operator fun invoke(
parent: CirClassNode, constructor: CirClassConstructorNode, index: Int, context: CirMemberContext
) {
/* Only perform re-approximation to nodes that are not 'complete' */
if (constructor.targetDeclarations.none { it == null }) return
val constructorAtIndex = constructor.targetDeclarations[index] ?: return
val approximationKey =
ConstructorApproximationKey.create(constructorAtIndex, signatureBuildingContextProvider(context, constructorAtIndex))
val newNode = parent.constructors.getOrPut(approximationKey) {
buildClassConstructorNode(storageManager, parent.targetDeclarations.size, classifiers, ParentNode(parent))
}
newNode.targetDeclarations.setIfAbsent(index, constructorAtIndex)
}
}
@@ -82,33 +82,36 @@ internal fun CirNodeWithMembers<*, *>.buildFunction(
context: TargetBuildingContext, function: CirFunction, parent: CirNode<*, *>? = null
) {
val functionNode = functions.getOrPut(
FunctionApproximationKey.create(context.memberContext, context.classifiers.commonClassifierIdResolver, function)
FunctionApproximationKey.create(function, SignatureBuildingContext(context.memberContext, function))
) {
buildFunctionNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent))
}
functionNode.targetDeclarations[context.targetIndex] = function
/* Multiple type substitutions could in result in the same commonization result */
functionNode.targetDeclarations.setIfAbsent(context.targetIndex, function)
}
internal fun CirNodeWithMembers<*, *>.buildProperty(
context: TargetBuildingContext, property: CirProperty, parent: CirNode<*, *>? = null
) {
val propertyNode = properties.getOrPut(
PropertyApproximationKey.create(context.memberContext, context.classifiers.commonClassifierIdResolver, property)
PropertyApproximationKey.create(property, SignatureBuildingContext(context.memberContext, property))
) {
buildPropertyNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent))
}
propertyNode.targetDeclarations[context.targetIndex] = property
/* Multiple type substitutions could in result in the same commonization result */
propertyNode.targetDeclarations.setIfAbsent(context.targetIndex, property)
}
internal fun CirClassNode.buildConstructor(
context: TargetBuildingContext, constructor: CirClassConstructor, parent: CirNode<*, *>
) {
val constructorNode = constructors.getOrPut(
ConstructorApproximationKey.create(context.memberContext, context.classifiers.commonClassifierIdResolver, constructor)
ConstructorApproximationKey.create(constructor, SignatureBuildingContext(context.memberContext, constructor))
) {
buildClassConstructorNode(context.storageManager, context.targets, context.classifiers, ParentNode(parent))
}
constructorNode.targetDeclarations[context.targetIndex] = constructor
/* Multiple type substitutions could in result in the same commonization result */
constructorNode.targetDeclarations.setIfAbsent(context.targetIndex, constructor)
}
internal fun CirPackageNode.buildTypeAlias(context: TargetBuildingContext, treeTypeAlias: CirTreeTypeAlias) {
@@ -32,8 +32,7 @@ class CommonizedGroup<T : Any>(
elements[index] = value
}
internal fun setAllowingOverride(index: Int, value: T?) {
elements[index] = value
fun setIfAbsent(index: Int, value: T?) {
if (this[index] == null) set(index, value)
}
}
@@ -371,7 +371,7 @@ class TypeCommonizerTest : AbstractInlineSourcesCommonizationTest() {
}
)
assertEquals(
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") }, commonizer(
mockClassType("kotlin/sequences/SequenceScope"), commonizer(
listOf(
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
@@ -110,11 +110,7 @@ class ParameterizedTypesCommonizationTest : AbstractInlineSourcesCommonizationTe
typealias TA2<R> = TA1<String, R>
typealias TA3 = TA2<Int>
/*
Desirable solution below!
Test ensures that no wrong commonization is emitted for now.
*/
//expect fun x1(x: TA1<String, Int>)
expect fun x1(x: TA1<String, Int>)
""".trimIndent()
)
}