Skip to content

Commit 31ce0e9

Browse files
committed
Introduce @SealedSerializationApi annotation
to be used with @SubclassOptInRequired. This annotation allows for even more fine-grained API marking. We now can designate APIs as public for use, but closed for implementation — the case for SerialDescriptor, which is a non-sealed interface for technical reasons.
1 parent d317f5d commit 31ce0e9

File tree

11 files changed

+69
-33
lines changed

11 files changed

+69
-33
lines changed

buildSrc/src/main/kotlin/source-sets-conventions.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ kotlin {
6868
progressiveMode = true
6969

7070
optIn("kotlin.ExperimentalMultiplatform")
71+
optIn("kotlin.ExperimentalSubclassOptIn")
7172
optIn("kotlinx.serialization.InternalSerializationApi")
73+
optIn("kotlinx.serialization.SealedSerializationApi")
7274
}
7375
}
7476

@@ -112,6 +114,7 @@ kotlin {
112114
sourceSets.matching({ it.name.contains("Test") }).configureEach {
113115
languageSettings {
114116
optIn("kotlinx.serialization.InternalSerializationApi")
117+
optIn("kotlinx.serialization.SealedSerializationApi")
115118
optIn("kotlinx.serialization.ExperimentalSerializationApi")
116119
}
117120
}

core/api/kotlinx-serialization-core.api

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ public final class kotlinx/serialization/SealedClassSerializer : kotlinx/seriali
8686
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
8787
}
8888

89+
public abstract interface annotation class kotlinx/serialization/SealedSerializationApi : java/lang/annotation/Annotation {
90+
}
91+
8992
public abstract interface class kotlinx/serialization/SerialFormat {
9093
public abstract fun getSerializersModule ()Lkotlinx/serialization/modules/SerializersModule;
9194
}

core/api/kotlinx-serialization-core.klib.api

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ open annotation class kotlinx.serialization/Required : kotlin/Annotation { // ko
6161
constructor <init>() // kotlinx.serialization/Required.<init>|<init>(){}[0]
6262
}
6363

64+
open annotation class kotlinx.serialization/SealedSerializationApi : kotlin/Annotation { // kotlinx.serialization/SealedSerializationApi|null[0]
65+
constructor <init>() // kotlinx.serialization/SealedSerializationApi.<init>|<init>(){}[0]
66+
}
67+
6468
open annotation class kotlinx.serialization/SerialInfo : kotlin/Annotation { // kotlinx.serialization/SerialInfo|null[0]
6569
constructor <init>() // kotlinx.serialization/SerialInfo.<init>|<init>(){}[0]
6670
}

core/commonMain/src/kotlinx/serialization/Annotations.kt

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -347,33 +347,3 @@ public annotation class Polymorphic
347347
@Target(AnnotationTarget.CLASS)
348348
@Retention(AnnotationRetention.RUNTIME)
349349
public annotation class KeepGeneratedSerializer
350-
351-
/**
352-
* Marks declarations that are still **experimental** in kotlinx.serialization, which means that the design of the
353-
* corresponding declarations has open issues which may (or may not) lead to their changes in the future.
354-
* Roughly speaking, there is a chance that those declarations will be deprecated in the near future or
355-
* the semantics of their behavior may change in some way that may break some code.
356-
*
357-
* By default, the following categories of API are experimental:
358-
*
359-
* * Writing 3rd-party serialization formats
360-
* * Writing non-trivial custom serializers
361-
* * Implementing [SerialDescriptor] interfaces
362-
* * Not-yet-stable serialization formats that require additional polishing
363-
*/
364-
@MustBeDocumented
365-
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS)
366-
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
367-
public annotation class ExperimentalSerializationApi
368-
369-
/**
370-
* Public API marked with this annotation is effectively **internal**, which means
371-
* it should not be used outside of `kotlinx.serialization`.
372-
* Signature, semantics, source and binary compatibilities are not guaranteed for this API
373-
* and will be changed without any warnings or migration aids.
374-
* If you cannot avoid using internal API to solve your problem, please report your use-case to serialization's issue tracker.
375-
*/
376-
@MustBeDocumented
377-
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS)
378-
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
379-
public annotation class InternalSerializationApi
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2017-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.serialization
6+
7+
import kotlinx.serialization.descriptors.*
8+
9+
/**
10+
* Marks declarations that are still **experimental** in kotlinx.serialization, which means that the design of the
11+
* corresponding declarations has open issues which may (or may not) lead to their changes in the future.
12+
* Roughly speaking, there is a chance that those declarations will be deprecated in the near future or
13+
* the semantics of their behavior may change in some way that may break some code.
14+
*
15+
* By default, the following categories of API are experimental:
16+
*
17+
* * Writing 3rd-party serialization formats
18+
* * Writing non-trivial custom serializers
19+
* * Implementing [SerialDescriptor] interfaces
20+
* * Not-yet-stable serialization formats that require additional polishing
21+
*/
22+
@MustBeDocumented
23+
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS)
24+
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
25+
public annotation class ExperimentalSerializationApi
26+
27+
/**
28+
* Public API marked with this annotation is effectively **internal**, which means
29+
* it should not be used outside of `kotlinx.serialization`.
30+
* Signature, semantics, source and binary compatibilities are not guaranteed for this API
31+
* and will be changed without any warnings or migration aids.
32+
* If you cannot avoid using internal API to solve your problem, please report your use-case to serialization's issue tracker.
33+
*/
34+
@MustBeDocumented
35+
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS)
36+
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
37+
public annotation class InternalSerializationApi
38+
39+
/**
40+
* Marks interfaces and non-final classes that can be freely referenced in users' code but should not be
41+
* implemented or inherited. Such declarations are effectively `sealed` and do not have this modifier purely for technical reasons.
42+
*
43+
* kotlinx.serialization library provides compatibility guarantees for existing signatures of such classes;
44+
* however, new functions or properties can be added to them in any release.
45+
*/
46+
@MustBeDocumented
47+
@Target() // no direct targets, only argument to @SubclassOptInRequired
48+
@RequiresOptIn(message = "This class or interface should not be inherited/implemented outside of kotlinx.serialization library. " +
49+
"Note it is still permitted to use it directly. Read its documentation about inheritance for details.", level = RequiresOptIn.Level.ERROR)
50+
public annotation class SealedSerializationApi
51+

core/commonMain/src/kotlinx/serialization/descriptors/SerialDescriptor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ import kotlinx.serialization.encoding.*
142142
* might be added to this interface when kotlinx.serialization adds support for new Kotlin features.
143143
* This interface is safe to use and construct via [buildClassSerialDescriptor], [PrimitiveSerialDescriptor], and `SerialDescriptor` factory function.
144144
*/
145+
@SubclassOptInRequired(SealedSerializationApi::class)
145146
public interface SerialDescriptor {
146147
/**
147148
* Serial name of the descriptor that identifies a pair of the associated serializer and target class.

formats/cbor/commonMain/src/kotlinx/serialization/cbor/CborDecoder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ import kotlinx.serialization.encoding.*
2525
* ```
2626
*/
2727
@ExperimentalSerializationApi
28+
@SubclassOptInRequired(SealedSerializationApi::class)
2829
public interface CborDecoder : Decoder {
2930
/**
3031
* Exposes the current [Cbor] instance and all its configuration flags. Useful for low-level custom serializers.
3132
*/
3233
public val cbor: Cbor
33-
}
34+
}

formats/cbor/commonMain/src/kotlinx/serialization/cbor/CborEncoder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ import kotlinx.serialization.encoding.*
2525
* ```
2626
*/
2727
@ExperimentalSerializationApi
28+
@SubclassOptInRequired(SealedSerializationApi::class)
2829
public interface CborEncoder : Encoder {
2930
/**
3031
* Exposes the current [Cbor] instance and all its configuration flags. Useful for low-level custom serializers.
3132
*/
3233
public val cbor: Cbor
33-
}
34+
}

formats/json/commonMain/src/kotlinx/serialization/json/JsonDecoder.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import kotlinx.serialization.descriptors.*
5151
* Accepting this interface in your API methods, casting [Decoder] to [JsonDecoder] and invoking its
5252
* methods is considered stable.
5353
*/
54+
@SubclassOptInRequired(SealedSerializationApi::class)
5455
public interface JsonDecoder : Decoder, CompositeDecoder {
5556
/**
5657
* An instance of the current [Json].

formats/json/commonMain/src/kotlinx/serialization/json/JsonEncoder.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
package kotlinx.serialization.json
66

7+
import kotlinx.serialization.*
78
import kotlinx.serialization.encoding.*
89

910
/**
@@ -49,6 +50,7 @@ import kotlinx.serialization.encoding.*
4950
* Accepting this interface in your API methods, casting [Encoder] to [JsonEncoder] and invoking its
5051
* methods is considered stable.
5152
*/
53+
@SubclassOptInRequired(SealedSerializationApi::class)
5254
public interface JsonEncoder : Encoder, CompositeEncoder {
5355
/**
5456
* An instance of the current [Json].

0 commit comments

Comments
 (0)