Skip to content

Commit

Permalink
Introduce @SealedSerializationApi annotation
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sandwwraith committed Oct 9, 2024
1 parent ada6ab1 commit 6de55d5
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 33 deletions.
3 changes: 3 additions & 0 deletions buildSrc/src/main/kotlin/source-sets-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ kotlin {
progressiveMode = true

optIn("kotlin.ExperimentalMultiplatform")
optIn("kotlin.ExperimentalSubclassOptIn")
optIn("kotlinx.serialization.InternalSerializationApi")
optIn("kotlinx.serialization.SealedSerializationApi")
}
}

Expand Down Expand Up @@ -112,6 +114,7 @@ kotlin {
sourceSets.matching({ it.name.contains("Test") }).configureEach {
languageSettings {
optIn("kotlinx.serialization.InternalSerializationApi")
optIn("kotlinx.serialization.SealedSerializationApi")
optIn("kotlinx.serialization.ExperimentalSerializationApi")
}
}
Expand Down
3 changes: 3 additions & 0 deletions core/api/kotlinx-serialization-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ public final class kotlinx/serialization/SealedClassSerializer : kotlinx/seriali
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
}

public abstract interface annotation class kotlinx/serialization/SealedSerializationApi : java/lang/annotation/Annotation {
}

public abstract interface class kotlinx/serialization/SerialFormat {
public abstract fun getSerializersModule ()Lkotlinx/serialization/modules/SerializersModule;
}
Expand Down
4 changes: 4 additions & 0 deletions core/api/kotlinx-serialization-core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ open annotation class kotlinx.serialization/Required : kotlin/Annotation { // ko
constructor <init>() // kotlinx.serialization/Required.<init>|<init>(){}[0]
}

open annotation class kotlinx.serialization/SealedSerializationApi : kotlin/Annotation { // kotlinx.serialization/SealedSerializationApi|null[0]
constructor <init>() // kotlinx.serialization/SealedSerializationApi.<init>|<init>(){}[0]
}

open annotation class kotlinx.serialization/SerialInfo : kotlin/Annotation { // kotlinx.serialization/SerialInfo|null[0]
constructor <init>() // kotlinx.serialization/SerialInfo.<init>|<init>(){}[0]
}
Expand Down
30 changes: 0 additions & 30 deletions core/commonMain/src/kotlinx/serialization/Annotations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -347,33 +347,3 @@ public annotation class Polymorphic
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
public annotation class KeepGeneratedSerializer

/**
* Marks declarations that are still **experimental** in kotlinx.serialization, which means that the design of the
* corresponding declarations has open issues which may (or may not) lead to their changes in the future.
* Roughly speaking, there is a chance that those declarations will be deprecated in the near future or
* the semantics of their behavior may change in some way that may break some code.
*
* By default, the following categories of API are experimental:
*
* * Writing 3rd-party serialization formats
* * Writing non-trivial custom serializers
* * Implementing [SerialDescriptor] interfaces
* * Not-yet-stable serialization formats that require additional polishing
*/
@MustBeDocumented
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
public annotation class ExperimentalSerializationApi

/**
* Public API marked with this annotation is effectively **internal**, which means
* it should not be used outside of `kotlinx.serialization`.
* Signature, semantics, source and binary compatibilities are not guaranteed for this API
* and will be changed without any warnings or migration aids.
* If you cannot avoid using internal API to solve your problem, please report your use-case to serialization's issue tracker.
*/
@MustBeDocumented
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS)
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
public annotation class InternalSerializationApi
51 changes: 51 additions & 0 deletions core/commonMain/src/kotlinx/serialization/ApiLevels.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2017-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.serialization

import kotlinx.serialization.descriptors.*

/**
* Marks declarations that are still **experimental** in kotlinx.serialization, which means that the design of the
* corresponding declarations has open issues which may (or may not) lead to their changes in the future.
* Roughly speaking, there is a chance that those declarations will be deprecated in the near future or
* the semantics of their behavior may change in some way that may break some code.
*
* By default, the following categories of API are experimental:
*
* * Writing 3rd-party serialization formats
* * Writing non-trivial custom serializers
* * Implementing [SerialDescriptor] interfaces
* * Not-yet-stable serialization formats that require additional polishing
*/
@MustBeDocumented
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS)
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
public annotation class ExperimentalSerializationApi

/**
* Public API marked with this annotation is effectively **internal**, which means
* it should not be used outside of `kotlinx.serialization`.
* Signature, semantics, source and binary compatibilities are not guaranteed for this API
* and will be changed without any warnings or migration aids.
* If you cannot avoid using internal API to solve your problem, please report your use-case to serialization's issue tracker.
*/
@MustBeDocumented
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS)
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
public annotation class InternalSerializationApi

/**
* Marks interfaces and non-final classes that can be freely referenced in users' code but should not be
* implemented or inherited. Such declarations are effectively `sealed` and do not have this modifier purely for technical reasons.
*
* kotlinx.serialization library provides compatibility guarantees for existing signatures of such classes;
* however, new functions or properties can be added to them in any release.
*/
@MustBeDocumented
@Target() // no direct targets, only argument to @SubclassOptInRequired
@RequiresOptIn(message = "This class or interface should not be inherited/implemented outside of kotlinx.serialization library. " +
"Note it is still permitted to use it directly. Read its documentation about inheritance for details.", level = RequiresOptIn.Level.ERROR)
public annotation class SealedSerializationApi

Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ import kotlinx.serialization.encoding.*
* might be added to this interface when kotlinx.serialization adds support for new Kotlin features.
* This interface is safe to use and construct via [buildClassSerialDescriptor], [PrimitiveSerialDescriptor], and `SerialDescriptor` factory function.
*/
@SubclassOptInRequired(SealedSerializationApi::class)
public interface SerialDescriptor {
/**
* Serial name of the descriptor that identifies a pair of the associated serializer and target class.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ import kotlinx.serialization.encoding.*
* ```
*/
@ExperimentalSerializationApi
@SubclassOptInRequired(SealedSerializationApi::class)
public interface CborDecoder : Decoder {
/**
* Exposes the current [Cbor] instance and all its configuration flags. Useful for low-level custom serializers.
*/
public val cbor: Cbor
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ import kotlinx.serialization.encoding.*
* ```
*/
@ExperimentalSerializationApi
@SubclassOptInRequired(SealedSerializationApi::class)
public interface CborEncoder : Encoder {
/**
* Exposes the current [Cbor] instance and all its configuration flags. Useful for low-level custom serializers.
*/
public val cbor: Cbor
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import kotlinx.serialization.descriptors.*
* Accepting this interface in your API methods, casting [Decoder] to [JsonDecoder] and invoking its
* methods is considered stable.
*/
@SubclassOptInRequired(SealedSerializationApi::class)
public interface JsonDecoder : Decoder, CompositeDecoder {
/**
* An instance of the current [Json].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package kotlinx.serialization.json

import kotlinx.serialization.*
import kotlinx.serialization.encoding.*

/**
Expand Down Expand Up @@ -49,6 +50,7 @@ import kotlinx.serialization.encoding.*
* Accepting this interface in your API methods, casting [Encoder] to [JsonEncoder] and invoking its
* methods is considered stable.
*/
@SubclassOptInRequired(SealedSerializationApi::class)
public interface JsonEncoder : Encoder, CompositeEncoder {
/**
* An instance of the current [Json].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public fun <T> writeJson(json: Json, value: T, serializer: SerializationStrategy
return result
}

@ExperimentalSerializationApi
private sealed class AbstractJsonTreeEncoder(
final override val json: Json,
protected val nodeConsumer: (JsonElement) -> Unit
Expand Down

0 comments on commit 6de55d5

Please sign in to comment.