Correctly handle @Repeatable @SerialInfo annotations on classes

that were affected by deduplication of inherited serial info annotations.

Prohibit combination of @InheritableSerialInfo and @Repeatable.

Fixes https://github.com/Kotlin/kotlinx.serialization/issues/2099
This commit is contained in:
Leonid Startsev
2023-03-17 16:57:31 +01:00
committed by Space Team
parent 8b12b3f18d
commit 6ee20574e1
13 changed files with 125 additions and 4 deletions
@@ -46,6 +46,7 @@ object FirSerializationErrors {
val INCONSISTENT_INHERITABLE_SERIALINFO by error2<PsiElement, ConeKotlinType, ConeKotlinType>()
val META_SERIALIZABLE_NOT_APPLICABLE by error0<PsiElement>()
val INHERITABLE_SERIALINFO_CANT_BE_REPEATABLE by error0<PsiElement>()
val EXTERNAL_SERIALIZER_USELESS by warning1<PsiElement, FirClassSymbol<*>>()
val EXTERNAL_CLASS_NOT_SERIALIZABLE by error2<PsiElement, FirClassSymbol<*>, ConeKotlinType>()
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.fir.analysis.checkers.containsRepeatableAnnotation
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.isSingleFieldValueClass
@@ -46,6 +47,7 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
with(context) {
val classSymbol = declaration.symbol
checkMetaSerializableApplicable(classSymbol, reporter)
checkInheritableSerialInfoNotRepeatable(classSymbol, reporter)
checkEnum(classSymbol, reporter)
checkExternalSerializer(classSymbol, reporter)
if (!canBeSerializedInternally(classSymbol, reporter)) return
@@ -71,6 +73,16 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
reporter.reportOn(anno.source, FirSerializationErrors.META_SERIALIZABLE_NOT_APPLICABLE)
}
context(CheckerContext)
private fun checkInheritableSerialInfoNotRepeatable(classSymbol: FirClassSymbol<out FirClass>, reporter: DiagnosticReporter) {
if (classSymbol.classKind != ClassKind.ANNOTATION_CLASS) return
if (!classSymbol.containsRepeatableAnnotation(session)) return
val anno = classSymbol.resolvedAnnotationsWithClassIds
.find { it.toAnnotationClassId(session) == SerializationAnnotations.inheritableSerialInfoClassId }
?: return
reporter.reportOn(anno.source, FirSerializationErrors.INHERITABLE_SERIALINFO_CANT_BE_REPEATABLE)
}
context(CheckerContext)
@Suppress("IncorrectFormatting") // KTIJ-22227
private fun checkExternalSerializer(classSymbol: FirClassSymbol<*>, reporter: DiagnosticReporter) {
@@ -155,6 +155,10 @@ object KtDefaultErrorMessagesSerialization : BaseDiagnosticRendererFactory() {
FirSerializationErrors.META_SERIALIZABLE_NOT_APPLICABLE,
"@MetaSerializable annotation can be used only on top-level annotation classes."
)
put(
FirSerializationErrors.INHERITABLE_SERIALINFO_CANT_BE_REPEATABLE,
"Repeatable serial info annotations can not be inheritable. Either remove @Repeatable or use a regular @SerialInfo annotation."
)
put(
FirSerializationErrors.EXTERNAL_SERIALIZER_USELESS,