[FIR] Remove FirDeclarationsForMetadataProviderExtension extension

`IrGeneratedDeclarationsRegistrar` should be now used instead to register
  IR declarations in resulting metadata
This commit is contained in:
Dmitriy Novozhilov
2023-11-28 18:09:45 +02:00
parent d94ce4dcb8
commit c70c8f927e
8 changed files with 49 additions and 299 deletions
@@ -34,8 +34,6 @@ class FirPluginPrototypeExtensionRegistrar : FirExtensionRegistrar() {
+::AdditionalMembersGenerator
+::CompanionGenerator
+::MembersOfSerializerGenerator
+::AllPropertiesConstructorMetadataProvider
}
}
@@ -1,48 +0,0 @@
/*
* Copyright 2010-2023 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.fir.plugin.generators
import org.jetbrains.kotlin.GeneratedDeclarationKey
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
import org.jetbrains.kotlin.fir.extensions.FirDeclarationsForMetadataProviderExtension
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.plugin.createConstructor
import org.jetbrains.kotlin.fir.plugin.fqn
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.scopes.getProperties
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
class AllPropertiesConstructorMetadataProvider(session: FirSession) : FirDeclarationsForMetadataProviderExtension(session) {
companion object {
val ANNOTATION_FQN = "AllPropertiesConstructor".fqn()
val PREDICATE = DeclarationPredicate.create { annotated(ANNOTATION_FQN) }
}
private object Key : GeneratedDeclarationKey()
override fun provideDeclarationsForClass(klass: FirClass, scopeSession: ScopeSession): List<FirDeclaration> {
if (!session.predicateBasedProvider.matches(PREDICATE, klass)) return emptyList()
val scope = klass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false, memberRequiredPhase = null)
val properties = scope.getCallableNames()
.flatMap { scope.getProperties(it) }
.sortedBy { it.containingClassLookupTag() == klass.symbol.toLookupTag() }
val constructor = createConstructor(klass.symbol, Key) {
for (property in properties) {
valueParameter(property.name, property.resolvedReturnType)
}
}
return listOf(constructor)
}
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
register(PREDICATE)
}
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.ir.plugin
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.plugin.generators.AllPropertiesConstructorMetadataProvider
import org.jetbrains.kotlin.fir.plugin.fqn
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
@@ -29,6 +29,10 @@ import java.util.Comparator
* Parent class should be Any or class, annotated with @AllPropertiesConstructor
*/
class AllPropertiesConstructorIrGenerator(val context: IrPluginContext) : IrElementVisitorVoid {
companion object {
private val ANNOTATION_FQN = "AllPropertiesConstructor".fqn()
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
@@ -89,8 +93,6 @@ class AllPropertiesConstructorIrGenerator(val context: IrPluginContext) : IrElem
}
private fun IrClass.hasAnnotation(): Boolean {
return annotations.findAnnotation(AllPropertiesConstructorMetadataProvider.ANNOTATION_FQN) != null
return annotations.hasAnnotation(ANNOTATION_FQN)
}
}
@@ -17,7 +17,6 @@ class FirSerializationExtensionRegistrar : FirExtensionRegistrar() {
+::SerializationFirResolveExtension
+::SerializationFirSupertypesExtension
+::FirSerializationCheckersComponent
+::SerializationFirDeclarationsForMetadataProvider
// services
+::DependencySerializationInfoProvider
@@ -1,126 +0,0 @@
/*
* Copyright 2010-2023 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.kotlinx.serialization.compiler.fir
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall
import org.jetbrains.kotlin.fir.extensions.FirDeclarationsForMetadataProviderExtension
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.plugin.createConstructor
import org.jetbrains.kotlin.fir.plugin.createMemberFunction
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmStandardClassIds
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlinx.serialization.compiler.fir.services.serializablePropertiesProvider
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
class SerializationFirDeclarationsForMetadataProvider(session: FirSession) : FirDeclarationsForMetadataProviderExtension(session) {
override fun provideDeclarationsForClass(klass: FirClass, scopeSession: ScopeSession): List<FirDeclaration> {
// FIXME: multi-field value classes require additional 'if' here, but they're not supported for now in serialization K2.
return if (klass.symbol.isInline || with(session) { !klass.symbol.isInternalSerializable }) emptyList()
// As we deprecated 'customize serializer via companion', we know for sure
// that serialize/deserialize functions are synthetic and generated by our plugin.
else listOfNotNull(generateDeserializationConstructor(klass), generateWriteSelf(klass))
}
private fun generateDeserializationConstructor(klass: FirClass): FirDeclaration =
createConstructor(klass.symbol, SerializationPluginKey, isPrimary = false) {
// deserialization constructor for final classes could be internal, because it can't be called in inheritors
visibility = if (klass.isFinal) Visibilities.Internal else Visibilities.Public
val serializableProperties =
session.serializablePropertiesProvider.getSerializablePropertiesForClass(klass.symbol).serializableProperties
val bitMaskSlotCount = serializableProperties.bitMaskSlotCount()
repeat(bitMaskSlotCount) {
valueParameter(Name.identifier("seen$it"), session.builtinTypes.intType.type)
}
serializableProperties.forEach { prop ->
valueParameter(
prop.originalDescriptorName,
prop.propertySymbol.resolvedReturnType.makeNullableIfNotPrimitive(session.typeContext)
)
}
val markerType =
ClassId(SerializationPackages.internalPackageFqName, SerialEntityNames.SERIAL_CTOR_MARKER_NAME).constructClassLikeType(
emptyArray(),
isNullable = true
)
valueParameter(SerialEntityNames.dummyParamName, markerType)
}
private fun generateWriteSelf(klass: FirClass): FirDeclaration? {
// write$Self in K1 is created only on JVM (see SerializationResolveExtension)
if (!session.moduleData.platform.isJvm()) return null
return createMemberFunction(
klass.symbol,
SerializationPluginKey,
SerialEntityNames.WRITE_SELF_NAME,
session.builtinTypes.unitType.type
) {
// write$Self for final classes could be internal, because it can't be called in inheritors
visibility = if (klass.isFinal) Visibilities.Internal else Visibilities.Public
klass.typeParameters.forEach {
typeParameter(it.symbol.name)
}
valueParameter(Name.identifier("self"), { functionTypeParams ->
klass.symbol.constructType(functionTypeParams.map { it.toConeType() }.toTypedArray(), false)
})
valueParameter(
Name.identifier("output"),
SerializationRuntimeClassIds.compositeEncoderClassId.constructClassLikeType(emptyArray(), false)
)
valueParameter(
Name.identifier("serialDesc"),
SerializationRuntimeClassIds.descriptorClassId.constructClassLikeType(emptyArray(), false)
)
klass.typeParameters.forEachIndexed { i, _ ->
valueParameter(Name.identifier("${SerialEntityNames.typeArgPrefix}$i"), { functionTps ->
SerializersClassIds.kSerializerId.constructClassLikeType(arrayOf(functionTps[i].toConeType()), false)
})
}
}.apply { replaceAnnotations(listOfNotNull(createJvmStaticAnnotation())) }
}
private fun createJvmStaticAnnotation(): FirAnnotation? {
val jvmStatic =
session.symbolProvider.getClassLikeSymbolByClassId(JvmStandardClassIds.Annotations.JvmStatic) as? FirRegularClassSymbol
?: return null
val jvmStaticCtor =
jvmStatic.declarationSymbols.firstIsInstanceOrNull<FirConstructorSymbol>() ?: return null
return buildAnnotationCall {
annotationTypeRef = jvmStatic.defaultType().toFirResolvedTypeRef()
calleeReference = buildResolvedNamedReference {
name = jvmStatic.name
resolvedSymbol = jvmStaticCtor
}
}
}
}
internal fun ConeKotlinType.makeNullableIfNotPrimitive(typeContext: ConeTypeContext): ConeKotlinType =
if (isPrimitive) this else withNullability(ConeNullability.NULLABLE, typeContext)