Skip to content

Commit a8323d3

Browse files
authored
Merge pull request #15 from ProjectMapK/refactors
Refactors
2 parents e908e0c + 6840228 commit a8323d3

File tree

6 files changed

+52
-70
lines changed

6 files changed

+52
-70
lines changed

src/main/kotlin/com/fasterxml/jackson/module/kotlin/InternalCommons.kt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ package com.fasterxml.jackson.module.kotlin
33
import com.fasterxml.jackson.databind.JsonMappingException
44
import kotlinx.metadata.KmClass
55
import kotlinx.metadata.KmValueParameter
6+
import kotlinx.metadata.jvm.JvmFieldSignature
67
import kotlinx.metadata.jvm.JvmMethodSignature
78
import kotlinx.metadata.jvm.KotlinClassHeader
89
import kotlinx.metadata.jvm.KotlinClassMetadata
910
import java.lang.reflect.Constructor
11+
import java.lang.reflect.Field
1012
import java.lang.reflect.Method
1113
import java.util.*
12-
import kotlin.reflect.KType
13-
import kotlin.reflect.jvm.jvmErasure
1414

1515
internal fun JsonMappingException.wrapWithPath(refFrom: Any?, refFieldName: String) = JsonMappingException.wrapWithPath(this, refFrom, refFieldName)
1616
internal fun JsonMappingException.wrapWithPath(refFrom: Any?, index: Int) = JsonMappingException.wrapWithPath(this, refFrom, index)
@@ -32,12 +32,10 @@ internal fun Int.toBitSet(): BitSet {
3232
internal fun Class<*>.isKotlinClass(): Boolean = declaredAnnotations.any { it is Metadata }
3333
internal fun Class<*>.isUnboxableValueClass() = annotations.any { it is JvmInline }
3434

35-
internal fun KType.erasedType(): Class<out Any> = this.jvmErasure.java
36-
37-
internal fun Class<*>.toKmClass(): KmClass = annotations
35+
internal fun Class<*>.toKmClass(): KmClass? = annotations
3836
.filterIsInstance<Metadata>()
39-
.first()
40-
.let {
37+
.firstOrNull()
38+
?.let {
4139
KotlinClassMetadata.read(
4240
KotlinClassHeader(
4341
it.kind,
@@ -49,7 +47,7 @@ internal fun Class<*>.toKmClass(): KmClass = annotations
4947
it.extraInt
5048
)
5149
) as KotlinClassMetadata.Class
52-
}.toKmClass()
50+
}?.toKmClass()
5351

5452
private val primitiveClassToDesc by lazy {
5553
mapOf(
@@ -81,6 +79,9 @@ internal fun Constructor<*>.toSignature(): JvmMethodSignature =
8179
internal fun Method.toSignature(): JvmMethodSignature =
8280
JvmMethodSignature(this.name, parameterTypes.toDescString() + this.returnType.descriptor)
8381

82+
internal fun Field.toSignature(): JvmFieldSignature =
83+
JvmFieldSignature(this.name, this.type.descriptor)
84+
8485
internal fun List<KmValueParameter>.hasVarargParam(): Boolean =
8586
lastOrNull()?.let { it.varargElementType != null } ?: false
8687

src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinAnnotationIntrospector.kt

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,21 @@ import com.fasterxml.jackson.databind.jsontype.NamedType
1515
import com.fasterxml.jackson.databind.ser.std.StdSerializer
1616
import com.fasterxml.jackson.module.kotlin.ser.serializers.ValueClassBoxSerializer
1717
import com.fasterxml.jackson.module.kotlin.ser.serializers.ValueClassStaticJsonValueSerializer
18+
import kotlinx.metadata.Flag
19+
import kotlinx.metadata.KmClassifier
20+
import kotlinx.metadata.KmProperty
21+
import kotlinx.metadata.jvm.fieldSignature
22+
import kotlinx.metadata.jvm.getterSignature
23+
import kotlinx.metadata.jvm.setterSignature
1824
import java.lang.reflect.AccessibleObject
1925
import java.lang.reflect.Constructor
2026
import java.lang.reflect.Field
2127
import java.lang.reflect.Method
22-
import kotlin.reflect.KClass
2328
import kotlin.reflect.KFunction
24-
import kotlin.reflect.KMutableProperty1
25-
import kotlin.reflect.KProperty1
2629
import kotlin.reflect.KType
2730
import kotlin.reflect.full.createType
28-
import kotlin.reflect.full.declaredMemberProperties
29-
import kotlin.reflect.full.memberProperties
30-
import kotlin.reflect.jvm.javaGetter
31-
import kotlin.reflect.jvm.javaSetter
3231
import kotlin.reflect.jvm.javaType
3332
import kotlin.reflect.jvm.kotlinFunction
34-
import kotlin.reflect.jvm.kotlinProperty
3533

3634
internal class KotlinAnnotationIntrospector(
3735
private val context: Module.SetupContext,
@@ -81,34 +79,29 @@ internal class KotlinAnnotationIntrospector(
8179
// it will be serialized properly without doing anything.
8280
if (this.returnType.isUnboxableValueClass()) return null
8381
}
82+
val getterSignature = getter.toSignature()
83+
84+
val kotlinProperty =
85+
getter.declaringClass.toKmClass()?.properties?.find { it.getterSignature == getterSignature }
86+
87+
(kotlinProperty?.returnType?.classifier as? KmClassifier.Class)?.let { classifier ->
88+
// Since there was no way to directly determine whether returnType is a value class or not,
89+
// Class is restored and processed.
90+
// If the cost of this process is significant, consider caching it.
91+
runCatching {
92+
// Kotlin-specific types such as kotlin.String will cause an error,
93+
// but value classes will not cause an error, so ignore them
94+
Class.forName(classifier.name.replace(".", "$").replace("/", "."))
95+
}
96+
.getOrNull()
97+
?.takeIf { it.annotations.any { ann -> ann is JvmInline } }
98+
?.let { outerClazz ->
99+
val innerClazz = getter.returnType
84100

85-
val kotlinProperty = getter
86-
.declaringClass
87-
.kotlin
88-
.let {
89-
// KotlinReflectionInternalError is raised in GitHub167 test,
90-
// but it looks like an edge case, so it is ignored.
91-
try {
92-
it.memberProperties
93-
} catch (e: Error) {
94-
null
101+
ValueClassStaticJsonValueSerializer.createdOrNull(outerClazz, innerClazz)
102+
?: @Suppress("UNCHECKED_CAST") (ValueClassBoxSerializer(outerClazz, innerClazz))
95103
}
96-
}?.find { it.javaGetter == getter }
97-
98-
(kotlinProperty?.returnType?.classifier as? KClass<*>)
99-
?.takeIf { it.isValue }
100-
?.java
101-
?.let { outerClazz ->
102-
val innerClazz = getter.returnType
103-
104-
ValueClassStaticJsonValueSerializer.createdOrNull(outerClazz, innerClazz)
105-
?: @Suppress("UNCHECKED_CAST") (
106-
ValueClassBoxSerializer(
107-
outerClazz,
108-
innerClazz
109-
)
110-
)
111-
}
104+
}
112105
}
113106
// Ignore the case of AnnotatedField, because JvmField cannot be set in the field of value class.
114107
else -> null
@@ -131,8 +124,14 @@ internal class KotlinAnnotationIntrospector(
131124
}
132125

133126
private fun AnnotatedField.hasRequiredMarker(): Boolean? {
134-
val byAnnotation = (member as Field).isRequiredByAnnotation()
135-
val byNullability = (member as Field).kotlinProperty?.returnType?.isRequired()
127+
val member = member as Field
128+
129+
val byAnnotation = member.isRequiredByAnnotation()
130+
val fieldSignature = member.toSignature()
131+
val byNullability = member.declaringClass.toKmClass()
132+
?.properties
133+
?.find { it.fieldSignature == fieldSignature }
134+
?.let { !Flag.Type.IS_NULLABLE(it.returnType.flags) }
136135

137136
return requiredAnnotationOrNullability(byAnnotation, byNullability)
138137
}
@@ -155,20 +154,19 @@ internal class KotlinAnnotationIntrospector(
155154
return (this.annotations.firstOrNull { it.annotationClass.java == JsonProperty::class.java } as? JsonProperty)?.required
156155
}
157156

158-
// Since Kotlin's property has the same Type for each field, getter, and setter,
159-
// nullability can be determined from the returnType of KProperty.
160-
private fun KProperty1<*, *>.isRequiredByNullability() = returnType.isRequired()
157+
private fun KmProperty.isRequiredByNullability(): Boolean = !Flag.Type.IS_NULLABLE(this.returnType.flags)
161158

162159
// This could be a setter or a getter of a class property or
163160
// a setter-like/getter-like method.
164161
private fun AnnotatedMethod.hasRequiredMarker(): Boolean? = this.getRequiredMarkerFromCorrespondingAccessor()
165162
?: this.member.getRequiredMarkerFromAccessorLikeMethod()
166163

167164
private fun AnnotatedMethod.getRequiredMarkerFromCorrespondingAccessor(): Boolean? {
168-
member.declaringClass.kotlin.declaredMemberProperties.forEach { kProperty ->
169-
if (kProperty.javaGetter == this.member || (kProperty as? KMutableProperty1)?.javaSetter == this.member) {
165+
val memberSignature = member.toSignature()
166+
member.declaringClass.toKmClass()?.properties?.forEach { kmProperty ->
167+
if (kmProperty.getterSignature == memberSignature || kmProperty.setterSignature == memberSignature) {
170168
val byAnnotation = this.member.isRequiredByAnnotation()
171-
val byNullability = kProperty.isRequiredByNullability()
169+
val byNullability = kmProperty.isRequiredByNullability()
172170
return requiredAnnotationOrNullability(byAnnotation, byNullability)
173171
}
174172
}

src/main/kotlin/com/fasterxml/jackson/module/kotlin/ReflectionCache.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,17 @@ internal class ReflectionCache(reflectionCacheSize: Int) {
3737

3838
private val javaClassToKotlin = LRUMap<Class<Any>, KClass<Any>>(reflectionCacheSize, reflectionCacheSize)
3939
private val javaConstructorToKotlin = LRUMap<Constructor<Any>, KFunction<Any>>(reflectionCacheSize, reflectionCacheSize)
40-
private val javaMethodToKotlin = LRUMap<Method, KFunction<*>>(reflectionCacheSize, reflectionCacheSize)
4140
private val javaConstructorToValueCreator = LRUMap<Constructor<Any>, ConstructorValueCreator<*>>(reflectionCacheSize, reflectionCacheSize)
4241
private val javaMethodToValueCreator = LRUMap<Method, MethodValueCreator<*>>(reflectionCacheSize, reflectionCacheSize)
4342
private val javaConstructorIsCreatorAnnotated = LRUMap<AnnotatedConstructor, Boolean>(reflectionCacheSize, reflectionCacheSize)
4443
private val javaMemberIsRequired = LRUMap<AnnotatedMember, BooleanTriState?>(reflectionCacheSize, reflectionCacheSize)
45-
private val kotlinGeneratedMethod = LRUMap<AnnotatedMethod, Boolean>(reflectionCacheSize, reflectionCacheSize)
4644

4745
fun kotlinFromJava(key: Class<Any>): KClass<Any> = javaClassToKotlin.get(key)
4846
?: key.kotlin.let { javaClassToKotlin.putIfAbsent(key, it) ?: it }
4947

5048
fun kotlinFromJava(key: Constructor<Any>): KFunction<Any>? = javaConstructorToKotlin.get(key)
5149
?: key.kotlinFunction?.let { javaConstructorToKotlin.putIfAbsent(key, it) ?: it }
5250

53-
fun kotlinFromJava(key: Method): KFunction<*>? = javaMethodToKotlin.get(key)
54-
?: key.kotlinFunction?.let { javaMethodToKotlin.putIfAbsent(key, it) ?: it }
55-
5651
/**
5752
* return null if...
5853
* - can't get kotlinFunction
@@ -87,7 +82,4 @@ internal class ReflectionCache(reflectionCacheSize: Int) {
8782

8883
fun javaMemberIsRequired(key: AnnotatedMember, calc: (AnnotatedMember) -> Boolean?): Boolean? = javaMemberIsRequired.get(key)?.value
8984
?: calc(key).let { javaMemberIsRequired.putIfAbsent(key, BooleanTriState.fromBoolean(it))?.value ?: it }
90-
91-
fun isKotlinGeneratedMethod(key: AnnotatedMethod, calc: (AnnotatedMethod) -> Boolean): Boolean = kotlinGeneratedMethod.get(key)
92-
?: calc(key).let { kotlinGeneratedMethod.putIfAbsent(key, it) ?: it }
9385
}

src/main/kotlin/com/fasterxml/jackson/module/kotlin/deser/value_instantiator/KotlinValueInstantiator.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.Valu
1515
import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.ValueParameter
1616
import com.fasterxml.jackson.module.kotlin.isKotlinClass
1717
import com.fasterxml.jackson.module.kotlin.wrapWithPath
18-
import kotlin.reflect.KParameter
19-
import kotlin.reflect.jvm.javaType
2018

2119
internal class KotlinValueInstantiator(
2220
src: StdValueInstantiator,
@@ -104,13 +102,6 @@ internal class KotlinValueInstantiator(
104102
return valueCreator.callBy(bucket)
105103
}
106104

107-
private fun KParameter.isPrimitive(): Boolean {
108-
return when (val javaType = type.javaType) {
109-
is Class<*> -> javaType.isPrimitive
110-
else -> false
111-
}
112-
}
113-
114105
private fun SettableBeanProperty.hasInjectableValueId(): Boolean = injectableValueId != null
115106
}
116107

src/main/kotlin/com/fasterxml/jackson/module/kotlin/deser/value_instantiator/creator/ConstructorValueCreator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal class ConstructorValueCreator<T : Any>(private val constructor: Constru
2222
// To prevent the call from failing, save the initial value and then rewrite the flag.
2323
if (!isAccessible) constructor.isAccessible = true
2424

25-
val declaringKmClass: KmClass = declaringClass.toKmClass()
25+
val declaringKmClass: KmClass = declaringClass.toKmClass()!!
2626

2727
val constructorParameters = constructor.toSignature().desc.let { desc ->
2828
// Compare only desc for performance

src/main/kotlin/com/fasterxml/jackson/module/kotlin/deser/value_instantiator/creator/MethodValueCreator.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal class MethodValueCreator<T>(private val method: Method) : ValueCreator<
2323

2424
init {
2525
val declaringClass = method.declaringClass
26-
companionField = declaringClass.getDeclaredField(declaringClass.toKmClass().companionObject!!)
26+
companionField = declaringClass.getDeclaredField(declaringClass.toKmClass()!!.companionObject!!)
2727

2828
// region: about accessibility
2929
isAccessible = method.isAccessible && companionField.isAccessible
@@ -35,7 +35,7 @@ internal class MethodValueCreator<T>(private val method: Method) : ValueCreator<
3535

3636
// region: read kotlin metadata information
3737
companionObjectClass = companionField.type
38-
val companionKmClass: KmClass = companionObjectClass.toKmClass()
38+
val companionKmClass: KmClass = companionObjectClass.toKmClass()!!
3939
val kmFunction: KmFunction = run {
4040
val signature = method.toSignature()
4141
companionKmClass.functions.first { signature == it.signature }

0 commit comments

Comments
 (0)