Skip to content

Commit 9e2e16e

Browse files
authored
Stabilize EmptySerializersModule (Kotlin#1921)
Fixes Kotlin#1765
1 parent bf3269b commit 9e2e16e

File tree

28 files changed

+177
-93
lines changed

28 files changed

+177
-93
lines changed

core/api/kotlinx-serialization-core.api

+1
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,7 @@ public final class kotlinx/serialization/modules/SerializersModuleBuilder : kotl
12051205
}
12061206

12071207
public final class kotlinx/serialization/modules/SerializersModuleBuildersKt {
1208+
public static final fun EmptySerializersModule ()Lkotlinx/serialization/modules/SerializersModule;
12081209
public static final fun SerializersModule (Lkotlin/jvm/functions/Function1;)Lkotlinx/serialization/modules/SerializersModule;
12091210
public static final fun polymorphic (Lkotlinx/serialization/modules/SerializersModuleBuilder;Lkotlin/reflect/KClass;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;)V
12101211
public static synthetic fun polymorphic$default (Lkotlinx/serialization/modules/SerializersModuleBuilder;Lkotlin/reflect/KClass;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V

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

+6-3
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ public inline fun <reified T> SerializersModule.serializer(): KSerializer<T> {
3838
* @throws SerializationException if serializer cannot be created (provided [type] or its type argument is not serializable).
3939
*/
4040
@OptIn(ExperimentalSerializationApi::class)
41-
public fun serializer(type: KType): KSerializer<Any?> = EmptySerializersModule.serializer(type)
41+
public fun serializer(type: KType): KSerializer<Any?> = EmptySerializersModule().serializer(type)
4242

4343
/**
4444
* Creates a serializer for the given [type].
4545
* [type] argument can be obtained with experimental [typeOf] method.
4646
* Returns `null` if serializer cannot be created (provided [type] or its type argument is not serializable).
4747
*/
4848
@OptIn(ExperimentalSerializationApi::class)
49-
public fun serializerOrNull(type: KType): KSerializer<Any?>? = EmptySerializersModule.serializerOrNull(type)
49+
public fun serializerOrNull(type: KType): KSerializer<Any?>? = EmptySerializersModule().serializerOrNull(type)
5050

5151
/**
5252
* Attempts to create a serializer for the given [type] and fallbacks to [contextual][SerializersModule.getContextual]
@@ -122,7 +122,10 @@ private fun SerializersModule.builtinSerializer(
122122
}
123123

124124
@OptIn(ExperimentalSerializationApi::class)
125-
internal fun <T : Any> SerializersModule.reflectiveOrContextual(kClass: KClass<T>, typeArgumentsSerializers: List<KSerializer<Any?>>): KSerializer<T>? {
125+
internal fun <T : Any> SerializersModule.reflectiveOrContextual(
126+
kClass: KClass<T>,
127+
typeArgumentsSerializers: List<KSerializer<Any?>>
128+
): KSerializer<T>? {
126129
return kClass.serializerOrNull() ?: getContextual(kClass, typeArgumentsSerializers)
127130
}
128131

core/commonMain/src/kotlinx/serialization/internal/NoOpEncoder.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import kotlinx.serialization.modules.*
1414
*/
1515
@OptIn(ExperimentalSerializationApi::class)
1616
internal object NoOpEncoder : AbstractEncoder() {
17-
override val serializersModule: SerializersModule = EmptySerializersModule
17+
override val serializersModule: SerializersModule = EmptySerializersModule()
1818

1919
public override fun encodeValue(value: Any): Unit = Unit
2020

core/commonMain/src/kotlinx/serialization/internal/Tagged.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public abstract class TaggedEncoder<Tag : Any?> : Encoder, CompositeEncoder {
2424
protected abstract fun SerialDescriptor.getTag(index: Int): Tag
2525

2626
override val serializersModule: SerializersModule
27-
get() = EmptySerializersModule
27+
get() = EmptySerializersModule()
2828

2929
// ---- API ----
3030
protected open fun encodeTaggedValue(tag: Tag, value: Any): Unit =
@@ -177,7 +177,7 @@ public abstract class NamedValueEncoder : TaggedEncoder<String>() {
177177
@InternalSerializationApi
178178
public abstract class TaggedDecoder<Tag : Any?> : Decoder, CompositeDecoder {
179179
override val serializersModule: SerializersModule
180-
get() = EmptySerializersModule
180+
get() = EmptySerializersModule()
181181

182182
protected abstract fun SerialDescriptor.getTag(index: Int): Tag
183183

core/commonMain/src/kotlinx/serialization/modules/SerializersModule.kt

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package kotlinx.serialization.modules
66

77
import kotlinx.serialization.*
88
import kotlinx.serialization.internal.*
9+
import kotlin.js.*
910
import kotlin.jvm.*
1011
import kotlin.native.concurrent.*
1112
import kotlin.reflect.*
@@ -18,6 +19,9 @@ import kotlin.reflect.*
1819
* To enable runtime serializers resolution, one of the special annotations must be used on target types
1920
* ([Polymorphic] or [Contextual]), and a serial module with serializers should be used during construction of [SerialFormat].
2021
*
22+
* Serializers module can be built with `SerializersModule {}` builder function.
23+
* Empty module can be obtained with `EmptySerializersModule()` factory function.
24+
*
2125
* @see Contextual
2226
* @see Polymorphic
2327
*/
@@ -28,7 +32,7 @@ public sealed class SerializersModule {
2832
"Deprecated in favor of overload with default parameter",
2933
ReplaceWith("getContextual(kclass)"),
3034
DeprecationLevel.HIDDEN
31-
) // Was stable since 1.0.0, HIDDEN in 1.2.0 in a backwards-compatible manner
35+
) // Was experimental since 1.0.0, HIDDEN in 1.2.0 in a backwards-compatible manner
3236
public fun <T : Any> getContextual(kclass: KClass<T>): KSerializer<T>? =
3337
getContextual(kclass, emptyList())
3438

@@ -70,7 +74,10 @@ public sealed class SerializersModule {
7074
* A [SerializersModule] which is empty and always returns `null`.
7175
*/
7276
@SharedImmutable
73-
@ExperimentalSerializationApi
77+
@Deprecated("Deprecated in the favour of 'EmptySerializersModule()'",
78+
level = DeprecationLevel.WARNING,
79+
replaceWith = ReplaceWith("EmptySerializersModule()"))
80+
@JsName("EmptySerializersModuleLegacyJs") // Compatibility with JS
7481
public val EmptySerializersModule: SerializersModule = SerialModuleImpl(emptyMap(), emptyMap(), emptyMap(), emptyMap(), emptyMap())
7582

7683
/**

core/commonMain/src/kotlinx/serialization/modules/SerializersModuleBuilders.kt

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public inline fun SerializersModule(builderAction: SerializersModuleBuilder.() -
3333
return builder.build()
3434
}
3535

36+
/**
37+
* A [SerializersModule] which is empty and returns `null` from each method.
38+
*/
39+
public fun EmptySerializersModule(): SerializersModule = @Suppress("DEPRECATION") EmptySerializersModule
40+
3641
/**
3742
* A builder class for [SerializersModule] DSL. To create an instance of builder, use [SerializersModule] factory function.
3843
*/

core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class BasicTypesSerializationTest {
2020

2121
// KeyValue Input/Output
2222
class KeyValueOutput(private val sb: StringBuilder) : AbstractEncoder() {
23-
override val serializersModule: SerializersModule = EmptySerializersModule
23+
override val serializersModule: SerializersModule = EmptySerializersModule()
2424

2525
override fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder {
2626
sb.append('{')
@@ -56,7 +56,7 @@ class BasicTypesSerializationTest {
5656
}
5757

5858
class KeyValueInput(private val inp: Parser) : AbstractDecoder() {
59-
override val serializersModule: SerializersModule = EmptySerializersModule
59+
override val serializersModule: SerializersModule = EmptySerializersModule()
6060

6161
override fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder {
6262
inp.expectAfterWhiteSpace('{')

core/commonTest/src/kotlinx/serialization/CustomPropertyAccessorsTest.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,8 @@ class CustomPropertyAccessorsTest {
108108
*/
109109

110110

111-
112111
private class CommonStringDecoder(private val elementCount: Int) : AbstractDecoder() {
113-
override val serializersModule: SerializersModule = EmptySerializersModule
112+
override val serializersModule: SerializersModule = EmptySerializersModule()
114113
private var elementIndex = 0
115114

116115
override fun decodeString(): String {

core/jvmMain/src/kotlinx/serialization/SerializersJvm.kt

+19-7
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import kotlin.reflect.*
2727
* @throws SerializationException if serializer cannot be created (provided [type] or its type argument is not serializable).
2828
*/
2929
@ExperimentalSerializationApi
30-
public fun serializer(type: Type): KSerializer<Any> = EmptySerializersModule.serializer(type)
30+
public fun serializer(type: Type): KSerializer<Any> = EmptySerializersModule().serializer(type)
3131

3232
/**
3333
* Reflectively constructs a serializer for the given reflective Java [type].
@@ -40,7 +40,7 @@ public fun serializer(type: Type): KSerializer<Any> = EmptySerializersModule.ser
4040
* Returns `null` if serializer cannot be created (provided [type] or its type argument is not serializable).
4141
*/
4242
@ExperimentalSerializationApi
43-
public fun serializerOrNull(type: Type): KSerializer<Any>? = EmptySerializersModule.serializerOrNull(type)
43+
public fun serializerOrNull(type: Type): KSerializer<Any>? = EmptySerializersModule().serializerOrNull(type)
4444

4545
/**
4646
* Retrieves serializer for the given reflective Java [type] using
@@ -56,7 +56,8 @@ public fun serializerOrNull(type: Type): KSerializer<Any>? = EmptySerializersMod
5656
*/
5757
@ExperimentalSerializationApi
5858
public fun SerializersModule.serializer(type: Type): KSerializer<Any> =
59-
serializerByJavaTypeImpl(type, failOnMissingTypeArgSerializer = true) ?: type.prettyClass().serializerNotRegistered()
59+
serializerByJavaTypeImpl(type, failOnMissingTypeArgSerializer = true) ?: type.prettyClass()
60+
.serializerNotRegistered()
6061

6162
/**
6263
* Retrieves serializer for the given reflective Java [type] using
@@ -75,7 +76,10 @@ public fun SerializersModule.serializerOrNull(type: Type): KSerializer<Any>? =
7576
serializerByJavaTypeImpl(type, failOnMissingTypeArgSerializer = false)
7677

7778
@OptIn(ExperimentalSerializationApi::class)
78-
private fun SerializersModule.serializerByJavaTypeImpl(type: Type, failOnMissingTypeArgSerializer: Boolean = true): KSerializer<Any>? =
79+
private fun SerializersModule.serializerByJavaTypeImpl(
80+
type: Type,
81+
failOnMissingTypeArgSerializer: Boolean = true
82+
): KSerializer<Any>? =
7983
when (type) {
8084
is GenericArrayType -> {
8185
genericArraySerializer(type, failOnMissingTypeArgSerializer)
@@ -85,7 +89,9 @@ private fun SerializersModule.serializerByJavaTypeImpl(type: Type, failOnMissing
8589
val rootClass = (type.rawType as Class<*>)
8690
val args = (type.actualTypeArguments)
8791
val argsSerializers =
88-
if (failOnMissingTypeArgSerializer) args.map { serializer(it) } else args.map { serializerOrNull(it) ?: return null }
92+
if (failOnMissingTypeArgSerializer) args.map { serializer(it) } else args.map {
93+
serializerOrNull(it) ?: return null
94+
}
8995
when {
9096
Set::class.java.isAssignableFrom(rootClass) -> SetSerializer(argsSerializers[0]) as KSerializer<Any>
9197
List::class.java.isAssignableFrom(rootClass) || Collection::class.java.isAssignableFrom(rootClass) -> ListSerializer(
@@ -122,7 +128,10 @@ private fun SerializersModule.serializerByJavaTypeImpl(type: Type, failOnMissing
122128
}
123129

124130
@OptIn(ExperimentalSerializationApi::class)
125-
private fun SerializersModule.typeSerializer(type: Class<*>, failOnMissingTypeArgSerializer: Boolean): KSerializer<Any>? {
131+
private fun SerializersModule.typeSerializer(
132+
type: Class<*>,
133+
failOnMissingTypeArgSerializer: Boolean
134+
): KSerializer<Any>? {
126135
return if (type.isArray && !type.componentType.isPrimitive) {
127136
val eType: Class<*> = type.componentType
128137
val s = if (failOnMissingTypeArgSerializer) serializer(eType) else (serializerOrNull(eType) ?: return null)
@@ -134,7 +143,10 @@ private fun SerializersModule.typeSerializer(type: Class<*>, failOnMissingTypeAr
134143
}
135144

136145
@OptIn(ExperimentalSerializationApi::class)
137-
private fun <T : Any> SerializersModule.reflectiveOrContextual(jClass: Class<T>, typeArgumentsSerializers: List<KSerializer<Any?>>): KSerializer<T>? {
146+
private fun <T : Any> SerializersModule.reflectiveOrContextual(
147+
jClass: Class<T>,
148+
typeArgumentsSerializers: List<KSerializer<Any?>>
149+
): KSerializer<T>? {
138150
jClass.constructSerializerForGivenTypeArgs(*typeArgumentsSerializers.toTypedArray())?.let { return it }
139151
val kClass = jClass.kotlin
140152
return kClass.builtinSerializerOrNull() ?: getContextual(kClass, typeArgumentsSerializers)

0 commit comments

Comments
 (0)