Handle situation where KSerializer is absent from immediate supertypes
of the class used in @UseSerializers: Use methods to receive full list of supertypes. K1 supertypes() call returned all supertypes, while IrClass.supertypes and FirClassSymbol.resolvedSuperTypes return only immediate ones. This lead to a difference in behavior between K1 and K2, and regression after plugin backend was rewritten from descriptors to IR. #KT-55340 Fixed
This commit is contained in:
committed by
Space Team
parent
c011f0c374
commit
1c4614e93b
+23
-1
@@ -13,10 +13,14 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.arguments
|
||||
import org.jetbrains.kotlin.fir.resolve.createSubstitutionForSupertype
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.services.dependencySerializationInfoProvider
|
||||
@@ -180,13 +184,31 @@ val ConeKotlinType.isKSerializer: Boolean
|
||||
fun ConeKotlinType.serializerForType(session: FirSession): ConeKotlinType? {
|
||||
return this.fullyExpandedType(session)
|
||||
.toRegularClassSymbol(session)
|
||||
?.resolvedSuperTypes
|
||||
?.getAllSubstitutedSupertypes(session)
|
||||
?.find { it.isKSerializer }
|
||||
?.typeArguments
|
||||
?.firstOrNull()
|
||||
?.type
|
||||
}
|
||||
|
||||
fun FirRegularClassSymbol.getAllSubstitutedSupertypes(session: FirSession): Set<ConeKotlinType> {
|
||||
val result = mutableSetOf<ConeKotlinType>()
|
||||
|
||||
fun process(symbol: FirRegularClassSymbol, substitutor: ConeSubstitutor) {
|
||||
for (superType in symbol.resolvedSuperTypes) {
|
||||
if (result.add(substitutor.substituteOrSelf(superType))) {
|
||||
val superClassSymbol = superType.fullyExpandedType(session).toRegularClassSymbol(session) ?: continue
|
||||
val superSubstitutor =
|
||||
(superType as? ConeLookupTagBasedType)?.let { createSubstitutionForSupertype(it, session) } ?: ConeSubstitutor.Empty
|
||||
process(superClassSymbol, ChainedSubstitutor(superSubstitutor, substitutor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process(this, ConeSubstitutor.Empty)
|
||||
return result
|
||||
}
|
||||
|
||||
val ConeKotlinType.isTypeParameter: Boolean
|
||||
get() = this is ConeTypeParameterType
|
||||
|
||||
|
||||
+11
-6
@@ -34,6 +34,7 @@ import org.jetbrains.kotlinx.serialization.compiler.fir.services.findTypeSeriali
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.services.serializablePropertiesProvider
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.services.versionReader
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds
|
||||
|
||||
object FirSerializationPluginClassChecker : FirClassChecker() {
|
||||
private val JAVA_SERIALIZABLE_ID = ClassId.topLevel(FqName("java.io.Serializable"))
|
||||
@@ -421,27 +422,31 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
|
||||
) {
|
||||
for (property in properties) {
|
||||
// TODO: reporting diagnostics on properties from superclasses looks a bad idea
|
||||
val serializerType = property.serializableWith
|
||||
val serializerSymbol = serializerType?.toRegularClassSymbol(session)
|
||||
val customSerializerType = property.serializableWith
|
||||
val serializerSymbol = customSerializerType?.toRegularClassSymbol(session)
|
||||
val propertySymbol = property.propertySymbol
|
||||
val typeRef = propertySymbol.resolvedReturnTypeRef
|
||||
val propertyType = typeRef.coneType
|
||||
val source = typeRef.source ?: propertySymbol.source
|
||||
if (serializerType != null && serializerSymbol != null) {
|
||||
if (customSerializerType != null && serializerSymbol != null) {
|
||||
// Do not account for @Polymorphic and @Contextual, as they are serializers for T: Any
|
||||
// and would not be compatible on direct comparison
|
||||
if (customSerializerType.classId in SerializersClassIds.setOfSpecialSerializers) return
|
||||
|
||||
checkCustomSerializerMatch(
|
||||
classSymbol,
|
||||
source = typeRef.source ?: propertySymbol.source,
|
||||
propertyType,
|
||||
serializerType,
|
||||
customSerializerType,
|
||||
reporter
|
||||
)
|
||||
checkCustomSerializerIsNotLocal(
|
||||
source = propertySymbol.serializableAnnotation(needArguments = false)?.source,
|
||||
classSymbol,
|
||||
serializerType,
|
||||
customSerializerType,
|
||||
reporter
|
||||
)
|
||||
checkSerializerNullability(propertyType, serializerType, source, reporter)
|
||||
checkSerializerNullability(propertyType, customSerializerType, source, reporter)
|
||||
} else {
|
||||
checkType(propertyType, source, reporter)
|
||||
checkGenericArrayType(propertyType, source, reporter)
|
||||
|
||||
Reference in New Issue
Block a user