[FIR] Modify signatures also from ERASED_COLLECTION_PARAMETER_SIGNATURES

In this commit we change value parameter type of containsAll, removeAll,
retainAll from Java collections. Originally it's Collection<?>,
we change it to Collection<T>

#KT-42340 Fixed
This commit is contained in:
Mikhail Glukhikh
2020-09-30 13:52:17 +03:00
committed by teamcityserver
parent 3a693e112b
commit 2dc6467b5d
10 changed files with 1244 additions and 41 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.java.scopes
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
@@ -22,6 +23,10 @@ import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_COLLECTION_PARAMETER_SIGNATURES
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_VALUE_PARAMETERS_SHORT_NAMES
import org.jetbrains.kotlin.load.java.SpecialGenericSignatures.Companion.ERASED_VALUE_PARAMETERS_SIGNATURES
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -58,56 +63,74 @@ class JavaClassMembersEnhancementScope(
private fun FirSimpleFunction.changeSignatureIfErasedValueParameter(): FirSimpleFunction {
val typeParameters = owner.fir.typeParameters
if (typeParameters.isEmpty() || name !in SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SHORT_NAMES) {
if (typeParameters.isEmpty() || name !in ERASED_VALUE_PARAMETERS_SHORT_NAMES) {
return this
}
val jvmDescriptor = this.computeJvmDescriptorReplacingKotlinToJava()
if (SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SIGNATURES.none { it.endsWith(jvmDescriptor) }) {
val jvmDescriptor = this.computeJvmDescriptorReplacingKotlinToJava().replace(
"kotlin/collections/Collection",
"java/util/Collection"
)
if (ERASED_VALUE_PARAMETERS_SIGNATURES.none { it.endsWith(jvmDescriptor) }) {
return this
}
val superClassIds = listOfNotNull(symbol.callableId.classId) +
lookupSuperTypes(owner, lookupInterfaces = true, deep = true, useSiteSession = session).map { it.lookupTag.classId }
for (superClassId in superClassIds) {
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(superClassId.asSingleFqName().toUnsafe()) ?: superClassId
val fqJvmDescriptor = "${javaClassId.asString()}.$jvmDescriptor"
if (fqJvmDescriptor in SpecialGenericSignatures.ERASED_VALUE_PARAMETERS_SIGNATURES) {
val specialSignatureInfo = SpecialGenericSignatures.getSpecialSignatureInfo(fqJvmDescriptor)
if (!specialSignatureInfo.isObjectReplacedWithTypeParameter) {
return this
}
val newParameterTypes = valueParameters.mapIndexed { i, valueParameter ->
val classLikeType =
valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.lowerBoundIfFlexible().safeAs<ConeClassLikeType>()
if (classLikeType?.lookupTag?.classId == StandardClassIds.Any) {
val typeParameterIndex = if (name.asString() == "containsValue") 1 else i
val typeParameter = typeParameters.getOrNull(typeParameterIndex) ?: typeParameters.first()
val type = ConeTypeParameterLookupTag(typeParameter.symbol).constructType(
emptyArray(), valueParameter.returnTypeRef.isMarkedNullable == true
val newParameterTypes: List<ConeKotlinType?> = when (val fqJvmDescriptor = "${javaClassId.asString()}.$jvmDescriptor") {
in ERASED_COLLECTION_PARAMETER_SIGNATURES -> {
valueParameters.map {
val typeParameter = typeParameters.first()
ConeClassLikeLookupTagImpl(ClassId.topLevel(StandardNames.FqNames.collection)).constructClassType(
arrayOf(
ConeTypeParameterLookupTag(typeParameter.symbol).constructType(emptyArray(), isNullable = false)
), isNullable = false
)
if (valueParameter.returnTypeRef.coneType is ConeFlexibleType) {
ConeFlexibleType(type, type.withNullability(ConeNullability.NULLABLE))
} else {
type
}
} else {
null
}
}
if (newParameterTypes.none { it != null }) {
return this
in ERASED_VALUE_PARAMETERS_SIGNATURES -> {
val specialSignatureInfo = SpecialGenericSignatures.getSpecialSignatureInfo(fqJvmDescriptor)
if (!specialSignatureInfo.isObjectReplacedWithTypeParameter) {
return this
}
valueParameters.mapIndexed { i, valueParameter ->
val classLikeType =
valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.lowerBoundIfFlexible().safeAs<ConeClassLikeType>()
if (classLikeType?.lookupTag?.classId == StandardClassIds.Any) {
val typeParameterIndex = if (name.asString() == "containsValue") 1 else i
val typeParameter = typeParameters.getOrNull(typeParameterIndex) ?: typeParameters.first()
val type = ConeTypeParameterLookupTag(typeParameter.symbol).constructType(
emptyArray(), valueParameter.returnTypeRef.isMarkedNullable == true
)
if (valueParameter.returnTypeRef.coneType is ConeFlexibleType) {
ConeFlexibleType(type, type.withNullability(ConeNullability.NULLABLE))
} else {
type
}
} else {
null
}
}
}
else -> {
continue
}
}
if (newParameterTypes.none { it != null }) {
return this
}
return FirFakeOverrideGenerator.createCopyForFirFunction(
FirNamedFunctionSymbol(symbol.callableId),
this,
session,
FirDeclarationOrigin.Enhancement,
newParameterTypes = valueParameters.zip(newParameterTypes).map { (valueParameter, newType) ->
newType ?: valueParameter.returnTypeRef.coneType
},
return FirFakeOverrideGenerator.createCopyForFirFunction(
FirNamedFunctionSymbol(symbol.callableId),
this,
session,
FirDeclarationOrigin.Enhancement,
newParameterTypes = valueParameters.zip(newParameterTypes).map { (valueParameter, newType) ->
newType ?: valueParameter.returnTypeRef.coneType
},
newDispatchReceiverType = dispatchReceiverType,
)
}
}
return this
}