[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.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]
|
||||
}
|
||||
}
|
||||
-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
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
+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
|
||||
) {
|
||||
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") },
|
||||
|
||||
+1
-5
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user