diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidIrExtension.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidIrExtension.kt index d8b8935206f..174d457ee56 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidIrExtension.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/codegen/AndroidIrExtension.kt @@ -121,7 +121,7 @@ private class AndroidIrTransformer(val extension: AndroidIrExtension, val plugin } // NOTE: sparse array version intentionally not implemented; this plugin is deprecated - @OptIn(FirIncompatiblePluginAPI::class) // TODO: check that it still works with FIR + @OptIn(FirIncompatiblePluginAPI::class) private val mapFactory = pluginContext.referenceFunctions(FqName("kotlin.collections.mutableMapOf")) .single { it.owner.valueParameters.isEmpty() } private val mapGet = pluginContext.irBuiltIns.mapClass.owner.functions diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/FirSerializationPredicates.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/FirSerializationPredicates.kt new file mode 100644 index 00000000000..6e9f7b0775e --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/FirSerializationPredicates.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2022 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.fir.extensions.predicate.AnnotatedWith +import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate +import org.jetbrains.kotlin.fir.extensions.predicate.ancestorAnnotated +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations + +object FirSerializationPredicates { + internal val serializerFor: DeclarationPredicate = + AnnotatedWith(setOf(SerializationAnnotations.serializerAnnotationFqName)) // @Serializer(for=...) + internal val generatedSerializer: DeclarationPredicate = + ancestorAnnotated(SerializationAnnotations.serializableAnnotationFqName) // @Serializable X.$serializer + internal val annotatedWithSerializable = AnnotatedWith(setOf(SerializationAnnotations.serializableAnnotationFqName)) +} \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirResolveExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirResolveExtension.kt index f8c8082ad61..02a8388eb28 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirResolveExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirResolveExtension.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes +import org.jetbrains.kotlin.fir.resolve.typeWithStarProjections import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.impl.* @@ -56,7 +57,6 @@ val kSerializerClassId = ClassId(SerializationPackages.packageFqName, SerialEnti class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGenerationExtension(session) { - // FIXME: I can't check status here override fun getNestedClassifiersNames(classSymbol: FirClassSymbol<*>): Set { val result = mutableSetOf() if (classSymbol.shouldHaveGeneratedMethodsInCompanion && !classSymbol.isSerializableObject) @@ -65,22 +65,7 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene result += SerialEntityNames.SERIALIZER_CLASS_NAME return result } - /** - * It's not documented how these classes relate with getCallableNamesForClass - * Document says: - * 1.> If you generate some class using generateClassLikeDeclaration then you don't need to fill it's declarations. - * Q: Don't need or MUSTN'T? - * - * 2. > Instead of that you need to generate members via generateProperties/Functions/Constructors methods - * of same generation extension (this is important note if you have multiple generation extensions in your plugin) - * - * Q: Does this mean that for e.g. generated companion `generateFunctions` will be called regardless of provided predicate? - * - * 3. This method is stated to be called on SUPERTYPES, but getNestedClassifiersNames stated to be called after SUPERTYPES. How is this possible? - * - * 4. It is should be mentioned that supertypes for generated class should be added here, - * while supertypes for exisiting classes — in separate extension - */ + override fun generateClassLikeDeclaration(classId: ClassId): FirClassLikeSymbol<*>? { return when (classId.shortClassName) { SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT -> { @@ -93,17 +78,7 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene } } - /** - * 1. It is unclear that for `generateConstructors` to work, one need to return SpecialNames.INIT from here - * 1a. Also it is unclear that objects need constructors too. - * - * 2. If it is a user-written companion object, will I get here? Why? - * - * 3. Is it supposed to check that classSymbol does not already have same Name? How to add a generated overload? - * - * 4. It is unclear what to do with properties - * - */ + override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>): Set { val classId = classSymbol.classId val result = mutableSetOf() @@ -124,7 +99,6 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene SpecialNames.INIT, SerialEntityNames.SAVE_NAME, SerialEntityNames.LOAD_NAME, - // FIXME: correctly create property? SerialEntityNames.SERIAL_DESC_FIELD_NAME ) if (classSymbol.superConeTypes.any { @@ -147,7 +121,7 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene @OptIn(SymbolInternals::class) private fun getFromSupertype(callableId: CallableId, owner: FirClassSymbol<*>, extractor: (FirTypeScope) -> List): T { - val scopeSession = ScopeSession() // ???????? + val scopeSession = ScopeSession() val scopes = lookupSuperTypes( owner, lookupInterfaces = true, deep = false, useSiteSession = session ).mapNotNull { useSiteSuperType -> @@ -240,7 +214,7 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene // FIXME: it seems that this list will always be used, why not provide it automatically? private val matchedClasses by lazy { - session.predicateBasedProvider.getSymbolsByPredicate(AnnotatedWith(setOf(SerializationAnnotations.serializableAnnotationFqName))) + session.predicateBasedProvider.getSymbolsByPredicate(FirSerializationPredicates.annotatedWithSerializable) .filterIsInstance() } @@ -267,7 +241,7 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene Modality.FINAL, EffectiveVisibility.Public ) - // FIXME: how to create annotations? + // TODO: add deprecate hidden // annotations = listOf(Annotations.create(listOf(KSerializerDescriptorResolver.createDeprecatedHiddenAnnotation(thisDescriptor.module)))) @@ -286,11 +260,8 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene }) superTypeRefs += buildResolvedTypeRef { - // FIXME: document how one gets type ref from FirClass - // is this a correct one or should I go with buildTypeProjectionWithVariance ? - // is this a correct place to add supertypes to synthetic declarations? Looks like FirSupertypesExtension does not see class. - // It seems that this code generates KSerializer> instead of KSerializer>, but it didn't matter for old FE - type = generatedSerializerClassId.constructClassLikeType(arrayOf(owner.defaultType().toTypeProjection(Variance.INVARIANT)), isNullable = false) + @OptIn(SymbolInternals::class) + type = generatedSerializerClassId.constructClassLikeType(arrayOf(owner.fir.typeWithStarProjections()), isNullable = false) } } // TODO: add typed constructor @@ -333,7 +304,6 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene } override fun FirDeclarationPredicateRegistrar.registerPredicates() { - // No predicate on final/open etc - register(AnnotatedWith(setOf(SerializationAnnotations.serializableAnnotationFqName))) + register(FirSerializationPredicates.annotatedWithSerializable) } } \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirSupertypesExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirSupertypesExtension.kt index 203a3556654..273e68e59d3 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirSupertypesExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirSupertypesExtension.kt @@ -7,44 +7,23 @@ package org.jetbrains.kotlinx.serialization.compiler.fir import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration -import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension -import org.jetbrains.kotlin.fir.extensions.predicate.* import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider -import org.jetbrains.kotlin.fir.resolve.defaultType -import org.jetbrains.kotlin.fir.resolve.getContainingDeclaration import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef -import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance import org.jetbrains.kotlin.fir.types.classId -import org.jetbrains.kotlin.fir.types.constructClassLikeType -import org.jetbrains.kotlin.fir.types.toTypeProjection import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlinx.serialization.compiler.fir.FirSerializationPredicates.serializerFor import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames -import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages class SerializationFirSupertypesExtension(session: FirSession) : FirSupertypeGenerationExtension(session) { - companion object { - private val serializerFor: DeclarationPredicate = - AnnotatedWith(setOf(SerializationAnnotations.serializerAnnotationFqName)) // @Serializer(for=...) - private val generatedSerializer: DeclarationPredicate = - ancestorAnnotated(SerializationAnnotations.serializableAnnotationFqName) // @Serializable X.$serializer - private val PREDICATE = serializerFor or generatedSerializer - } override fun needTransformSupertypes(declaration: FirClassLikeDeclaration): Boolean = session.predicateBasedProvider.matches(serializerFor, declaration) - || ( // TODO: this part is not working - session.predicateBasedProvider.matches(generatedSerializer, declaration) - && declaration is FirRegularClass - && declaration.name == SerialEntityNames.SERIALIZER_CLASS_NAME - ) override fun FirDeclarationPredicateRegistrar.registerPredicates() { - register(PREDICATE) + register(serializerFor) } override fun computeAdditionalSupertypes( @@ -56,20 +35,8 @@ class SerializationFirSupertypesExtension(session: FirSession) : FirSupertypeGen if (resolvedSupertypes.any { it.type.classId == kSerializerClassId || it.type.classId == generatedSerializerClassId }) return emptyList() - if (session.predicateBasedProvider.matches(serializerFor, classLikeDeclaration)) { + return if (session.predicateBasedProvider.matches(serializerFor, classLikeDeclaration)) { TODO("Support @Serializer(for=...) supertype generation") - } else { - // TODO: Remove this section as it is not working because one should add supertype for generated class where this class is created. - // @Serializable X.$serializer - val parent = (classLikeDeclaration.getContainingDeclaration(session) as? FirRegularClass) - ?: error("Generated serializer $classLikeDeclaration is not contained in any class") - - return listOf(buildResolvedTypeRef { - // FIXME: document how one gets type ref from FirClass - // FIXME: is this a correct one or should I go with buildTypeProjectionWithVariance ? - // It seems that this code generates KSerializer> instead of KSerializer>, but it didn't matter for old FE - type = generatedSerializerClassId.constructClassLikeType(arrayOf(parent.defaultType().toTypeProjection(Variance.INVARIANT)), isNullable = false) - }) - } + } else emptyList() } } \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt index fde1c2b6efb..44a9a389322 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt @@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations -// FIXME: why FirAnnotation.classId.asSingleFqName is available, but FirAnnotation.fqName() requires FirSession? internal val FirClassSymbol<*>.hasSerializableAnnotation get() = this.annotations.any { it.classId?.asSingleFqName()?.asString() == SerializationAnnotations.serializableAnnotationFqName.asString() @@ -56,9 +55,8 @@ internal fun FirClassSymbol<*>.isInternallySerializableEnum(): Boolean = internal val FirClassSymbol<*>.shouldHaveGeneratedSerializer: Boolean get() = (isInternalSerializable && isFinalOrOpen()) || isInternallySerializableEnum() -@OptIn(SymbolInternals::class) private fun FirClassSymbol<*>.isFinalOrOpen(): Boolean { - val modality = fir.status.modality + val modality = rawStatus.modality // null means default modality, final return (modality == null || modality == Modality.FINAL || modality == Modality.OPEN) } \ No newline at end of file