[Commonizer] Implement first ReApproximationCirNodeTransformer
^KT-48288
This commit is contained in:
committed by
Space
parent
d2627f0a76
commit
b68f14960a
@@ -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.mergedtree.CirRootNode
|
||||||
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer
|
import org.jetbrains.kotlin.commonizer.metadata.CirTreeSerializer
|
||||||
import org.jetbrains.kotlin.commonizer.transformer.InlineTypeAliasCirNodeTransformer
|
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.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
|
||||||
@@ -63,6 +65,19 @@ internal fun commonizeTarget(
|
|||||||
|
|
||||||
InlineTypeAliasCirNodeTransformer(parameters.storageManager, classifiers).invoke(mergedTree)
|
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)
|
mergedTree.accept(CommonizationVisitor(mergedTree), Unit)
|
||||||
|
|
||||||
return mergedTree
|
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]
|
||||||
|
}
|
||||||
|
}
|
||||||
-45
@@ -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
|
|
||||||
}
|
|
||||||
+12
-179
@@ -7,38 +7,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.commonizer.mergedtree
|
package org.jetbrains.kotlin.commonizer.mergedtree
|
||||||
|
|
||||||
import gnu.trove.TIntHashSet
|
|
||||||
import org.jetbrains.kotlin.commonizer.cir.*
|
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.appendHashCode
|
||||||
import org.jetbrains.kotlin.commonizer.utils.hashCode
|
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
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -48,14 +21,13 @@ data class PropertyApproximationKey(
|
|||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
internal fun create(
|
internal fun create(
|
||||||
context: CirMemberContext,
|
property: CirProperty,
|
||||||
commonClassifierIdResolver: CirCommonClassifierIdResolver,
|
signatureBuildingContext: SignatureBuildingContext
|
||||||
property: CirProperty
|
|
||||||
): PropertyApproximationKey {
|
): PropertyApproximationKey {
|
||||||
return PropertyApproximationKey(
|
return PropertyApproximationKey(
|
||||||
name = property.name,
|
name = property.name,
|
||||||
extensionReceiverParameterType = property.extensionReceiver?.let {
|
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 {
|
companion object {
|
||||||
internal fun create(
|
internal fun create(
|
||||||
context: CirMemberContext,
|
function: CirFunction,
|
||||||
commonClassifierIdResolver: CirCommonClassifierIdResolver,
|
signatureBuildingContext: SignatureBuildingContext
|
||||||
function: CirFunction
|
|
||||||
): FunctionApproximationKey {
|
): FunctionApproximationKey {
|
||||||
return FunctionApproximationKey(
|
return FunctionApproximationKey(
|
||||||
name = function.name,
|
name = function.name,
|
||||||
valueParametersTypes = valueParameterTypes(context, commonClassifierIdResolver, function),
|
valueParametersTypes = valueParameterTypes(function, signatureBuildingContext),
|
||||||
extensionReceiverParameterType = function.extensionReceiver?.let {
|
extensionReceiverParameterType = function.extensionReceiver?.let {
|
||||||
buildApproximationSignature(SignatureBuildingContext.create(context, commonClassifierIdResolver, function), it.type)
|
buildApproximationSignature(signatureBuildingContext, it.type)
|
||||||
},
|
},
|
||||||
objCFunctionApproximation = objCFunctionApproximation(function)
|
objCFunctionApproximation = objCFunctionApproximation(function)
|
||||||
)
|
)
|
||||||
@@ -102,7 +73,6 @@ 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>,
|
||||||
@@ -111,10 +81,10 @@ data class ConstructorApproximationKey(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
internal fun create(
|
internal fun create(
|
||||||
context: CirMemberContext, commonClassifierIdResolver: CirCommonClassifierIdResolver, constructor: CirClassConstructor
|
constructor: CirClassConstructor, signatureBuildingContext: SignatureBuildingContext
|
||||||
): ConstructorApproximationKey {
|
): ConstructorApproximationKey {
|
||||||
return ConstructorApproximationKey(
|
return ConstructorApproximationKey(
|
||||||
valueParametersTypes = valueParameterTypes(context, commonClassifierIdResolver, constructor),
|
valueParametersTypes = valueParameterTypes(constructor, signatureBuildingContext),
|
||||||
objCFunctionApproximation = objCFunctionApproximation(constructor)
|
objCFunctionApproximation = objCFunctionApproximation(constructor)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -140,150 +110,13 @@ private fun <T> objCFunctionApproximation(value: T): ObjCFunctionApproximation
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> valueParameterTypes(
|
private fun <T> valueParameterTypes(
|
||||||
context: CirMemberContext,
|
callable: T,
|
||||||
commonClassifierIdResolver: CirCommonClassifierIdResolver,
|
signatureBuildingContext: SignatureBuildingContext,
|
||||||
callable: T
|
|
||||||
): Array<CirTypeSignature>
|
): 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, commonClassifierIdResolver, callable), parameter.returnType)
|
buildApproximationSignature(signatureBuildingContext, 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]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+103
@@ -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
|
context: TargetBuildingContext, function: CirFunction, parent: CirNode<*, *>? = null
|
||||||
) {
|
) {
|
||||||
val functionNode = functions.getOrPut(
|
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))
|
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(
|
internal fun CirNodeWithMembers<*, *>.buildProperty(
|
||||||
context: TargetBuildingContext, property: CirProperty, parent: CirNode<*, *>? = null
|
context: TargetBuildingContext, property: CirProperty, parent: CirNode<*, *>? = null
|
||||||
) {
|
) {
|
||||||
val propertyNode = properties.getOrPut(
|
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))
|
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(
|
internal fun CirClassNode.buildConstructor(
|
||||||
context: TargetBuildingContext, constructor: CirClassConstructor, parent: CirNode<*, *>
|
context: TargetBuildingContext, constructor: CirClassConstructor, parent: CirNode<*, *>
|
||||||
) {
|
) {
|
||||||
val constructorNode = constructors.getOrPut(
|
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))
|
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) {
|
internal fun CirPackageNode.buildTypeAlias(context: TargetBuildingContext, treeTypeAlias: CirTreeTypeAlias) {
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ class CommonizedGroup<T : Any>(
|
|||||||
elements[index] = value
|
elements[index] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun setAllowingOverride(index: Int, value: T?) {
|
fun setIfAbsent(index: Int, value: T?) {
|
||||||
elements[index] = value
|
if (this[index] == null) set(index, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ class TypeCommonizerTest : AbstractInlineSourcesCommonizationTest() {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") }, commonizer(
|
mockClassType("kotlin/sequences/SequenceScope"), commonizer(
|
||||||
listOf(
|
listOf(
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
||||||
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
mockTAType("kotlin/sequences/SequenceBuilder") { mockClassType("kotlin/sequences/SequenceScope") },
|
||||||
|
|||||||
+1
-5
@@ -110,11 +110,7 @@ class ParameterizedTypesCommonizationTest : AbstractInlineSourcesCommonizationTe
|
|||||||
typealias TA2<R> = TA1<String, R>
|
typealias TA2<R> = TA1<String, R>
|
||||||
typealias TA3 = TA2<Int>
|
typealias TA3 = TA2<Int>
|
||||||
|
|
||||||
/*
|
expect fun x1(x: TA1<String, Int>)
|
||||||
Desirable solution below!
|
|
||||||
Test ensures that no wrong commonization is emitted for now.
|
|
||||||
*/
|
|
||||||
//expect fun x1(x: TA1<String, Int>)
|
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user