diff --git a/Changelog.md b/Changelog.md
index e3167de7d..d5ff7b06e 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -20,6 +20,8 @@ Changes:
This aids #225.
Fixes:
+- More reluctant caching of extended type descriptors such that type
+ parameters work correctly with caching.
- Fix NodeSerializer in the serialization module to properly forward
to the actual implementation.
- Don't make the companion of `XmlDeclMode` internal (#219). This is a
diff --git a/serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/DefaultFormatCache.kt b/serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/DefaultFormatCache.kt
index ec3d5e729..2169c6617 100644
--- a/serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/DefaultFormatCache.kt
+++ b/serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/DefaultFormatCache.kt
@@ -27,7 +27,6 @@ import kotlinx.serialization.descriptors.SerialKind
import kotlinx.serialization.descriptors.StructureKind
import nl.adaptivity.xmlutil.Namespace
import nl.adaptivity.xmlutil.QName
-import nl.adaptivity.xmlutil.localPart
import nl.adaptivity.xmlutil.namespaceURI
import nl.adaptivity.xmlutil.serialization.XML.XmlCodecConfig
import nl.adaptivity.xmlutil.serialization.structure.SafeParentInfo
@@ -48,7 +47,7 @@ internal class DefaultFormatCache : FormatCache() {
@OptIn(ExperimentalSerializationApi::class)
override fun lookupType(namespace: Namespace?, serialDesc: SerialDescriptor, defaultValue: () -> XmlTypeDescriptor): XmlTypeDescriptor {
- return lookupType(TypeKey(namespace?.namespaceURI, serialDesc.serialName), serialDesc.kind, defaultValue)
+ return lookupType(TypeKey(namespace?.namespaceURI, serialDesc.serialName, serialDesc.hashCode()), serialDesc.kind, defaultValue)
}
/**
@@ -57,12 +56,7 @@ internal class DefaultFormatCache : FormatCache() {
*/
@OptIn(ExperimentalSerializationApi::class)
override fun lookupType(parentName: QName, serialDesc: SerialDescriptor, defaultValue: () -> XmlTypeDescriptor): XmlTypeDescriptor {
- return lookupType(TypeKey(parentName.namespaceURI, serialDesc.serialName), serialDesc.kind, defaultValue)
- }
-
- @OptIn(ExperimentalSerializationApi::class)
- override fun lookupType(name: QName, kind: SerialKind, defaultValue: () -> XmlTypeDescriptor): XmlTypeDescriptor {
- return lookupType(TypeKey(name.namespaceURI, name.localPart), kind, defaultValue)
+ return lookupType(TypeKey(parentName.namespaceURI, serialDesc.serialName, serialDesc.hashCode()), serialDesc.kind, defaultValue)
}
@OptIn(ExperimentalSerializationApi::class)
@@ -91,8 +85,6 @@ internal class DefaultFormatCache : FormatCache() {
// This has to be getOrPut rather than `computeIfAbsent` as computeIfAbsent prevents other
// changes to different types. GetOrPut does not have that property (but is technically slower)
return elemDescCache.getOrPut(key) {
-// val parentName = serializerParent.descriptor?.typeDescriptor?.run { typeQname ?: serialName }
-// println("Calculating new descriptor for $parentName/${serializerParent.elementSerialDescriptor.serialName}")
defaultValue()
}.also {
pendingDescs.remove(key)
@@ -106,9 +98,6 @@ internal class DefaultFormatCache : FormatCache() {
preserveSpace: Boolean
): XmlCompositeDescriptor {
return XmlCompositeDescriptor(codecConfig, serializerParent, tagParent, preserveSpace)
-// return lookupDescriptor(null, serializerParent, tagParent, false) {
-// XmlCompositeDescriptor(config, serializersModule, serializerParent, tagParent, preserveSpace)
-// } as XmlCompositeDescriptor
}
internal data class DescKey(
@@ -118,11 +107,11 @@ internal class DefaultFormatCache : FormatCache() {
val canBeAttribute: Boolean
)
- private data class TypeKey(val namespace: String, val serialName: String)
+ private data class TypeKey(val namespace: String, val serialName: String, val descriptorHash: Int)
companion object {
@JvmStatic
- private fun TypeKey(namespace: String?, serialName: String) =
- DefaultFormatCache.TypeKey(namespace ?: "", serialName)
+ private fun TypeKey(namespace: String?, serialName: String, descriptorHash: Int) =
+ DefaultFormatCache.TypeKey(namespace ?: "", serialName, descriptorHash)
}
}
diff --git a/serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/FormatCache.kt b/serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/FormatCache.kt
index 9b7ea8339..17d0bfa78 100644
--- a/serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/FormatCache.kt
+++ b/serialization/src/commonMain/kotlin/nl/adaptivity/xmlutil/serialization/FormatCache.kt
@@ -20,10 +20,8 @@
package nl.adaptivity.xmlutil.serialization
-import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.descriptors.SerialKind
import nl.adaptivity.xmlutil.Namespace
import nl.adaptivity.xmlutil.QName
import nl.adaptivity.xmlutil.serialization.structure.SafeParentInfo
@@ -40,9 +38,6 @@ public abstract class FormatCache internal constructor(){
*/
internal abstract fun lookupType(parentName: QName, serialDesc: SerialDescriptor, defaultValue: () -> XmlTypeDescriptor): XmlTypeDescriptor
- @OptIn(ExperimentalSerializationApi::class)
- internal abstract fun lookupType(name: QName, kind: SerialKind, defaultValue: () -> XmlTypeDescriptor): XmlTypeDescriptor
-
internal abstract fun lookupDescriptor(
overridenSerializer: KSerializer<*>?,
serializerParent: SafeParentInfo,
@@ -71,13 +66,6 @@ public abstract class FormatCache internal constructor(){
defaultValue: () -> XmlTypeDescriptor
): XmlTypeDescriptor = defaultValue()
- @OptIn(ExperimentalSerializationApi::class)
- override fun lookupType(
- name: QName,
- kind: SerialKind,
- defaultValue: () -> XmlTypeDescriptor
- ): XmlTypeDescriptor = defaultValue()
-
override fun lookupDescriptor(
overridenSerializer: KSerializer<*>?,
serializerParent: SafeParentInfo,
diff --git a/serialization/src/commonTest/kotlin/nl/adaptivity/xml/serialization/regressions/TestCachedDescriptorCache.kt b/serialization/src/commonTest/kotlin/nl/adaptivity/xml/serialization/regressions/TestCachedDescriptorCache.kt
new file mode 100644
index 000000000..f31132117
--- /dev/null
+++ b/serialization/src/commonTest/kotlin/nl/adaptivity/xml/serialization/regressions/TestCachedDescriptorCache.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024.
+ *
+ * This file is part of xmlutil.
+ *
+ * This file is licenced to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You should have received a copy of the license with the source distribution.
+ * Alternatively, you may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package nl.adaptivity.xml.serialization.regressions
+
+import io.github.pdvrieze.xmlutil.testutil.assertXmlEquals
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.encodeToString
+import nl.adaptivity.xmlutil.serialization.XML
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class TestCachedDescriptorCache {
+
+ @Test
+ fun testParameterisedSerializerCache() {
+ val format = XML {}
+
+ val serialized1 = format.encodeToString(Outer(Inner1(1, 2)))
+ assertXmlEquals("", serialized1)
+
+ val serialized2 = format.encodeToString(Outer(Inner2("a", "b", "c")))
+ assertXmlEquals("", serialized2)
+ }
+
+ @Serializable
+ data class Outer(val data: T)
+
+ @Serializable
+ data class Inner1(val data1: Int, val data2: Int)
+
+ @Serializable
+ data class Inner2(val data3: String, val data4: String, val data5: String)
+}