diff --git a/core/api/kotlinx-serialization-core.api b/core/api/kotlinx-serialization-core.api index c8d0d35d77..6a2c1a20d1 100644 --- a/core/api/kotlinx-serialization-core.api +++ b/core/api/kotlinx-serialization-core.api @@ -202,9 +202,19 @@ public final class kotlinx/serialization/builtins/BuiltinSerializersKt { public static final fun serializer (Lkotlin/jvm/internal/ShortCompanionObject;)Lkotlinx/serialization/KSerializer; public static final fun serializer (Lkotlin/jvm/internal/StringCompanionObject;)Lkotlinx/serialization/KSerializer; public static final fun serializer (Lkotlin/time/Duration$Companion;)Lkotlinx/serialization/KSerializer; + public static final fun serializer (Lkotlin/time/Instant$Companion;)Lkotlinx/serialization/KSerializer; public static final fun serializer (Lkotlin/uuid/Uuid$Companion;)Lkotlinx/serialization/KSerializer; } +public final class kotlinx/serialization/builtins/InstantComponentSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/serialization/builtins/InstantComponentSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlin/time/Instant; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlin/time/Instant;)V +} + public final class kotlinx/serialization/builtins/LongAsStringSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lkotlinx/serialization/builtins/LongAsStringSerializer; public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Long; @@ -795,6 +805,15 @@ public final class kotlinx/serialization/internal/InlineClassDescriptorKt { public static final fun InlinePrimitiveDescriptor (Ljava/lang/String;Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/descriptors/SerialDescriptor; } +public final class kotlinx/serialization/internal/InstantSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/serialization/internal/InstantSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlin/time/Instant; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlin/time/Instant;)V +} + public final class kotlinx/serialization/internal/IntArrayBuilder : kotlinx/serialization/internal/PrimitiveArrayBuilder { public synthetic fun build$kotlinx_serialization_core ()Ljava/lang/Object; } diff --git a/core/api/kotlinx-serialization-core.klib.api b/core/api/kotlinx-serialization-core.klib.api index 041c115e26..5aefad0f2f 100644 --- a/core/api/kotlinx-serialization-core.klib.api +++ b/core/api/kotlinx-serialization-core.klib.api @@ -890,6 +890,14 @@ sealed class kotlinx.serialization.modules/SerializersModule { // kotlinx.serial final fun <#A1: kotlin/Any> getContextual(kotlin.reflect/KClass<#A1>): kotlinx.serialization/KSerializer<#A1>? // kotlinx.serialization.modules/SerializersModule.getContextual|getContextual(kotlin.reflect.KClass<0:0>){0§}[0] } +final object kotlinx.serialization.builtins/InstantComponentSerializer : kotlinx.serialization/KSerializer { // kotlinx.serialization.builtins/InstantComponentSerializer|null[0] + final val descriptor // kotlinx.serialization.builtins/InstantComponentSerializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.serialization.builtins/InstantComponentSerializer.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlin.time/Instant // kotlinx.serialization.builtins/InstantComponentSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, kotlin.time/Instant) // kotlinx.serialization.builtins/InstantComponentSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlin.time.Instant){}[0] +} + final object kotlinx.serialization.builtins/LongAsStringSerializer : kotlinx.serialization/KSerializer { // kotlinx.serialization.builtins/LongAsStringSerializer|null[0] final val descriptor // kotlinx.serialization.builtins/LongAsStringSerializer.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.serialization.builtins/LongAsStringSerializer.descriptor.|(){}[0] @@ -956,6 +964,14 @@ final object kotlinx.serialization.internal/FloatSerializer : kotlinx.serializat final fun serialize(kotlinx.serialization.encoding/Encoder, kotlin/Float) // kotlinx.serialization.internal/FloatSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlin.Float){}[0] } +final object kotlinx.serialization.internal/InstantSerializer : kotlinx.serialization/KSerializer { // kotlinx.serialization.internal/InstantSerializer|null[0] + final val descriptor // kotlinx.serialization.internal/InstantSerializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.serialization.internal/InstantSerializer.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlin.time/Instant // kotlinx.serialization.internal/InstantSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, kotlin.time/Instant) // kotlinx.serialization.internal/InstantSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlin.time.Instant){}[0] +} + final object kotlinx.serialization.internal/IntArraySerializer : kotlinx.serialization.internal/PrimitiveArraySerializer, kotlinx.serialization/KSerializer // kotlinx.serialization.internal/IntArraySerializer|null[0] final object kotlinx.serialization.internal/IntSerializer : kotlinx.serialization/KSerializer { // kotlinx.serialization.internal/IntSerializer|null[0] @@ -1074,6 +1090,7 @@ final val kotlinx.serialization.modules/EmptySerializersModule // kotlinx.serial final fun (): kotlinx.serialization.modules/SerializersModule // kotlinx.serialization.modules/EmptySerializersModule.|(){}[0] final fun (kotlin.time/Duration.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer // kotlinx.serialization.builtins/serializer|serializer@kotlin.time.Duration.Companion(){}[0] +final fun (kotlin.time/Instant.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer // kotlinx.serialization.builtins/serializer|serializer@kotlin.time.Instant.Companion(){}[0] final fun (kotlin.uuid/Uuid.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer // kotlinx.serialization.builtins/serializer|serializer@kotlin.uuid.Uuid.Companion(){}[0] final fun (kotlin/Boolean.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer // kotlinx.serialization.builtins/serializer|serializer@kotlin.Boolean.Companion(){}[0] final fun (kotlin/Byte.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer // kotlinx.serialization.builtins/serializer|serializer@kotlin.Byte.Companion(){}[0] diff --git a/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt b/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt index c481e3adf8..aedd4fe874 100644 --- a/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt +++ b/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt @@ -10,6 +10,8 @@ import kotlinx.serialization.internal.* import kotlin.reflect.* import kotlinx.serialization.descriptors.* import kotlin.time.Duration +import kotlin.time.ExperimentalTime +import kotlin.time.Instant import kotlin.uuid.* /** @@ -245,12 +247,30 @@ public fun UShort.Companion.serializer(): KSerializer = UShortSerializer /** * Returns serializer for [Duration]. - * It is serialized as a string that represents a duration in the ISO-8601-2 format. + * It is serialized as a string that represents a duration in the format used by [Duration.toIsoString], + * that is, the ISO-8601-2 format. * - * The result of serialization is similar to calling [Duration.toIsoString], for deserialization is [Duration.parseIsoString]. + * For deserialization, [Duration.parseIsoString] is used. + * + * @see Duration.toIsoString + * @see Duration.parseIsoString */ public fun Duration.Companion.serializer(): KSerializer = DurationSerializer +/** + * Returns serializer for [Instant]. + * It is serialized as a string that represents an instant in the format used by [Instant.toString] + * and described in ISO-8601-1:2019, 5.4.2.1b). + * + * Deserialization is case-insensitive. + * More details can be found in the documentation of [Instant.toString] and [Instant.parse] functions. + * + * @see Instant.toString + * @see Instant.parse + */ +@ExperimentalTime +public fun Instant.Companion.serializer(): KSerializer = InstantSerializer + /** * Returns serializer for [Uuid]. * Serializer operates with a standard UUID string representation, also known as "hex-and-dash" format — diff --git a/core/commonMain/src/kotlinx/serialization/builtins/InstantComponentSerializer.kt b/core/commonMain/src/kotlinx/serialization/builtins/InstantComponentSerializer.kt new file mode 100644 index 0000000000..3aaedccb9e --- /dev/null +++ b/core/commonMain/src/kotlinx/serialization/builtins/InstantComponentSerializer.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2025-2025 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.builtins + +import kotlinx.serialization.* +import kotlinx.serialization.descriptors.* +import kotlinx.serialization.encoding.* +import kotlin.time.ExperimentalTime +import kotlin.time.Instant + +/** + * Serializer that encodes and decodes [Instant] as its second and nanosecond components of the Unix time. + * + * JSON example: `{"epochSeconds":1607505416,"nanosecondsOfSecond":124000}`. + */ +@ExperimentalTime +public object InstantComponentSerializer : KSerializer { + + override val descriptor: SerialDescriptor = + buildClassSerialDescriptor("kotlinx.serialization.InstantComponentSerializer") { + element("epochSeconds") + element("nanosecondsOfSecond", isOptional = true) + } + + @OptIn(ExperimentalSerializationApi::class) + override fun deserialize(decoder: Decoder): Instant = + decoder.decodeStructure(descriptor) { + var epochSecondsNotSeen = true + var epochSeconds: Long = 0 + var nanosecondsOfSecond = 0 + while (true) { + when (val index = decodeElementIndex(descriptor)) { + 0 -> { + epochSecondsNotSeen = false + epochSeconds = decodeLongElement(descriptor, 0) + } + 1 -> nanosecondsOfSecond = decodeIntElement(descriptor, 1) + CompositeDecoder.DECODE_DONE -> break + else -> throw SerializationException("Unexpected index: $index") + } + } + if (epochSecondsNotSeen) throw MissingFieldException( + missingField = "epochSeconds", + serialName = descriptor.serialName + ) + Instant.fromEpochSeconds(epochSeconds, nanosecondsOfSecond) + } + + @OptIn(ExperimentalSerializationApi::class) + override fun serialize(encoder: Encoder, value: Instant) { + encoder.encodeStructure(descriptor) { + encodeLongElement(descriptor, 0, value.epochSeconds) + if (value.nanosecondsOfSecond != 0 || shouldEncodeElementDefault(descriptor, 1)) { + encodeIntElement(descriptor, 1, value.nanosecondsOfSecond) + } + } + } + +} diff --git a/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt b/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt index fbc5dc1476..8db48f72e9 100644 --- a/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt +++ b/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt @@ -10,6 +10,8 @@ import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlin.time.Duration +import kotlin.time.ExperimentalTime +import kotlin.time.Instant import kotlin.uuid.* @@ -39,6 +41,20 @@ internal object NothingSerializer : KSerializer { } } +@PublishedApi +@ExperimentalTime +internal object InstantSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("kotlin.time.Instant", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: Instant) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): Instant { + return Instant.parse(decoder.decodeString()) + } +} + @PublishedApi @ExperimentalUuidApi internal object UuidSerializer: KSerializer { diff --git a/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt b/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt index 859818aa29..6115f8fd1d 100644 --- a/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt +++ b/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt @@ -10,7 +10,6 @@ import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* import kotlinx.serialization.encoding.CompositeDecoder.Companion.UNKNOWN_NAME import kotlinx.serialization.modules.* -import kotlinx.serialization.test.* import kotlin.test.* import kotlin.time.Duration diff --git a/core/jsMain/src/kotlinx/serialization/internal/Platform.kt b/core/jsMain/src/kotlinx/serialization/internal/Platform.kt index e423afca2a..72625567fe 100644 --- a/core/jsMain/src/kotlinx/serialization/internal/Platform.kt +++ b/core/jsMain/src/kotlinx/serialization/internal/Platform.kt @@ -81,7 +81,8 @@ private val KClass<*>.isInterface: Boolean return js.asDynamic().`$metadata$`?.kind == "interface" } -@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class, ExperimentalSerializationApi::class) +@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class, ExperimentalSerializationApi::class, + ExperimentalTime::class) internal actual fun initBuiltins(): Map, KSerializer<*>> = mapOf( String::class to String.serializer(), Char::class to Char.serializer(), @@ -111,5 +112,6 @@ internal actual fun initBuiltins(): Map, KSerializer<*>> = mapOf( Unit::class to Unit.serializer(), Nothing::class to NothingSerializer(), Duration::class to Duration.serializer(), + Instant::class to Instant.serializer(), Uuid::class to Uuid.serializer() ) diff --git a/core/jvmMain/src/kotlinx/serialization/internal/Platform.kt b/core/jvmMain/src/kotlinx/serialization/internal/Platform.kt index b838a0fe52..65d38fba70 100644 --- a/core/jvmMain/src/kotlinx/serialization/internal/Platform.kt +++ b/core/jvmMain/src/kotlinx/serialization/internal/Platform.kt @@ -201,6 +201,9 @@ internal actual fun initBuiltins(): Map, KSerializer<*>> = buildMap { } @OptIn(ExperimentalUuidApi::class) loadSafe { put(Uuid::class, Uuid.serializer()) } + + @OptIn(ExperimentalTime::class) + loadSafe { put(Instant::class, Instant.serializer()) } } // Reference classes in [block] ignoring any exceptions related to class loading diff --git a/core/nativeMain/src/kotlinx/serialization/internal/Platform.kt b/core/nativeMain/src/kotlinx/serialization/internal/Platform.kt index c2e9fdd7e0..7e2423a76e 100644 --- a/core/nativeMain/src/kotlinx/serialization/internal/Platform.kt +++ b/core/nativeMain/src/kotlinx/serialization/internal/Platform.kt @@ -75,7 +75,8 @@ private fun arrayOfAnyNulls(size: Int): Array = arrayOfNulls(size) a internal actual fun isReferenceArray(rootClass: KClass): Boolean = rootClass == Array::class -@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class, ExperimentalSerializationApi::class) +@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class, ExperimentalSerializationApi::class, + ExperimentalTime::class) internal actual fun initBuiltins(): Map, KSerializer<*>> = mapOf( String::class to String.serializer(), Char::class to Char.serializer(), @@ -105,5 +106,6 @@ internal actual fun initBuiltins(): Map, KSerializer<*>> = mapOf( Unit::class to Unit.serializer(), Nothing::class to NothingSerializer(), Duration::class to Duration.serializer(), + Instant::class to Instant.serializer(), Uuid::class to Uuid.serializer() ) diff --git a/core/wasmMain/src/kotlinx/serialization/internal/Platform.kt b/core/wasmMain/src/kotlinx/serialization/internal/Platform.kt index ecfee8ede8..381d6a4d68 100644 --- a/core/wasmMain/src/kotlinx/serialization/internal/Platform.kt +++ b/core/wasmMain/src/kotlinx/serialization/internal/Platform.kt @@ -65,7 +65,8 @@ internal actual fun ArrayList.toNativeArrayImpl(eClass: KCl internal actual fun isReferenceArray(rootClass: KClass): Boolean = rootClass == Array::class -@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class, ExperimentalSerializationApi::class) +@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class, ExperimentalSerializationApi::class, + ExperimentalTime::class) internal actual fun initBuiltins(): Map, KSerializer<*>> = mapOf( String::class to String.serializer(), Char::class to Char.serializer(), @@ -95,5 +96,6 @@ internal actual fun initBuiltins(): Map, KSerializer<*>> = mapOf( Unit::class to Unit.serializer(), Nothing::class to NothingSerializer(), Duration::class to Duration.serializer(), + Instant::class to Instant.serializer(), Uuid::class to Uuid.serializer() ) diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/InstantSerializationTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/InstantSerializationTest.kt new file mode 100644 index 0000000000..b15a01f66d --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/InstantSerializationTest.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2025-2025 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.builtins.* +import kotlin.time.* +import kotlin.test.* +import kotlin.reflect.typeOf + +@OptIn(ExperimentalTime::class) +class InstantSerializationTest: JsonTestBase() { + private fun iso8601Serialization(serializer: KSerializer) { + for ((instant, json) in listOf( + Pair(Instant.fromEpochSeconds(1607505416, 124000), + "\"2020-12-09T09:16:56.000124Z\""), + Pair(Instant.fromEpochSeconds(-1607505416, -124000), + "\"1919-01-23T14:43:03.999876Z\""), + Pair(Instant.fromEpochSeconds(987654321, 123456789), + "\"2001-04-19T04:25:21.123456789Z\""), + Pair(Instant.fromEpochSeconds(987654321, 0), + "\"2001-04-19T04:25:21Z\""), + )) { + assertJsonFormAndRestored(serializer, instant, json) + } + for ((instant, json) in listOf( + Pair(Instant.fromEpochSeconds(987654321, 123456789), + "\"2001-04-19T07:55:21.123456789+03:30\""), + Pair(Instant.fromEpochSeconds(987654321, 123456789), + "\"2001-04-19T00:55:21.123456789-03:30\""), + )) { + assertRestoredFromJsonForm(serializer, json, instant) + } + } + + private fun componentSerialization(serializer: KSerializer) { + for ((instant, json) in listOf( + Pair(Instant.fromEpochSeconds(1607505416, 124000), + "{\"epochSeconds\":1607505416,\"nanosecondsOfSecond\":124000}"), + Pair(Instant.fromEpochSeconds(-1607505416, -124000), + "{\"epochSeconds\":-1607505417,\"nanosecondsOfSecond\":999876000}"), + Pair(Instant.fromEpochSeconds(987654321, 123456789), + "{\"epochSeconds\":987654321,\"nanosecondsOfSecond\":123456789}"), + Pair(Instant.fromEpochSeconds(987654321, 0), + "{\"epochSeconds\":987654321,\"nanosecondsOfSecond\":0}"), + )) { + assertJsonFormAndRestored(serializer, instant, json) + } + // by default, `nanosecondsOfSecond` is optional + assertJsonFormAndRestored(serializer, Instant.fromEpochSeconds(987654321, 0), + "{\"epochSeconds\":987654321}", Json { }) + // having a `"nanosecondsOfSecond": 0` field doesn't break deserialization + assertEquals(Instant.fromEpochSeconds(987654321, 0), + Json.decodeFromString(serializer, + "{\"epochSeconds\":987654321,\"nanosecondsOfSecond\":0}")) + // as does not having a `"nanosecondsOfSecond"` field if `encodeDefaults` is true + assertEquals(Instant.fromEpochSeconds(987654321, 0), + default.decodeFromString(serializer, + "{\"epochSeconds\":987654321}")) + // "epochSeconds" should always be present + assertFailsWith { Json.decodeFromString(serializer, "{}") } + assertFailsWith { Json.decodeFromString(serializer, "{\"nanosecondsOfSecond\":3}") } + } + + @Test + fun testIso8601Serialization() { + iso8601Serialization(Instant.serializer()) + } + + @Test + fun testComponentSerialization() { + componentSerialization(InstantComponentSerializer) + } + + @Test + fun testDefaultSerializers() { + // should be the same as the ISO 8601 + @Suppress("UNCHECKED_CAST") + iso8601Serialization(serializer(typeOf()) as KSerializer) + // iso8601Serialization(serializer()) TODO: uncomment when the compiler adds KT-75759 + } +} diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt index de8cfb38b0..66f00177aa 100644 --- a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt @@ -190,4 +190,15 @@ abstract class JsonTestBase { assertTrue("Failed with streaming = $jsonTestingMode\n\tsource value =$data\n\tdeserialized value=$deserialized") { check(data, deserialized) } } } + + internal fun assertRestoredFromJsonForm( + serializer: KSerializer, + jsonForm: String, + expected: T, + ) { + parametrizedTest { jsonTestingMode -> + val deserialized: T = Json.decodeFromString(serializer, jsonForm, jsonTestingMode) + assertEquals(expected, deserialized, "Failed with streaming = $jsonTestingMode") + } + } } diff --git a/gradle.properties b/gradle.properties index 89fe620723..deb1585fa6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -23,5 +23,3 @@ org.gradle.kotlin.dsl.allWarningsAsErrors=true kotlin.native.distribution.type=prebuilt org.gradle.jvmargs="-XX:+HeapDumpOnOutOfMemoryError" - -org.jetbrains.dokka.experimental.tryK2=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 22b2552b8b..132a67b614 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.1.20" kover = "0.8.2" -dokka = "2.0.0-Beta" +dokka = "2.0.0" knit = "0.5.0" bcv = "0.16.2" animalsniffer = "1.7.1"