Added support of MetaSerializable to the FIR
This commit is contained in:
committed by
Space Team
parent
28340459b0
commit
503f4d924d
+2
-15
@@ -367,20 +367,7 @@ interface IrBuilderWithPluginContext {
|
||||
val annotationClass = annotationCall.symbol.owner.parentAsClass
|
||||
if (!annotationClass.isSerialInfoAnnotation) return@mapNotNull null
|
||||
|
||||
if (compilerContext.platform.isJvm()) {
|
||||
val implClass = compilerContext.serialInfoImplJvmIrGenerator.getImplClass(annotationClass)
|
||||
val ctor = implClass.constructors.singleOrNull { it.valueParameters.size == annotationCall.valueArgumentsCount }
|
||||
?: error("No constructor args found for SerialInfo annotation Impl class: ${implClass.render()}")
|
||||
irCall(ctor).apply {
|
||||
for (i in 0 until annotationCall.valueArgumentsCount) {
|
||||
val argument = annotationCall.getValueArgument(i)
|
||||
?: annotationClass.primaryConstructor!!.valueParameters[i].defaultValue?.expression
|
||||
putValueArgument(i, argument!!.deepCopyWithVariables())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
annotationCall.deepCopyWithVariables()
|
||||
}
|
||||
annotationCall.deepCopyWithVariables()
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
@@ -400,4 +387,4 @@ interface IrBuilderWithPluginContext {
|
||||
}
|
||||
|
||||
fun IrClass.getSuperClassOrAny(): IrClass = getSuperClassNotAny() ?: compilerContext.irBuiltIns.anyClass.owner
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -5,9 +5,7 @@
|
||||
|
||||
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.kotlin.fir.extensions.predicate.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
||||
|
||||
object FirSerializationPredicates {
|
||||
@@ -15,5 +13,7 @@ object FirSerializationPredicates {
|
||||
AnnotatedWith(setOf(SerializationAnnotations.serializerAnnotationFqName)) // @Serializer(for=...)
|
||||
internal val generatedSerializer: DeclarationPredicate =
|
||||
ancestorAnnotated(SerializationAnnotations.serializableAnnotationFqName) // @Serializable X.$serializer
|
||||
internal val annotatedWithSerializable = AnnotatedWith(setOf(SerializationAnnotations.serializableAnnotationFqName))
|
||||
}
|
||||
internal val hasMetaAnnotation = metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName)
|
||||
internal val annotatedWithSerializableOrMeta =
|
||||
AnnotatedWith(setOf(SerializationAnnotations.serializableAnnotationFqName)) or metaAnnotated(SerializationAnnotations.metaSerializableAnnotationFqName)
|
||||
}
|
||||
|
||||
+36
-23
@@ -10,11 +10,13 @@ import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingDeclarationSymbol
|
||||
import org.jetbrains.kotlin.fir.copy
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.origin
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
|
||||
import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
|
||||
@@ -55,15 +57,15 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
hasFactory && hasMarkedFactory
|
||||
}
|
||||
|
||||
internal val FirClassSymbol<*>.shouldHaveGeneratedSerializer: Boolean
|
||||
get() = (isInternalSerializable && isFinalOrOpen()) || (classKind == ClassKind.ENUM_CLASS && hasSerializableAnnotationWithoutArgs && !runtimeHasEnumSerializerFactory)
|
||||
|
||||
override fun getNestedClassifiersNames(classSymbol: FirClassSymbol<*>): Set<Name> {
|
||||
val result = mutableSetOf<Name>()
|
||||
if (classSymbol.shouldHaveGeneratedMethodsInCompanion && !classSymbol.isSerializableObject)
|
||||
result += SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT
|
||||
if (classSymbol.shouldHaveGeneratedSerializer /* TODO && !classSymbol.hasCompanionObjectAsSerializer*/)
|
||||
result += SerialEntityNames.SERIALIZER_CLASS_NAME
|
||||
with(session) {
|
||||
if (classSymbol.shouldHaveGeneratedMethodsInCompanion && !classSymbol.isSerializableObject)
|
||||
result += SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT
|
||||
if (classSymbol.shouldHaveGeneratedSerializer(!runtimeHasEnumSerializerFactory) /* TODO && !classSymbol.hasCompanionObjectAsSerializer*/)
|
||||
result += SerialEntityNames.SERIALIZER_CLASS_NAME
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -115,7 +117,8 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> if (classSymbol.isSerializableObject) result += SerialEntityNames.SERIALIZER_PROVIDER_NAME
|
||||
|
||||
else -> if (with(session) { classSymbol.isSerializableObject }) result += SerialEntityNames.SERIALIZER_PROVIDER_NAME
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -129,8 +132,7 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
useSiteSuperType.scopeForSupertype(session, scopeSession, owner.fir)
|
||||
}
|
||||
val targets = scopes.flatMap { extractor(it) }
|
||||
val target = targets.singleOrNull() ?: error("Multiple overrides found for ${callableId.callableName}")
|
||||
return target
|
||||
return targets.singleOrNull() ?: error("Multiple overrides found for ${callableId.callableName}")
|
||||
}
|
||||
|
||||
// TODO: support @Serializer(for)
|
||||
@@ -138,7 +140,14 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
override fun generateFunctions(callableId: CallableId, context: MemberGenerationContext?): List<FirNamedFunctionSymbol> {
|
||||
val owner = context?.owner ?: return emptyList()
|
||||
if (callableId.callableName == SerialEntityNames.SERIALIZER_PROVIDER_NAME) {
|
||||
val serializableClass = owner.getSerializableClassSymbolIfCompanion(session) ?: return emptyList()
|
||||
val serializableClass = if (owner.isCompanion) {
|
||||
val containingSymbol = owner.getContainingDeclarationSymbol(session) as? FirClassSymbol<*> ?: return emptyList()
|
||||
if (with(session) { containingSymbol.shouldHaveGeneratedMethodsInCompanion }) containingSymbol else null
|
||||
} else {
|
||||
if (with(session) { owner.isSerializableObject }) owner else null
|
||||
}
|
||||
|
||||
serializableClass ?: return emptyList()
|
||||
return listOf(generateSerializerGetterInCompanion(owner, serializableClass, callableId))
|
||||
}
|
||||
if (owner.name != SerialEntityNames.SERIALIZER_CLASS_NAME) return emptyList()
|
||||
@@ -228,7 +237,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(FirSerializationPredicates.annotatedWithSerializable)
|
||||
session.predicateBasedProvider.getSymbolsByPredicate(FirSerializationPredicates.annotatedWithSerializableOrMeta)
|
||||
.filterIsInstance<FirRegularClassSymbol>()
|
||||
}
|
||||
|
||||
@@ -324,7 +333,7 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
name = SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT
|
||||
symbol = FirRegularClassSymbol(classId)
|
||||
superTypeRefs += session.builtinTypes.anyType
|
||||
if (owner.companionNeedsSerializerFactory()) {
|
||||
if (with(session) { owner.companionNeedsSerializerFactory }) {
|
||||
val serializerFactoryClassId = ClassId(SerializationPackages.internalPackageFqName, SERIALIZER_FACTORY_INTERFACE_NAME)
|
||||
superTypeRefs += serializerFactoryClassId.constructClassLikeType(emptyArray(), false).toFirResolvedTypeRef()
|
||||
}
|
||||
@@ -333,16 +342,20 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
}
|
||||
|
||||
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
|
||||
register(FirSerializationPredicates.annotatedWithSerializable)
|
||||
register(FirSerializationPredicates.annotatedWithSerializableOrMeta, FirSerializationPredicates.hasMetaAnnotation)
|
||||
}
|
||||
|
||||
private fun FirClassSymbol<*>.companionNeedsSerializerFactory(): Boolean {
|
||||
if (!(moduleData.platform.isNative() || moduleData.platform.isJs())) return false
|
||||
if (isSerializableObject) return true
|
||||
if (isSerializableEnum) return true
|
||||
if (isAbstractOrSealedSerializableClass) return true
|
||||
if (isSealedSerializableInterface) return true
|
||||
if (typeParameterSymbols.isEmpty()) return false
|
||||
return true
|
||||
}
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
private val FirClassSymbol<*>.companionNeedsSerializerFactory: Boolean
|
||||
get() {
|
||||
if (!(moduleData.platform.isNative() || moduleData.platform.isJs())) return false
|
||||
if (isSerializableObject) return true
|
||||
if (isSerializableEnum) return true
|
||||
if (isAbstractOrSealedSerializableClass) return true
|
||||
if (isSealedSerializableInterface) return true
|
||||
if (typeParameterSymbols.isEmpty()) return false
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+73
-135
@@ -7,24 +7,18 @@ package org.jetbrains.kotlinx.serialization.compiler.fir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingDeclarationSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
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.defaultType
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.scopes.getSingleClassifier
|
||||
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.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.services.dependencySerializationInfoProvider
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
||||
@@ -32,7 +26,6 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotat
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.metaSerializableAnnotationClassId
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoClassId
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialNameAnnotationClassId
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SpecialBuiltins
|
||||
|
||||
object AnnotationParameterNames {
|
||||
val VALUE = Name.identifier("value")
|
||||
@@ -65,10 +58,6 @@ val FirBasedSymbol<*>.hasSerialTransient: Boolean
|
||||
val FirBasedSymbol<*>.serialTransientAnnotation: FirAnnotation?
|
||||
get() = getAnnotationByClassId(SerializationAnnotations.serialTransientClassId)
|
||||
|
||||
context(CheckerContext)
|
||||
val FirBasedSymbol<*>.hasAnySerialAnnotation: Boolean
|
||||
get() = serialNameValue != null || resolvedAnnotationsWithClassIds.any { it.annotationClassSymbol?.isSerialInfoAnnotation == true }
|
||||
|
||||
val FirClassSymbol<*>.hasSerializableAnnotation: Boolean
|
||||
get() = serializableAnnotation(needArguments = false) != null
|
||||
|
||||
@@ -90,81 +79,84 @@ val FirClassSymbol<*>.hasSerializableAnnotationWithoutArgs: Boolean
|
||||
}
|
||||
} ?: false
|
||||
|
||||
context(CheckerContext)
|
||||
val FirClassSymbol<*>.hasSerializableOrMetaAnnotationWithoutArgs: Boolean
|
||||
get() = hasSerializableAnnotationWithoutArgs || (!hasSerializableAnnotation && hasMetaSerializableAnnotation)
|
||||
|
||||
|
||||
context(CheckerContext)
|
||||
val FirClassSymbol<*>.hasSerializableOrMetaAnnotation
|
||||
get() = hasSerializableAnnotation || hasMetaSerializableAnnotation
|
||||
|
||||
context(CheckerContext)
|
||||
val FirClassSymbol<*>.hasMetaSerializableAnnotation: Boolean
|
||||
get() = metaSerializableAnnotation(needArguments = false) != null
|
||||
|
||||
context(CheckerContext)
|
||||
fun FirClassSymbol<*>.metaSerializableAnnotation(needArguments: Boolean): FirAnnotation? {
|
||||
val annotations = if (needArguments) resolvedAnnotationsWithClassIds else resolvedAnnotationsWithArguments
|
||||
return annotations.firstOrNull { it.isMetaSerializableAnnotation }
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
val FirAnnotation.isMetaSerializableAnnotation: Boolean
|
||||
get() = annotationClassSymbol?.hasAnnotation(metaSerializableAnnotationClassId) ?: false
|
||||
|
||||
context(CheckerContext)
|
||||
val ConeKotlinType.serializableWith: ConeKotlinType?
|
||||
get() = customAnnotations.serializableWith ?: toRegularClassSymbol(session)?.serializableWith
|
||||
|
||||
internal val FirBasedSymbol<*>.serializableWith: ConeKotlinType?
|
||||
get() = serializableAnnotation(needArguments = true)?.getKClassArgument(AnnotationParameterNames.WITH)
|
||||
|
||||
internal val List<FirAnnotation>.serializableWith: ConeKotlinType?
|
||||
get() = serializableAnnotation()?.getKClassArgument(AnnotationParameterNames.WITH)
|
||||
|
||||
internal val FirClassSymbol<*>.serializerAnnotation: FirAnnotation?
|
||||
get() = getAnnotationByClassId(SerializationAnnotations.serializerAnnotationClassId)
|
||||
|
||||
// ---------------------- class utils ----------------------
|
||||
internal val FirClassSymbol<*>.serializerForClass: ConeKotlinType?
|
||||
get() = resolvedAnnotationsWithArguments
|
||||
.getAnnotationByClassId(SerializationAnnotations.serializerAnnotationClassId)
|
||||
?.getKClassArgument(AnnotationParameterNames.FOR_CLASS)
|
||||
|
||||
internal val FirClassSymbol<*>.serializerAnnotation: FirAnnotation?
|
||||
get() = getAnnotationByClassId(SerializationAnnotations.serializerAnnotationClassId)
|
||||
|
||||
context(CheckerContext)
|
||||
private val FirAnnotation.annotationClassSymbol: FirRegularClassSymbol?
|
||||
get() = annotationTypeRef.coneType
|
||||
.fullyExpandedType(session)
|
||||
.toRegularClassSymbol(session)
|
||||
|
||||
// ---------------------- class utils ----------------------
|
||||
|
||||
internal val FirClassSymbol<*>.shouldHaveGeneratedMethodsInCompanion: Boolean
|
||||
get() = this.isSerializableObject || this.isSerializableEnum || this.classKind == ClassKind.CLASS && hasSerializableAnnotation || this.isSealedSerializableInterface
|
||||
|
||||
internal val FirClassSymbol<*>.isSerializableObject: Boolean
|
||||
get() = classKind.isObject && hasSerializableAnnotation
|
||||
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.isInternallySerializableObject: Boolean
|
||||
get() = classKind.isObject && hasSerializableAnnotationWithoutArgs
|
||||
get() = classKind.isObject && hasSerializableOrMetaAnnotationWithoutArgs
|
||||
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.isSerializableObject: Boolean
|
||||
get() = classKind.isObject && hasSerializableOrMetaAnnotation
|
||||
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.isSealedSerializableInterface: Boolean
|
||||
get() = classKind.isInterface && rawStatus.modality == Modality.SEALED && hasSerializableAnnotation
|
||||
get() = classKind.isInterface && rawStatus.modality == Modality.SEALED && hasSerializableOrMetaAnnotation
|
||||
|
||||
context(FirSession)
|
||||
val FirClassSymbol<*>.hasSerializableOrMetaAnnotation: Boolean
|
||||
get() = hasSerializableAnnotation || hasMetaSerializableAnnotation
|
||||
|
||||
context(FirSession)
|
||||
val FirClassSymbol<*>.hasMetaSerializableAnnotation: Boolean
|
||||
get() = predicateBasedProvider.matches(FirSerializationPredicates.hasMetaAnnotation, this)
|
||||
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.shouldHaveGeneratedMethodsInCompanion: Boolean
|
||||
get() = isSerializableObject
|
||||
|| isSerializableEnum
|
||||
|| (classKind == ClassKind.CLASS && hasSerializableOrMetaAnnotation)
|
||||
|| isSealedSerializableInterface
|
||||
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.isInternalSerializable: Boolean
|
||||
get() {
|
||||
if (!classKind.isClass) return false
|
||||
return hasSerializableAnnotationWithoutArgs
|
||||
return hasSerializableOrMetaAnnotationWithoutArgs
|
||||
}
|
||||
|
||||
context(FirSession)
|
||||
val FirClassSymbol<*>.hasSerializableOrMetaAnnotationWithoutArgs: Boolean
|
||||
get() = hasSerializableAnnotationWithoutArgs || (!hasSerializableAnnotation && hasMetaSerializableAnnotation)
|
||||
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.isAbstractOrSealedSerializableClass: Boolean
|
||||
get() = isInternalSerializable && (rawStatus.modality == Modality.ABSTRACT || rawStatus.modality == Modality.SEALED)
|
||||
|
||||
internal val FirClassSymbol<*>.isInternallySerializableEnum: Boolean
|
||||
get() = classKind.isEnumClass && hasSerializableAnnotationWithoutArgs
|
||||
|
||||
/**
|
||||
* Check that class is enum and marked by `Serializable` or meta-serializable annotation.
|
||||
*/
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.isSerializableEnum: Boolean
|
||||
get() = classKind.isEnumClass && hasSerializableAnnotation
|
||||
get() = classKind.isEnumClass && hasSerializableOrMetaAnnotation
|
||||
|
||||
/**
|
||||
* Check that class is enum and marked by `Serializable` annotation without serializer argument or meta-serializable annotation.
|
||||
*/
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.isSerializableEnumWithoutArgs: Boolean
|
||||
get() = classKind.isEnumClass && hasSerializableOrMetaAnnotationWithoutArgs
|
||||
|
||||
internal fun FirClassSymbol<*>.isFinalOrOpen(): Boolean {
|
||||
val modality = rawStatus.modality
|
||||
@@ -172,75 +164,30 @@ internal fun FirClassSymbol<*>.isFinalOrOpen(): Boolean {
|
||||
return (modality == null || modality == Modality.FINAL || modality == Modality.OPEN)
|
||||
}
|
||||
|
||||
internal fun FirClassSymbol<*>.getSerializableClassSymbolIfCompanion(session: FirSession): FirClassSymbol<*>? {
|
||||
if (isSerializableObject) return this
|
||||
if (!isCompanion) return null
|
||||
val classDescriptor = (getContainingDeclarationSymbol(session) as? FirClassSymbol<*>) ?: return null
|
||||
if (!classDescriptor.shouldHaveGeneratedMethodsInCompanion) return null
|
||||
return classDescriptor
|
||||
}
|
||||
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
val FirClassSymbol<*>.hasCompanionObjectAsSerializer: Boolean
|
||||
get() = isInternallySerializableObject ||
|
||||
(this as? FirRegularClassSymbol)?.companionObjectSymbol?.serializerForClass == this.defaultType()
|
||||
get() = isInternallySerializableObject || hasCustomSerializerOnCompanion
|
||||
|
||||
fun FirClassSymbol<*>.getSuperClassNotAny(session: FirSession): FirRegularClassSymbol? {
|
||||
return getSuperClassOrAny(session).takeUnless { it.classId == StandardClassIds.Any }
|
||||
}
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
val FirClassSymbol<*>.hasCustomSerializerOnCompanion: Boolean
|
||||
get() = (this as? FirRegularClassSymbol)?.companionObjectSymbol?.serializerForClass != null
|
||||
|
||||
fun FirClassSymbol<*>.getSuperClassOrAny(session: FirSession): FirRegularClassSymbol {
|
||||
return resolvedSuperTypes.firstNotNullOfOrNull { superType ->
|
||||
superType.fullyExpandedType(session)
|
||||
.toRegularClassSymbol(session)
|
||||
?.takeIf { it.classKind == ClassKind.CLASS }
|
||||
} ?: session.builtinTypes.anyType.toRegularClassSymbol(session) ?: error("Symbol for kotlin/Any not found")
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
val FirClassSymbol<*>?.classSerializer: FirClassSymbol<*>?
|
||||
get() {
|
||||
if (this == null) return null
|
||||
// serializer annotation on class?
|
||||
serializableWith?.let { return it.toRegularClassSymbol(session) }
|
||||
// companion object serializer?
|
||||
if (this is FirRegularClassSymbol && hasCompanionObjectAsSerializer) return companionObjectSymbol
|
||||
// can infer @Poly?
|
||||
polymorphicSerializerIfApplicableAutomatically?.let { return it }
|
||||
// default serializable?
|
||||
if (shouldHaveGeneratedSerializer) {
|
||||
// $serializer nested class
|
||||
return unsubstitutedScope(this@CheckerContext)
|
||||
.getSingleClassifier(SerialEntityNames.SERIALIZER_CLASS_NAME) as? FirClassSymbol<*>
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
val FirClassSymbol<*>.polymorphicSerializerIfApplicableAutomatically: FirClassSymbol<*>?
|
||||
get() {
|
||||
val serializerName = when {
|
||||
isInterface -> when (modality) {
|
||||
Modality.SEALED -> SpecialBuiltins.sealedSerializer
|
||||
else -> SpecialBuiltins.polymorphicSerializer
|
||||
}
|
||||
isInternalSerializable -> when (modality) {
|
||||
Modality.SEALED -> SpecialBuiltins.sealedSerializer
|
||||
Modality.ABSTRACT -> SpecialBuiltins.polymorphicSerializer
|
||||
else -> null
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
return serializerName?.let { session.dependencySerializationInfoProvider.getClassFromSerializationPackage(Name.identifier(it)) }
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
context(FirSession)
|
||||
val FirClassSymbol<*>.isEnumWithLegacyGeneratedSerializer: Boolean
|
||||
get() = isInternallySerializableEnum && session.dependencySerializationInfoProvider.useGeneratedEnumSerializer
|
||||
get() = classKind.isEnumClass && dependencySerializationInfoProvider.useGeneratedEnumSerializer && hasSerializableOrMetaAnnotationWithoutArgs
|
||||
|
||||
context(CheckerContext)
|
||||
context(FirSession)
|
||||
val FirClassSymbol<*>.shouldHaveGeneratedSerializer: Boolean
|
||||
get() = (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN)) || isEnumWithLegacyGeneratedSerializer
|
||||
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal fun FirClassSymbol<*>.shouldHaveGeneratedSerializer(useGeneratedEnumSerializer: Boolean): Boolean {
|
||||
return (isInternalSerializable && isFinalOrOpen()) || (useGeneratedEnumSerializer && isSerializableEnumWithoutArgs)
|
||||
}
|
||||
|
||||
// ---------------------- type utils ----------------------
|
||||
|
||||
val ConeKotlinType.isKSerializer: Boolean
|
||||
@@ -259,15 +206,6 @@ fun ConeKotlinType.serializerForType(session: FirSession): ConeKotlinType? {
|
||||
val ConeKotlinType.isTypeParameter: Boolean
|
||||
get() = this is ConeTypeParameterType
|
||||
|
||||
context(CheckerContext)
|
||||
val ConeKotlinType.overriddenSerializer: ConeKotlinType?
|
||||
get() = toRegularClassSymbol(session)?.serializableWith
|
||||
|
||||
context(CheckerContext)
|
||||
context(FirSession)
|
||||
val ConeKotlinType.isGeneratedSerializableObject: Boolean
|
||||
get() = toRegularClassSymbol(session)?.let { it.classKind.isObject && it.hasSerializableOrMetaAnnotationWithoutArgs } ?: false
|
||||
|
||||
// ---------------------- other ----------------------
|
||||
|
||||
val CheckerContext.currentFile: FirFile
|
||||
get() = containingDeclarations.first() as FirFile
|
||||
get() = toRegularClassSymbol(this@FirSession)?.let { it.classKind.isObject && it.hasSerializableOrMetaAnnotationWithoutArgs } ?: false
|
||||
|
||||
+14
-39
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.descriptors.isEnumClass
|
||||
import org.jetbrains.kotlin.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isInlineClass
|
||||
@@ -19,6 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.*
|
||||
@@ -31,6 +33,7 @@ import org.jetbrains.kotlinx.serialization.compiler.fir.services.dependencySeria
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.services.findTypeSerializerOrContextUnchecked
|
||||
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
|
||||
|
||||
object FirSerializationPluginClassChecker : FirClassChecker() {
|
||||
private val JAVA_SERIALIZABLE_ID = ClassId.topLevel(FqName("java.io.Serializable"))
|
||||
@@ -204,9 +207,9 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
if (!classSymbol.hasSerializableOrMetaAnnotation) return false
|
||||
|
||||
|
||||
if (!with(session) { classSymbol.hasSerializableOrMetaAnnotation }) return false
|
||||
|
||||
if (classSymbol.isAnonymousObjectOrInsideIt) {
|
||||
reporter.reportOn(classSymbol.serializableOrMetaAnnotationSource, FirSerializationErrors.ANONYMOUS_OBJECTS_NOT_SUPPORTED)
|
||||
return false
|
||||
@@ -227,13 +230,13 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!classSymbol.hasSerializableOrMetaAnnotationWithoutArgs) {
|
||||
if (!with(session) { classSymbol.hasSerializableOrMetaAnnotationWithoutArgs }) {
|
||||
// defined custom serializer
|
||||
checkClassWithCustomSerializer(classSymbol, reporter)
|
||||
return false
|
||||
}
|
||||
|
||||
if (classSymbol.serializableAnnotationIsUseless) {
|
||||
if (with(session) { classSymbol.serializableAnnotationIsUseless }) {
|
||||
reporter.reportOn(classSymbol.serializableOrMetaAnnotationSource, FirSerializationErrors.SERIALIZABLE_ANNOTATION_IGNORED)
|
||||
return false
|
||||
}
|
||||
@@ -241,7 +244,7 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
|
||||
// check that we can instantiate supertype
|
||||
if (!classSymbol.isEnumClass) { // enums are inherited from java.lang.Enum and can't be inherited from other classes
|
||||
val superClassSymbol = classSymbol.getSuperClassOrAny(session)
|
||||
if (!superClassSymbol.isInternalSerializable) {
|
||||
if (with(session) { !superClassSymbol.isInternalSerializable }) {
|
||||
val noArgConstructorSymbol = superClassSymbol.declarationSymbols.firstOrNull { it is FirConstructorSymbol && it.valueParameterSymbols.isEmpty() }
|
||||
if (noArgConstructorSymbol == null) {
|
||||
reporter.reportOn(classSymbol.serializableOrMetaAnnotationSource, FirSerializationErrors.NON_SERIALIZABLE_PARENT_MUST_HAVE_NOARG_CTOR)
|
||||
@@ -296,9 +299,11 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
private fun buildSerializableProperties(classSymbol: FirClassSymbol<*>, reporter: DiagnosticReporter): FirSerializableProperties? {
|
||||
if (!classSymbol.hasSerializableOrMetaAnnotation) return null
|
||||
if (!classSymbol.isInternalSerializable) return null
|
||||
if (classSymbol.hasCompanionObjectAsSerializer) return null
|
||||
with(session) {
|
||||
if (!classSymbol.hasSerializableOrMetaAnnotation) return null
|
||||
if (!classSymbol.isInternalSerializable) return null
|
||||
if (classSymbol.hasCompanionObjectAsSerializer) return null
|
||||
}
|
||||
|
||||
val properties = session.serializablePropertiesProvider.getSerializablePropertiesForClass(classSymbol)
|
||||
if (!properties.isExternallySerializable) {
|
||||
@@ -487,34 +492,4 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
|
||||
reporter.reportOn(source, FirSerializationErrors.SERIALIZER_NULLABILITY_INCOMPATIBLE, serializerType, classType)
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
private val FirClassSymbol<*>.isSerializableEnumWithMissingSerializer: Boolean
|
||||
get() {
|
||||
if (!isEnumClass) return false
|
||||
if (hasSerializableOrMetaAnnotation) return false
|
||||
if (hasAnySerialAnnotation) return true
|
||||
return collectEnumEntries().any { it.hasAnySerialAnnotation }
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
private val FirClassSymbol<*>.serializableOrMetaAnnotationSource: KtSourceElement?
|
||||
get() {
|
||||
serializableAnnotation(needArguments = false)?.source?.let { return it }
|
||||
metaSerializableAnnotation(needArguments = false)?.source?.let { return it }
|
||||
return null
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
private val FirClassSymbol<*>.serializableAnnotationIsUseless: Boolean
|
||||
get() = !classKind.isEnumClass &&
|
||||
hasSerializableOrMetaAnnotationWithoutArgs &&
|
||||
!isInternalSerializable &&
|
||||
!hasCompanionObjectAsSerializer &&
|
||||
!isSealedSerializableInterface
|
||||
}
|
||||
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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.checkers
|
||||
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.isEnumClass
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.collectEnumEntries
|
||||
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.scopes.getSingleClassifier
|
||||
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.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.customAnnotations
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.serializableWith
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.services.dependencySerializationInfoProvider
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SpecialBuiltins
|
||||
|
||||
// ---------------------- search utils ----------------------
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>?.classSerializer: FirClassSymbol<*>?
|
||||
get() {
|
||||
if (this == null) return null
|
||||
// serializer annotation on class?
|
||||
serializableWith?.let { return it.toRegularClassSymbol(session) }
|
||||
// companion object serializer?
|
||||
if (this is FirRegularClassSymbol && with(session) { hasCompanionObjectAsSerializer }) return companionObjectSymbol
|
||||
// can infer @Poly?
|
||||
polymorphicSerializerIfApplicableAutomatically?.let { return it }
|
||||
// default serializable?
|
||||
if (with(session) { shouldHaveGeneratedSerializer }) {
|
||||
// $serializer nested class
|
||||
return unsubstitutedScope(this@CheckerContext)
|
||||
.getSingleClassifier(SerialEntityNames.SERIALIZER_CLASS_NAME) as? FirClassSymbol<*>
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
val FirClassSymbol<*>.polymorphicSerializerIfApplicableAutomatically: FirClassSymbol<*>?
|
||||
get() {
|
||||
val serializerName = when {
|
||||
isInterface -> when (modality) {
|
||||
Modality.SEALED -> SpecialBuiltins.sealedSerializer
|
||||
else -> SpecialBuiltins.polymorphicSerializer
|
||||
}
|
||||
|
||||
with(session) { isInternalSerializable } -> when (modality) {
|
||||
Modality.SEALED -> SpecialBuiltins.sealedSerializer
|
||||
Modality.ABSTRACT -> SpecialBuiltins.polymorphicSerializer
|
||||
else -> null
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
return serializerName?.let { session.dependencySerializationInfoProvider.getClassFromSerializationPackage(Name.identifier(it)) }
|
||||
}
|
||||
|
||||
// ---------------------- annotation utils ----------------------
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirAnnotation.annotationClassSymbol: FirRegularClassSymbol?
|
||||
get() = annotationTypeRef.coneType
|
||||
.fullyExpandedType(session)
|
||||
.toRegularClassSymbol(session)
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirAnnotation.isMetaSerializableAnnotation: Boolean
|
||||
get() = annotationClassSymbol?.hasAnnotation(SerializationAnnotations.metaSerializableAnnotationClassId) ?: false
|
||||
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal fun FirClassSymbol<*>.metaSerializableAnnotation(needArguments: Boolean): FirAnnotation? {
|
||||
val annotations = if (needArguments) resolvedAnnotationsWithClassIds else resolvedAnnotationsWithArguments
|
||||
return annotations.firstOrNull { it.isMetaSerializableAnnotation }
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.serializableOrMetaAnnotationSource: KtSourceElement?
|
||||
get() {
|
||||
serializableAnnotation(needArguments = false)?.source?.let { return it }
|
||||
metaSerializableAnnotation(needArguments = false)?.source?.let { return it }
|
||||
return null
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirBasedSymbol<*>.hasAnySerialAnnotation: Boolean
|
||||
get() = serialNameValue != null || resolvedAnnotationsWithClassIds.any { it.annotationClassSymbol?.isSerialInfoAnnotation == true }
|
||||
|
||||
// ---------------------- class utils ----------------------
|
||||
|
||||
fun FirClassSymbol<*>.getSuperClassNotAny(session: FirSession): FirRegularClassSymbol? {
|
||||
return getSuperClassOrAny(session).takeUnless { it.classId == StandardClassIds.Any }
|
||||
}
|
||||
|
||||
fun FirClassSymbol<*>.getSuperClassOrAny(session: FirSession): FirRegularClassSymbol {
|
||||
return resolvedSuperTypes.firstNotNullOfOrNull { superType ->
|
||||
superType.fullyExpandedType(session)
|
||||
.toRegularClassSymbol(session)
|
||||
?.takeIf { it.classKind == ClassKind.CLASS }
|
||||
} ?: session.builtinTypes.anyType.toRegularClassSymbol(session) ?: error("Symbol for kotlin/Any not found")
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.isSerializableEnumWithMissingSerializer: Boolean
|
||||
get() {
|
||||
if (!isEnumClass) return false
|
||||
if (with(session) { hasSerializableOrMetaAnnotation }) return false
|
||||
if (hasAnySerialAnnotation) return true
|
||||
return collectEnumEntries().any { it.hasAnySerialAnnotation }
|
||||
}
|
||||
|
||||
context(FirSession)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val FirClassSymbol<*>.serializableAnnotationIsUseless: Boolean
|
||||
get() = !classKind.isEnumClass &&
|
||||
hasSerializableOrMetaAnnotationWithoutArgs &&
|
||||
!isInternalSerializable &&
|
||||
!hasCompanionObjectAsSerializer &&
|
||||
!isSealedSerializableInterface
|
||||
|
||||
// ---------------------- type utils ----------------------
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val ConeKotlinType.serializableWith: ConeKotlinType?
|
||||
get() = customAnnotations.serializableWith ?: toRegularClassSymbol(session)?.serializableWith
|
||||
|
||||
|
||||
context(CheckerContext)
|
||||
@Suppress("IncorrectFormatting") // KTIJ-22227
|
||||
internal val ConeKotlinType.overriddenSerializer: ConeKotlinType?
|
||||
get() = toRegularClassSymbol(session)?.serializableWith
|
||||
|
||||
|
||||
// ---------------------- others ----------------------
|
||||
internal val CheckerContext.currentFile: FirFile
|
||||
get() = containingDeclarations.first() as FirFile
|
||||
+11
-9
@@ -25,7 +25,9 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.serializableWith
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.checkers.classSerializer
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.checkers.currentFile
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.checkers.overriddenSerializer
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
|
||||
|
||||
@@ -116,20 +118,20 @@ fun findTypeSerializer(type: ConeKotlinType): FirClassSymbol<*>? {
|
||||
if (type.isArrayType) {
|
||||
return serializationProvider.getClassFromInternalSerializationPackage(SpecialBuiltins.Names.referenceArraySerializer)
|
||||
}
|
||||
if (type.isGeneratedSerializableObject) {
|
||||
if (with(session) { type.isGeneratedSerializableObject }) {
|
||||
return serializationProvider.getClassFromInternalSerializationPackage(SpecialBuiltins.Names.objectSerializer)
|
||||
}
|
||||
// see if there is a standard serializer
|
||||
val standardSerializer = findStandardKotlinTypeSerializer(type) ?: findEnumTypeSerializer(type)
|
||||
val standardSerializer = with(session) { findStandardKotlinTypeSerializer(type) ?: findEnumTypeSerializer(type) }
|
||||
if (standardSerializer != null) return standardSerializer
|
||||
val symbol = type.toRegularClassSymbol(session) ?: return null
|
||||
if (symbol.isSealedSerializableInterface) {
|
||||
if (with(session) { symbol.isSealedSerializableInterface }) {
|
||||
return serializationProvider.getClassFromSerializationPackage(SpecialBuiltins.Names.polymorphicSerializer)
|
||||
}
|
||||
return symbol.classSerializer // check for serializer defined on the type
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
context(FirSession)
|
||||
fun findStandardKotlinTypeSerializer(type: ConeKotlinType): FirClassSymbol<*>? {
|
||||
val name = when {
|
||||
type.isBoolean -> PrimitiveBuiltins.booleanSerializer
|
||||
@@ -142,15 +144,15 @@ fun findStandardKotlinTypeSerializer(type: ConeKotlinType): FirClassSymbol<*>? {
|
||||
type.isChar -> PrimitiveBuiltins.charSerializer
|
||||
else -> findStandardKotlinTypeSerializerName(type.classId?.asFqNameString())
|
||||
}?.let(Name::identifier) ?: return null
|
||||
val symbolProvider = session.symbolProvider
|
||||
val symbolProvider = symbolProvider
|
||||
return symbolProvider.getClassLikeSymbolByClassId(ClassId(SerializationPackages.internalPackageFqName, name)) as? FirClassSymbol<*>
|
||||
?: symbolProvider.getClassLikeSymbolByClassId(ClassId(SerializationPackages.packageFqName, name)) as? FirClassSymbol<*>
|
||||
}
|
||||
|
||||
context(CheckerContext)
|
||||
context(FirSession)
|
||||
fun findEnumTypeSerializer(type: ConeKotlinType): FirClassSymbol<*>? {
|
||||
val symbol = type.toRegularClassSymbol(session) ?: return null
|
||||
val symbol = type.toRegularClassSymbol(this@FirSession) ?: return null
|
||||
return runIf(symbol.isEnumClass && !symbol.isEnumWithLegacyGeneratedSerializer) {
|
||||
session.symbolProvider.getClassLikeSymbolByClassId(SerializersClassIds.enumSerializerId) as? FirClassSymbol<*>
|
||||
symbolProvider.getClassLikeSymbolByClassId(SerializersClassIds.enumSerializerId) as? FirClassSymbol<*>
|
||||
}
|
||||
}
|
||||
|
||||
+10
-6
@@ -13,17 +13,17 @@ import org.jetbrains.kotlin.fir.caches.createCache
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.caches.getValue
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.correspondingValueParameterFromPrimaryConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableReference
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
|
||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionSessionComponent
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirPropertyFromParameterResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.processAllProperties
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.checkers.getSuperClassNotAny
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.isInternalSerializable
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.ISerializableProperty
|
||||
|
||||
@@ -35,6 +35,10 @@ class FirSerializablePropertiesProvider(session: FirSession) : FirExtensionSessi
|
||||
return cache.getValue(classSymbol)
|
||||
}
|
||||
|
||||
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
|
||||
register(FirSerializationPredicates.hasMetaAnnotation)
|
||||
}
|
||||
|
||||
private fun createSerializableProperties(classSymbol: FirClassSymbol<*>): FirSerializableProperties {
|
||||
val allPropertySymbols = buildList {
|
||||
classSymbol
|
||||
@@ -49,7 +53,7 @@ class FirSerializablePropertiesProvider(session: FirSession) : FirExtensionSessi
|
||||
it to parameterSymbol.hasDefaultValue
|
||||
}.toMap().withDefault { false }
|
||||
|
||||
val isInternalSerializable = classSymbol.isInternalSerializable
|
||||
val isInternalSerializable = with(session) { classSymbol.isInternalSerializable }
|
||||
|
||||
fun isPropertySerializable(propertySymbol: FirPropertySymbol): Boolean {
|
||||
return when {
|
||||
@@ -75,7 +79,7 @@ class FirSerializablePropertiesProvider(session: FirSession) : FirExtensionSessi
|
||||
.let { (fromConstructor, standalone) ->
|
||||
val superClassSymbol = classSymbol.getSuperClassNotAny(session)
|
||||
buildList {
|
||||
if (superClassSymbol != null && superClassSymbol.isInternalSerializable) {
|
||||
if (superClassSymbol != null && with(session) { superClassSymbol.isInternalSerializable }) {
|
||||
addAll(getSerializablePropertiesForClass(superClassSymbol).serializableProperties)
|
||||
}
|
||||
addAll(fromConstructor)
|
||||
@@ -84,7 +88,7 @@ class FirSerializablePropertiesProvider(session: FirSession) : FirExtensionSessi
|
||||
}
|
||||
.let { restoreCorrectOrderFromClassProtoExtension(classSymbol, it) }
|
||||
|
||||
val isExternallySerializable = classSymbol.isInternallySerializableEnum ||
|
||||
val isExternallySerializable = classSymbol.isEnumClass ||
|
||||
primaryConstructorProperties.size == classSymbol.primaryConstructorSymbol()?.valueParameterSymbols?.size
|
||||
|
||||
val (serializableConstructorProperties, serializableStandaloneProperties) = serializableProperties.partition { it.propertySymbol in primaryConstructorProperties }
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
|
||||
// WITH_STDLIB
|
||||
|
||||
@@ -0,0 +1,468 @@
|
||||
FILE: metaSerializable.kt
|
||||
@R|kotlinx/serialization/MetaSerializable|() @R|kotlin/annotation/Target|(allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY|)) public final annotation class MySerializable : R|kotlin/Annotation| {
|
||||
public constructor(): R|MySerializable| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
@R|kotlinx/serialization/MetaSerializable|() @R|kotlin/annotation/Target|(allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY|)) public final annotation class MySerializableWithInfo : R|kotlin/Annotation| {
|
||||
public constructor(value: R|kotlin/Int|, kclass: R|kotlin/reflect/KClass<*>|): R|MySerializableWithInfo| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val value: R|kotlin/Int| = R|<local>/value|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final val kclass: R|kotlin/reflect/KClass<*>| = R|<local>/kclass|
|
||||
public get(): R|kotlin/reflect/KClass<*>|
|
||||
|
||||
}
|
||||
@R|MySerializable|() public final class Project1 : R|kotlin/Any| {
|
||||
public constructor(name: R|kotlin/String|, language: R|kotlin/String|): R|Project1| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val name: R|kotlin/String| = R|<local>/name|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final val language: R|kotlin/String| = R|<local>/language|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<Project1>|
|
||||
|
||||
private constructor(): R|Project1.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<Project1>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|Project1|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|Project1|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|Project1.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public final class Project2 : R|kotlin/Any| {
|
||||
public constructor(name: R|kotlin/String|, language: R|kotlin/String|): R|Project2| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val name: R|kotlin/String| = R|<local>/name|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final val language: R|kotlin/String| = R|<local>/language|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<Project2>|
|
||||
|
||||
private constructor(): R|Project2.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<Project2>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|Project2|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|Project2|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|Project2.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|kotlinx/serialization/Serializable|() public final class Wrapper : R|kotlin/Any| {
|
||||
public constructor(@R|MySerializableWithInfo|(value = Int(234), kclass = <getClass>(Q|kotlin/Int|)) project: R|Project2|): R|Wrapper| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@R|MySerializableWithInfo|(value = Int(234), kclass = <getClass>(Q|kotlin/Int|)) public final val project: R|Project2| = R|<local>/project|
|
||||
public get(): R|Project2|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<Wrapper>|
|
||||
|
||||
private constructor(): R|Wrapper.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<Wrapper>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|Wrapper|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|Wrapper|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|Wrapper.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|kotlinx/serialization/Serializable|() @R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public final class Project3 : R|kotlin/Any| {
|
||||
public constructor(name: R|kotlin/String|, language: R|kotlin/String|): R|Project3| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val name: R|kotlin/String| = R|<local>/name|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final val language: R|kotlin/String| = R|<local>/language|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<Project3>|
|
||||
|
||||
private constructor(): R|Project3.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<Project3>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|Project3|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|Project3|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|Project3.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|kotlinx/serialization/Serializable|(with = <getClass>(Q|MySerializer|)) @R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public final class Project4 : R|kotlin/Any| {
|
||||
public constructor(name: R|kotlin/String|, language: R|kotlin/String|): R|Project4| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val name: R|kotlin/String| = R|<local>/name|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final val language: R|kotlin/String| = R|<local>/language|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<Project4>|
|
||||
|
||||
private constructor(): R|Project4.Companion|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public sealed class TestSealed : R|kotlin/Any| {
|
||||
protected constructor(): R|TestSealed| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public final class A : R|TestSealed| {
|
||||
public constructor(value1: R|kotlin/String|): R|TestSealed.A| {
|
||||
super<R|TestSealed|>()
|
||||
}
|
||||
|
||||
public final val value1: R|kotlin/String| = R|<local>/value1|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<TestSealed.A>|
|
||||
|
||||
private constructor(): R|TestSealed.A.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<TestSealed.A>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|TestSealed.A|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|TestSealed.A|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|TestSealed.A.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public final class B : R|TestSealed| {
|
||||
public constructor(value2: R|kotlin/String|): R|TestSealed.B| {
|
||||
super<R|TestSealed|>()
|
||||
}
|
||||
|
||||
public final val value2: R|kotlin/String| = R|<local>/value2|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<TestSealed.B>|
|
||||
|
||||
private constructor(): R|TestSealed.B.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<TestSealed.B>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|TestSealed.B|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|TestSealed.B|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|TestSealed.B.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<TestSealed>|
|
||||
|
||||
private constructor(): R|TestSealed.Companion|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|MySerializable|() public abstract class TestAbstract : R|kotlin/Any| {
|
||||
public constructor(): R|TestAbstract| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public final class A : R|TestSealed| {
|
||||
public constructor(value1: R|kotlin/String|): R|TestAbstract.A| {
|
||||
super<R|TestSealed|>()
|
||||
}
|
||||
|
||||
public final val value1: R|kotlin/String| = R|<local>/value1|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<TestAbstract.A>|
|
||||
|
||||
private constructor(): R|TestAbstract.A.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<TestAbstract.A>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|TestAbstract.A|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|TestAbstract.A|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|TestAbstract.A.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public final class B : R|TestSealed| {
|
||||
public constructor(value2: R|kotlin/String|): R|TestAbstract.B| {
|
||||
super<R|TestSealed|>()
|
||||
}
|
||||
|
||||
public final val value2: R|kotlin/String| = R|<local>/value2|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<TestAbstract.B>|
|
||||
|
||||
private constructor(): R|TestAbstract.B.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<TestAbstract.B>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|TestAbstract.B|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|TestAbstract.B|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|TestAbstract.B.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<TestAbstract>|
|
||||
|
||||
private constructor(): R|TestAbstract.Companion|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public final enum class TestEnum : R|kotlin/Enum<TestEnum>| {
|
||||
private constructor(): R|TestEnum| {
|
||||
super<R|kotlin/Enum<TestEnum>|>()
|
||||
}
|
||||
|
||||
public final static enum entry Value1: R|TestEnum|
|
||||
public final static enum entry Value2: R|TestEnum|
|
||||
public final static fun values(): R|kotlin/Array<TestEnum>| {
|
||||
}
|
||||
|
||||
public final static fun valueOf(value: R|kotlin/String|): R|TestEnum| {
|
||||
}
|
||||
|
||||
public final static val entries: R|kotlin/enums/EnumEntries<TestEnum>|
|
||||
public get(): R|kotlin/enums/EnumEntries<TestEnum>|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<TestEnum>|
|
||||
|
||||
private constructor(): R|TestEnum.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<TestEnum>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|TestEnum|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|TestEnum|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|TestEnum.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|MySerializableWithInfo|(value = Int(123), kclass = <getClass>(Q|kotlin/String|)) public final object TestObject : R|kotlin/Any| {
|
||||
private constructor(): R|TestObject| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<TestObject>|
|
||||
|
||||
}
|
||||
public final object MySerializer : R|kotlinx/serialization/KSerializer<Project4>| {
|
||||
private constructor(): R|MySerializer| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final override val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor| = R|kotlinx/serialization/descriptors/PrimitiveSerialDescriptor|(String(Project4), Q|kotlinx/serialization/descriptors/PrimitiveKind.STRING|)
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final override fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|Project4|): R|kotlin/Unit| {
|
||||
^serialize R|<local>/encoder|.R|kotlinx/serialization/encoding/Encoder.encodeString|(<strcat>(R|<local>/value|.R|/Project4.name|, String(:), R|<local>/value|.R|/Project4.language|))
|
||||
}
|
||||
|
||||
public final override fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|Project4| {
|
||||
lval params: R|kotlin/collections/List<kotlin/String>| = R|<local>/decoder|.R|kotlinx/serialization/encoding/Decoder.decodeString|().R|kotlin/text/split|(vararg(Char(:)))
|
||||
^deserialize R|/Project4.Project4|(R|<local>/params|.R|SubstitutionOverride<kotlin/collections/List.get: R|kotlin/String|>|(Int(0)), R|<local>/params|.R|SubstitutionOverride<kotlin/collections/List.get: R|kotlin/String|>|(Int(1)))
|
||||
}
|
||||
|
||||
}
|
||||
public final fun testMetaSerializable(): R|kotlin/Unit| {
|
||||
lval string: R|kotlin/String| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.encodeToString|<R|Project1|>(Q|Project1|.R|/Project1.Companion.serializer|(), R|/Project1.Project1|(String(name), String(lang)))
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String({"name":"name","language":"lang"}), R|<local>/string|)
|
||||
lval reconstructed: R|Project1| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.decodeFromString|<R|Project1|>(Q|Project1|.R|/Project1.Companion.serializer|(), R|<local>/string|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String(name), R|<local>/reconstructed|.R|/Project1.name|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String(lang), R|<local>/reconstructed|.R|/Project1.language|)
|
||||
}
|
||||
public final fun testMetaSerializableWithInfo(): R|kotlin/Unit| {
|
||||
lval string: R|kotlin/String| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.encodeToString|<R|Project2|>(Q|Project2|.R|/Project2.Companion.serializer|(), R|/Project2.Project2|(String(name), String(lang)))
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String({"name":"name","language":"lang"}), R|<local>/string|)
|
||||
lval reconstructed: R|Project2| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.decodeFromString|<R|Project2|>(Q|Project2|.R|/Project2.Companion.serializer|(), R|<local>/string|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String(name), R|<local>/reconstructed|.R|/Project2.name|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String(lang), R|<local>/reconstructed|.R|/Project2.language|)
|
||||
lval info: R|MySerializableWithInfo| = Q|Project2|.R|/Project2.Companion.serializer|().R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|.R|kotlinx/serialization/descriptors/SerialDescriptor.annotations|.R|kotlin/collections/filterIsInstance|<R|MySerializableWithInfo|>().R|kotlin/collections/first|<R|MySerializableWithInfo|>()
|
||||
R|kotlin/test/assertEquals|<R|kotlin/Int|>(Int(123), R|<local>/info|.R|/MySerializableWithInfo.value|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/reflect/KClass<out kotlin/Any>|>(<getClass>(Q|kotlin/String|), R|<local>/info|.R|/MySerializableWithInfo.kclass|)
|
||||
}
|
||||
public final fun testMetaSerializableOnProperty(): R|kotlin/Unit| {
|
||||
lval info: R|MySerializableWithInfo| = Q|Wrapper|.R|/Wrapper.Companion.serializer|().R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|.R|kotlinx/serialization/descriptors/SerialDescriptor.getElementAnnotations|(Int(0)).R|kotlin/collections/filterIsInstance|<R|MySerializableWithInfo|>().R|kotlin/collections/first|<R|MySerializableWithInfo|>()
|
||||
R|kotlin/test/assertEquals|<R|kotlin/Int|>(Int(234), R|<local>/info|.R|/MySerializableWithInfo.value|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/reflect/KClass<out kotlin/Any>|>(<getClass>(Q|kotlin/Int|), R|<local>/info|.R|/MySerializableWithInfo.kclass|)
|
||||
}
|
||||
public final fun testSerializableAndMetaAnnotation(): R|kotlin/Unit| {
|
||||
lval string: R|kotlin/String| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.encodeToString|<R|Project3|>(Q|Project3|.R|/Project3.Companion.serializer|(), R|/Project3.Project3|(String(name), String(lang)))
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String({"name":"name","language":"lang"}), R|<local>/string|)
|
||||
lval reconstructed: R|Project3| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.decodeFromString|<R|Project3|>(Q|Project3|.R|/Project3.Companion.serializer|(), R|<local>/string|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String(name), R|<local>/reconstructed|.R|/Project3.name|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String(lang), R|<local>/reconstructed|.R|/Project3.language|)
|
||||
lval info: R|MySerializableWithInfo| = Q|Project3|.R|/Project3.Companion.serializer|().R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|.R|kotlinx/serialization/descriptors/SerialDescriptor.annotations|.R|kotlin/collections/filterIsInstance|<R|MySerializableWithInfo|>().R|kotlin/collections/first|<R|MySerializableWithInfo|>()
|
||||
R|kotlin/test/assertEquals|<R|kotlin/Int|>(Int(123), R|<local>/info|.R|/MySerializableWithInfo.value|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/reflect/KClass<out kotlin/Any>|>(<getClass>(Q|kotlin/String|), R|<local>/info|.R|/MySerializableWithInfo.kclass|)
|
||||
}
|
||||
public final fun testCustomSerializerAndMetaAnnotation(): R|kotlin/Unit| {
|
||||
lval string: R|kotlin/String| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.encodeToString|<R|Project4|>(Q|Project4|.R|/Project4.Companion.serializer|(), R|/Project4.Project4|(String(name), String(lang)))
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String(name:lang), R|<local>/string|)
|
||||
lval reconstructed: R|Project4| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.decodeFromString|<R|Project4|>(Q|Project4|.R|/Project4.Companion.serializer|(), R|<local>/string|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String(name), R|<local>/reconstructed|.R|/Project4.name|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/String|>(String(lang), R|<local>/reconstructed|.R|/Project4.language|)
|
||||
}
|
||||
public final fun testSealed(): R|kotlin/Unit| {
|
||||
lval serializerA: R|kotlinx/serialization/KSerializer<TestSealed.A>| = Q|TestSealed.A|.R|/TestSealed.A.Companion.serializer|()
|
||||
lval serializerB: R|kotlinx/serialization/KSerializer<TestSealed.B>| = Q|TestSealed.B|.R|/TestSealed.B.Companion.serializer|()
|
||||
R|kotlin/test/assertNotNull|<R|kotlinx/serialization/KSerializer<TestSealed.A>|>(R|<local>/serializerA|)
|
||||
R|kotlin/test/assertNotNull|<R|kotlinx/serialization/KSerializer<TestSealed.B>|>(R|<local>/serializerB|)
|
||||
lval infoA: R|MySerializableWithInfo| = R|<local>/serializerA|.R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|.R|kotlinx/serialization/descriptors/SerialDescriptor.annotations|.R|kotlin/collections/filterIsInstance|<R|MySerializableWithInfo|>().R|kotlin/collections/first|<R|MySerializableWithInfo|>()
|
||||
lval infoB: R|MySerializableWithInfo| = R|<local>/serializerB|.R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|.R|kotlinx/serialization/descriptors/SerialDescriptor.annotations|.R|kotlin/collections/filterIsInstance|<R|MySerializableWithInfo|>().R|kotlin/collections/first|<R|MySerializableWithInfo|>()
|
||||
R|kotlin/test/assertEquals|<R|kotlin/Int|>(Int(123), R|<local>/infoA|.R|/MySerializableWithInfo.value|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/reflect/KClass<out kotlin/Any>|>(<getClass>(Q|kotlin/String|), R|<local>/infoA|.R|/MySerializableWithInfo.kclass|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/Int|>(Int(123), R|<local>/infoB|.R|/MySerializableWithInfo.value|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/reflect/KClass<out kotlin/Any>|>(<getClass>(Q|kotlin/String|), R|<local>/infoB|.R|/MySerializableWithInfo.kclass|)
|
||||
}
|
||||
public final fun testAbstract(): R|kotlin/Unit| {
|
||||
lval serializerA: R|kotlinx/serialization/KSerializer<TestAbstract.A>| = Q|TestAbstract.A|.R|/TestAbstract.A.Companion.serializer|()
|
||||
lval serializerB: R|kotlinx/serialization/KSerializer<TestAbstract.B>| = Q|TestAbstract.B|.R|/TestAbstract.B.Companion.serializer|()
|
||||
R|kotlin/test/assertNotNull|<R|kotlinx/serialization/KSerializer<TestAbstract.A>|>(R|<local>/serializerA|)
|
||||
R|kotlin/test/assertNotNull|<R|kotlinx/serialization/KSerializer<TestAbstract.B>|>(R|<local>/serializerB|)
|
||||
lval infoA: R|MySerializableWithInfo| = R|<local>/serializerA|.R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|.R|kotlinx/serialization/descriptors/SerialDescriptor.annotations|.R|kotlin/collections/filterIsInstance|<R|MySerializableWithInfo|>().R|kotlin/collections/first|<R|MySerializableWithInfo|>()
|
||||
lval infoB: R|MySerializableWithInfo| = R|<local>/serializerB|.R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|.R|kotlinx/serialization/descriptors/SerialDescriptor.annotations|.R|kotlin/collections/filterIsInstance|<R|MySerializableWithInfo|>().R|kotlin/collections/first|<R|MySerializableWithInfo|>()
|
||||
R|kotlin/test/assertEquals|<R|kotlin/Int|>(Int(123), R|<local>/infoA|.R|/MySerializableWithInfo.value|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/reflect/KClass<out kotlin/Any>|>(<getClass>(Q|kotlin/String|), R|<local>/infoA|.R|/MySerializableWithInfo.kclass|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/Int|>(Int(123), R|<local>/infoB|.R|/MySerializableWithInfo.value|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/reflect/KClass<out kotlin/Any>|>(<getClass>(Q|kotlin/String|), R|<local>/infoB|.R|/MySerializableWithInfo.kclass|)
|
||||
}
|
||||
public final fun testEnum(): R|kotlin/Unit| {
|
||||
lval serializer: R|kotlinx/serialization/KSerializer<TestEnum>| = Q|TestEnum|.R|/TestEnum.Companion.serializer|()
|
||||
R|kotlin/test/assertNotNull|<R|kotlinx/serialization/KSerializer<TestEnum>|>(R|<local>/serializer|)
|
||||
lval info: R|MySerializableWithInfo| = R|<local>/serializer|.R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|.R|kotlinx/serialization/descriptors/SerialDescriptor.annotations|.R|kotlin/collections/filterIsInstance|<R|MySerializableWithInfo|>().R|kotlin/collections/first|<R|MySerializableWithInfo|>()
|
||||
R|kotlin/test/assertEquals|<R|kotlin/Int|>(Int(123), R|<local>/info|.R|/MySerializableWithInfo.value|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/reflect/KClass<out kotlin/Any>|>(<getClass>(Q|kotlin/String|), R|<local>/info|.R|/MySerializableWithInfo.kclass|)
|
||||
}
|
||||
public final fun testObject(): R|kotlin/Unit| {
|
||||
lval serializer: R|kotlinx/serialization/KSerializer<TestObject>| = Q|TestObject|.R|/TestObject.serializer|()
|
||||
R|kotlin/test/assertNotNull|<R|kotlinx/serialization/KSerializer<TestObject>|>(R|<local>/serializer|)
|
||||
lval info: R|MySerializableWithInfo| = R|<local>/serializer|.R|SubstitutionOverride<kotlinx/serialization/KSerializer.descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|>|.R|kotlinx/serialization/descriptors/SerialDescriptor.annotations|.R|kotlin/collections/filterIsInstance|<R|MySerializableWithInfo|>().R|kotlin/collections/first|<R|MySerializableWithInfo|>()
|
||||
R|kotlin/test/assertEquals|<R|kotlin/Int|>(Int(123), R|<local>/info|.R|/MySerializableWithInfo.value|)
|
||||
R|kotlin/test/assertEquals|<R|kotlin/reflect/KClass<out kotlin/Any>|>(<getClass>(Q|kotlin/String|), R|<local>/info|.R|/MySerializableWithInfo.kclass|)
|
||||
}
|
||||
public final fun box(): R|kotlin/String| {
|
||||
R|/testMetaSerializable|()
|
||||
R|/testMetaSerializableWithInfo|()
|
||||
R|/testMetaSerializableOnProperty|()
|
||||
R|/testSealed|()
|
||||
R|/testAbstract|()
|
||||
R|/testEnum|()
|
||||
R|/testObject|()
|
||||
^box String(OK)
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.encoding.*
|
||||
import kotlinx.serialization.descriptors.*
|
||||
import kotlinx.serialization.json.*
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.test.*
|
||||
|
||||
@MetaSerializable
|
||||
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
|
||||
annotation class MySerializable
|
||||
|
||||
@MetaSerializable
|
||||
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
|
||||
annotation class MySerializableWithInfo(
|
||||
val value: Int,
|
||||
val kclass: KClass<*>
|
||||
)
|
||||
|
||||
@MySerializable
|
||||
class Project1(val name: String, val language: String)
|
||||
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
class Project2(val name: String, val language: String)
|
||||
|
||||
@Serializable
|
||||
class Wrapper(
|
||||
@MySerializableWithInfo(234, Int::class) val project: Project2
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
class Project3(val name: String, val language: String)
|
||||
|
||||
@Serializable(with = MySerializer::class)
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
class Project4(val name: String, val language: String)
|
||||
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
sealed class TestSealed {
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
class A(val value1: String) : TestSealed()
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
class B(val value2: String) : TestSealed()
|
||||
}
|
||||
|
||||
@MySerializable
|
||||
abstract class TestAbstract {
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
class A(val value1: String) : TestSealed()
|
||||
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
class B(val value2: String) : TestSealed()
|
||||
}
|
||||
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
enum class TestEnum { Value1, Value2 }
|
||||
|
||||
@MySerializableWithInfo(123, String::class)
|
||||
object TestObject
|
||||
|
||||
object MySerializer : KSerializer<Project4> {
|
||||
|
||||
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Project4", PrimitiveKind.STRING)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Project4) = encoder.encodeString("${value.name}:${value.language}")
|
||||
|
||||
override fun deserialize(decoder: Decoder): Project4 {
|
||||
val params = decoder.decodeString().split(':')
|
||||
return Project4(params[0], params[1])
|
||||
}
|
||||
}
|
||||
|
||||
fun testMetaSerializable() {
|
||||
val string = Json.encodeToString(Project1.serializer(), Project1("name", "lang"))
|
||||
assertEquals("""{"name":"name","language":"lang"}""", string)
|
||||
|
||||
val reconstructed = Json.decodeFromString(Project1.serializer(), string)
|
||||
assertEquals("name", reconstructed.name)
|
||||
assertEquals("lang", reconstructed.language)
|
||||
}
|
||||
|
||||
fun testMetaSerializableWithInfo() {
|
||||
val string = Json.encodeToString(Project2.serializer(), Project2("name", "lang"))
|
||||
assertEquals("""{"name":"name","language":"lang"}""", string)
|
||||
|
||||
val reconstructed = Json.decodeFromString(Project2.serializer(), string)
|
||||
assertEquals("name", reconstructed.name)
|
||||
assertEquals("lang", reconstructed.language)
|
||||
|
||||
val info = Project2.serializer().descriptor.annotations.filterIsInstance<MySerializableWithInfo>().first()
|
||||
assertEquals(123, info.value)
|
||||
assertEquals(String::class, info.kclass)
|
||||
}
|
||||
|
||||
fun testMetaSerializableOnProperty() {
|
||||
val info = Wrapper.serializer().descriptor.getElementAnnotations(0).filterIsInstance<MySerializableWithInfo>().first()
|
||||
assertEquals(234, info.value)
|
||||
assertEquals(Int::class, info.kclass)
|
||||
}
|
||||
|
||||
fun testSerializableAndMetaAnnotation() {
|
||||
val string = Json.encodeToString(Project3.serializer(), Project3("name", "lang"))
|
||||
assertEquals("""{"name":"name","language":"lang"}""", string)
|
||||
|
||||
val reconstructed = Json.decodeFromString(Project3.serializer(), string)
|
||||
assertEquals("name", reconstructed.name)
|
||||
assertEquals("lang", reconstructed.language)
|
||||
|
||||
val info = Project3.serializer().descriptor.annotations.filterIsInstance<MySerializableWithInfo>().first()
|
||||
assertEquals(123, info.value)
|
||||
assertEquals(String::class, info.kclass)
|
||||
}
|
||||
|
||||
fun testCustomSerializerAndMetaAnnotation() {
|
||||
val string = Json.encodeToString(Project4.serializer(), Project4("name", "lang"))
|
||||
assertEquals("""name:lang""", string)
|
||||
|
||||
val reconstructed = Json.decodeFromString(Project4.serializer(), string)
|
||||
assertEquals("name", reconstructed.name)
|
||||
assertEquals("lang", reconstructed.language)
|
||||
}
|
||||
|
||||
fun testSealed() {
|
||||
val serializerA = TestSealed.A.serializer()
|
||||
val serializerB = TestSealed.B.serializer()
|
||||
assertNotNull(serializerA)
|
||||
assertNotNull(serializerB)
|
||||
|
||||
val infoA = serializerA.descriptor.annotations.filterIsInstance<MySerializableWithInfo>().first()
|
||||
val infoB = serializerB.descriptor.annotations.filterIsInstance<MySerializableWithInfo>().first()
|
||||
assertEquals(123, infoA.value)
|
||||
assertEquals(String::class, infoA.kclass)
|
||||
assertEquals(123, infoB.value)
|
||||
assertEquals(String::class, infoB.kclass)
|
||||
}
|
||||
|
||||
fun testAbstract() {
|
||||
val serializerA = TestAbstract.A.serializer()
|
||||
val serializerB = TestAbstract.B.serializer()
|
||||
assertNotNull(serializerA)
|
||||
assertNotNull(serializerB)
|
||||
|
||||
val infoA = serializerA.descriptor.annotations.filterIsInstance<MySerializableWithInfo>().first()
|
||||
val infoB = serializerB.descriptor.annotations.filterIsInstance<MySerializableWithInfo>().first()
|
||||
assertEquals(123, infoA.value)
|
||||
assertEquals(String::class, infoA.kclass)
|
||||
assertEquals(123, infoB.value)
|
||||
assertEquals(String::class, infoB.kclass)
|
||||
}
|
||||
|
||||
fun testEnum() {
|
||||
val serializer = TestEnum.serializer()
|
||||
assertNotNull(serializer)
|
||||
|
||||
val info = serializer.descriptor.annotations.filterIsInstance<MySerializableWithInfo>().first()
|
||||
assertEquals(123, info.value)
|
||||
assertEquals(String::class, info.kclass)
|
||||
}
|
||||
|
||||
fun testObject() {
|
||||
val serializer = TestObject.serializer()
|
||||
assertNotNull(serializer)
|
||||
|
||||
val info = serializer.descriptor.annotations.filterIsInstance<MySerializableWithInfo>().first()
|
||||
assertEquals(123, info.value)
|
||||
assertEquals(String::class, info.kclass)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
testMetaSerializable()
|
||||
testMetaSerializableWithInfo()
|
||||
testMetaSerializableOnProperty()
|
||||
testSealed()
|
||||
testAbstract()
|
||||
testEnum()
|
||||
testObject()
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -157,6 +157,12 @@ public class SerializationFirBlackBoxTestGenerated extends AbstractSerialization
|
||||
runTest("plugins/kotlinx-serialization/testData/firMembers/inlineClasses.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("metaSerializable.kt")
|
||||
public void testMetaSerializable() throws Exception {
|
||||
runTest("plugins/kotlinx-serialization/testData/firMembers/metaSerializable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleProperties.kt")
|
||||
public void testMultipleProperties() throws Exception {
|
||||
|
||||
+6
@@ -180,6 +180,12 @@ public class SerializationFirDiagnosticTestGenerated extends AbstractSerializati
|
||||
runTest("plugins/kotlinx-serialization/testData/firMembers/inlineClasses.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("metaSerializable.kt")
|
||||
public void testMetaSerializable() throws Exception {
|
||||
runTest("plugins/kotlinx-serialization/testData/firMembers/metaSerializable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleProperties.kt")
|
||||
public void testMultipleProperties() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user