From 717d1c774b359d797b7945862edf5aec150e40b5 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 3 Jan 2024 12:00:59 +0200 Subject: [PATCH] [FIR] Save information about SerializationPluginMetadataExtensions in the property attribute K1 implementation of kotlinx.serialization used SerializationPluginMetadataExtensions for two purposes: - to extract the source-order of properties - to identify which properties are actually serializable In K2, the first point is covered by the compiler itself (as it correctly orders properties during deserialization), and to cover the second point we need to save in the propery information if it was mentioned in this extension or not KT-64312 --- .../deserialization/ClassDeserialization.kt | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt index 6091c149089..4de76e6bb9d 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.scopes.FirScopeProvider import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeTypeProjection @@ -142,9 +143,14 @@ fun deserializeClassToSymbol( } ) + val propertiesOrderFromExtension = classProto.getPropertyOrderFromMetadataExtension() addDeclarations( - classProto.propertiesInOrder(versionRequirements).map { - classDeserializer.loadProperty(it, classProto, symbol) + classProto.propertiesInOrder(versionRequirements, propertiesOrderFromExtension).map { propertyProto -> + classDeserializer.loadProperty(propertyProto, classProto, symbol).also { property -> + if (propertyProto.name in propertiesOrderFromExtension) { + property.registeredInSerializationPluginMetadataExtension = true + } + } } ) @@ -299,21 +305,33 @@ fun FirRegularClassBuilder.addCloneForArrayIfNeeded(classId: ClassId, dispatchRe } } -private fun ProtoBuf.ClassOrBuilder.propertiesInOrder(versionRequirements: List): List { +private fun ProtoBuf.ClassOrBuilder.getPropertyOrderFromMetadataExtension(): Set { + return getExtension(SerializationPluginMetadataExtensions.propertiesNamesInProgramOrder).toSet() +} + +private fun ProtoBuf.ClassOrBuilder.propertiesInOrder( + versionRequirements: List, + orderFromExtension: Set, +): List { val properties = propertyList if (versionRequirements.any { it.version.major >= 2 }) return properties - val order = getExtension(SerializationPluginMetadataExtensions.propertiesNamesInProgramOrder) - .takeIf { it.isNotEmpty() } - ?.toSet() - ?: return properties + if (orderFromExtension.isEmpty()) return properties val propertiesByName = properties.groupBy { it.name } - val orderedProperties = order.flatMap { propertiesByName[it] ?: emptyList() } + val orderedProperties = orderFromExtension.flatMap { propertiesByName[it] ?: emptyList() } // non-serializable properties are not saved in SerializationPluginMetadataExtensions, so we need to pick up them if any return if (orderedProperties.size == properties.size) { orderedProperties } else { - orderedProperties + properties.filter { it.name !in order } + orderedProperties + properties.filter { it.name !in orderFromExtension } } } val FirSession.deserializationExtension: FirDeserializationExtension? by FirSession.nullableSessionComponentAccessor() + +private object RegisteredInSerializationPluginMetadataExtensionKey : FirDeclarationDataKey() + +private var FirProperty.registeredInSerializationPluginMetadataExtension: Boolean? + by FirDeclarationDataRegistry.data(RegisteredInSerializationPluginMetadataExtensionKey) + +val FirPropertySymbol.registeredInSerializationPluginMetadataExtension: Boolean + get() = fir.registeredInSerializationPluginMetadataExtension ?: false