[Commonizer] Fix: approximate signatures with type parameter upper bounds

This commit is contained in:
Dmitriy Dolovov
2019-10-10 16:10:48 +07:00
parent 92656a53ae
commit a3e3b43aed
2 changed files with 41 additions and 18 deletions
@@ -47,8 +47,8 @@ class CirSimpleType(private val wrapped: SimpleType) : CirType() {
val isDefinitelyNotNullType get() = abbreviation.isDefinitelyNotNullType
val expandedTypeConstructorId by lazy(PUBLICATION) { CirTypeConstructorId(expanded) }
inline val isClassOrTypeAlias: Boolean get() = (kind == CLASS || kind == TYPE_ALIAS)
val fqNameWithTypeParameters: String get() = wrapped.fqNameWithTypeParameters
inline val isClassOrTypeAlias get() = (kind == CLASS || kind == TYPE_ALIAS)
val fqNameWithTypeParameters by lazy(PUBLICATION) { wrapped.fqNameWithTypeParameters }
override fun equals(other: Any?) = wrapped == (other as? CirSimpleType)?.wrapped
override fun hashCode() = wrapped.hashCode()
@@ -11,7 +11,10 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils.getTypeParameterDescriptorOrNull
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
internal fun <T> Sequence<T>.toList(expectedCapacity: Int): List<T> {
@@ -29,29 +32,49 @@ internal inline val KotlinType.fqName: FqName
get() = declarationDescriptor.fqNameSafe
internal val KotlinType.fqNameWithTypeParameters: String
get() = buildString { buildFqNameWithTypeParameters(this@fqNameWithTypeParameters) }
get() = buildString { buildFqNameWithTypeParameters(this@fqNameWithTypeParameters, HashSet()) }
private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType) {
private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, exploredTypeParameters: MutableSet<KotlinType>) {
append(type.fqName)
val arguments = type.arguments
if (arguments.isNotEmpty()) {
append("<")
arguments.forEachIndexed { index, argument ->
if (index > 0)
append(",")
val typeParameterDescriptor = getTypeParameterDescriptorOrNull(type)
if (typeParameterDescriptor != null) {
// N.B this is type parameter type
if (argument.isStarProjection)
append("*")
else {
val variance = argument.projectionKind
if (variance != Variance.INVARIANT)
append(variance).append(" ")
buildFqNameWithTypeParameters(argument.type)
if (exploredTypeParameters.add(type.makeNotNullable())) { // print upper bounds once the first time when type parameter type is met
append(":[")
typeParameterDescriptor.upperBounds.forEachIndexed { index, upperBound ->
if (index > 0)
append(",")
buildFqNameWithTypeParameters(upperBound, exploredTypeParameters)
}
append("]")
}
} else {
// N.B. this is classifier type
val arguments = type.arguments
if (arguments.isNotEmpty()) {
append("<")
arguments.forEachIndexed { index, argument ->
if (index > 0)
append(",")
if (argument.isStarProjection)
append("*")
else {
val variance = argument.projectionKind
if (variance != Variance.INVARIANT)
append(variance).append(" ")
buildFqNameWithTypeParameters(argument.type, exploredTypeParameters)
}
}
append(">")
}
append(">")
}
if (type.isMarkedNullable)
append("?")
}
internal fun Any?.isNull(): Boolean = this == null