Skip to content

Commit f339684

Browse files
ht-jorozza
authored andcommitted
Fix getCodec of matching type argument bug (#1339)
bson-kotlin optional type fix Port bson-kotlin test to bson-kotlinx (#1452) JAVA-5365
1 parent 1aafa7a commit f339684

File tree

5 files changed

+30
-11
lines changed

5 files changed

+30
-11
lines changed

bson-kotlin/src/main/kotlin/org/bson/codecs/kotlin/DataClassCodec.kt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@ package org.bson.codecs.kotlin
1818
import java.lang.reflect.ParameterizedType
1919
import java.lang.reflect.Type
2020
import kotlin.reflect.KClass
21+
import kotlin.reflect.KClassifier
2122
import kotlin.reflect.KFunction
2223
import kotlin.reflect.KParameter
2324
import kotlin.reflect.KProperty1
24-
import kotlin.reflect.KType
2525
import kotlin.reflect.KTypeParameter
26+
import kotlin.reflect.KTypeProjection
2627
import kotlin.reflect.full.createType
2728
import kotlin.reflect.full.findAnnotation
2829
import kotlin.reflect.full.findAnnotations
2930
import kotlin.reflect.full.hasAnnotation
3031
import kotlin.reflect.full.primaryConstructor
3132
import kotlin.reflect.jvm.javaType
33+
import kotlin.reflect.jvm.jvmErasure
3234
import org.bson.BsonReader
3335
import org.bson.BsonType
3436
import org.bson.BsonWriter
@@ -140,7 +142,9 @@ internal data class DataClassCodec<T : Any>(
140142
val primaryConstructor =
141143
kClass.primaryConstructor ?: throw CodecConfigurationException("No primary constructor for $kClass")
142144
val typeMap =
143-
types.mapIndexed { i, k -> primaryConstructor.typeParameters[i].createType() to k }.toMap()
145+
types
146+
.mapIndexed { i, k -> primaryConstructor.typeParameters[i].createType().classifier!! to k }
147+
.toMap()
144148

145149
val propertyModels =
146150
primaryConstructor.parameters.map { kParameter ->
@@ -191,18 +195,20 @@ internal data class DataClassCodec<T : Any>(
191195
@Suppress("UNCHECKED_CAST")
192196
private fun getCodec(
193197
kParameter: KParameter,
194-
typeMap: Map<KType, Type>,
198+
typeMap: Map<KClassifier, Type>,
195199
codecRegistry: CodecRegistry
196200
): Codec<Any> {
197201
return when (kParameter.type.classifier) {
198202
is KClass<*> -> {
199203
codecRegistry.getCodec(
200204
kParameter,
201205
(kParameter.type.classifier as KClass<Any>).javaObjectType,
202-
kParameter.type.arguments.mapNotNull { typeMap[it.type] ?: it.type?.javaType }.toList())
206+
kParameter.type.arguments
207+
.mapNotNull { typeMap[it.type?.classifier] ?: computeJavaType(it) }
208+
.toList())
203209
}
204210
is KTypeParameter -> {
205-
when (val pType = typeMap[kParameter.type] ?: kParameter.type.javaType) {
211+
when (val pType = typeMap[kParameter.type.classifier] ?: kParameter.type.javaType) {
206212
is Class<*> ->
207213
codecRegistry.getCodec(kParameter, (pType as Class<Any>).kotlin.javaObjectType, emptyList())
208214
is ParameterizedType ->
@@ -219,6 +225,13 @@ internal data class DataClassCodec<T : Any>(
219225
"Could not find codec for ${kParameter.name} with type ${kParameter.type}")
220226
}
221227

228+
private fun computeJavaType(kTypeProjection: KTypeProjection): Type? {
229+
val javaType: Type = kTypeProjection.type?.javaType!!
230+
return if (javaType == Any::class.java) {
231+
kTypeProjection.type?.jvmErasure?.javaObjectType
232+
} else javaType
233+
}
234+
222235
@Suppress("UNCHECKED_CAST")
223236
private fun CodecRegistry.getCodec(kParameter: KParameter, clazz: Class<Any>, types: List<Type>): Codec<Any> {
224237
val codec =

bson-kotlin/src/test/kotlin/org/bson/codecs/kotlin/DataClassCodecTest.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,15 +249,17 @@ class DataClassCodecTest {
249249
|"nestedParameterized": {
250250
| "parameterizedDataClass":
251251
| {"number": 4.2, "string": "myString", "parameterizedList": [{"name": "embedded1"}]},
252-
| "other": "myOtherString"
252+
| "other": "myOtherString", "optionalOther": "myOptionalOtherString"
253253
| }
254254
|}"""
255255
.trimMargin()
256256
val dataClass =
257257
DataClassWithNestedParameterizedDataClass(
258258
"myId",
259259
DataClassWithNestedParameterized(
260-
DataClassParameterized(4.2, "myString", listOf(DataClassEmbedded("embedded1"))), "myOtherString"))
260+
DataClassParameterized(4.2, "myString", listOf(DataClassEmbedded("embedded1"))),
261+
"myOtherString",
262+
"myOptionalOtherString"))
261263

262264
assertRoundTrips(expected, dataClass)
263265
}

bson-kotlin/src/test/kotlin/org/bson/codecs/kotlin/samples/DataClasses.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ data class DataClassWithNestedParameterizedDataClass(
8989

9090
data class DataClassWithNestedParameterized<A, B, C : Number>(
9191
val parameterizedDataClass: DataClassParameterized<C, A>,
92-
val other: B
92+
val other: B,
93+
val optionalOther: B?
9394
)
9495

9596
data class DataClassWithPair(val pair: Pair<String, Int>)

bson-kotlinx/src/test/kotlin/org/bson/codecs/kotlinx/KotlinSerializerCodecTest.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,15 +373,17 @@ class KotlinSerializerCodecTest {
373373
|"nestedParameterized": {
374374
| "parameterizedDataClass":
375375
| {"number": 4.2, "string": "myString", "parameterizedList": [{"name": "embedded1"}]},
376-
| "other": "myOtherString"
376+
| "other": "myOtherString", "optionalOther": "myOptionalOtherString"
377377
| }
378378
|}"""
379379
.trimMargin()
380380
val dataClass =
381381
DataClassWithNestedParameterizedDataClass(
382382
"myId",
383383
DataClassWithNestedParameterized(
384-
DataClassParameterized(4.2, "myString", listOf(DataClassEmbedded("embedded1"))), "myOtherString"))
384+
DataClassParameterized(4.2, "myString", listOf(DataClassEmbedded("embedded1"))),
385+
"myOtherString",
386+
"myOptionalOtherString"))
385387

386388
assertRoundTrips(expected, dataClass)
387389
}

bson-kotlinx/src/test/kotlin/org/bson/codecs/kotlinx/samples/DataClasses.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ data class DataClassWithNestedParameterizedDataClass(
120120
@Serializable
121121
data class DataClassWithNestedParameterized<A, B, C : Number>(
122122
val parameterizedDataClass: DataClassParameterized<C, A>,
123-
val other: B
123+
val other: B,
124+
val optionalOther: B?
124125
)
125126

126127
@Serializable data class DataClassWithPair(val pair: Pair<String, Int>)

0 commit comments

Comments
 (0)