|
| 1 | +// Visitor API has already been deprecated, but the error is being suppressed for now. |
| 2 | +@file:Suppress("DEPRECATION_ERROR") |
| 3 | + |
1 | 4 | package io.github.projectmapk.jackson.module.kogera |
2 | 5 |
|
3 | 6 | import kotlinx.metadata.ClassKind |
4 | 7 | import kotlinx.metadata.ClassName |
5 | | -import kotlinx.metadata.ExperimentalContextReceivers |
6 | | -import kotlinx.metadata.Flags |
7 | | -import kotlinx.metadata.KmClassExtensionVisitor |
8 | | -import kotlinx.metadata.KmClassVisitor |
| 8 | +import kotlinx.metadata.KmClass |
9 | 9 | import kotlinx.metadata.KmConstructor |
10 | | -import kotlinx.metadata.KmConstructorVisitor |
11 | | -import kotlinx.metadata.KmExtensionType |
12 | 10 | import kotlinx.metadata.KmFunction |
13 | | -import kotlinx.metadata.KmFunctionVisitor |
14 | 11 | import kotlinx.metadata.KmProperty |
15 | | -import kotlinx.metadata.KmPropertyVisitor |
16 | 12 | import kotlinx.metadata.KmType |
17 | | -import kotlinx.metadata.KmTypeAliasVisitor |
18 | | -import kotlinx.metadata.KmTypeParameterVisitor |
19 | | -import kotlinx.metadata.KmTypeVisitor |
20 | | -import kotlinx.metadata.KmVariance |
21 | | -import kotlinx.metadata.KmVersionRequirementVisitor |
22 | | -import kotlinx.metadata.internal.accept |
23 | | -import kotlinx.metadata.internal.metadata.jvm.deserialization.JvmProtoBufUtil |
24 | 13 | import kotlinx.metadata.jvm.getterSignature |
25 | 14 | import kotlinx.metadata.jvm.signature |
26 | 15 | import java.lang.reflect.Constructor |
27 | 16 | import java.lang.reflect.Field |
28 | 17 | import java.lang.reflect.Method |
29 | 18 | import kotlinx.metadata.internal.metadata.deserialization.Flags as ProtoFlags |
30 | 19 |
|
31 | | -// KmClassVisitor with all processing disabled as much as possible to reduce load |
32 | | -internal sealed class ReducedKmClassVisitor : KmClassVisitor() { |
33 | | - final override val delegate: KmClassVisitor? get() = null |
34 | | - |
35 | | - // from KmDeclarationContainerVisitor |
36 | | - override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor? = null |
37 | | - override fun visitProperty( |
38 | | - flags: Flags, |
39 | | - name: String, |
40 | | - getterFlags: Flags, |
41 | | - setterFlags: Flags |
42 | | - ): KmPropertyVisitor? = null |
43 | | - override fun visitTypeAlias(flags: Flags, name: String): KmTypeAliasVisitor? = null |
44 | | - override fun visitExtensions(type: KmExtensionType): KmClassExtensionVisitor? = null |
45 | | - |
46 | | - // from KmClassVisitor |
47 | | - override fun visit(flags: Flags, name: ClassName) {} |
48 | | - override fun visitTypeParameter( |
49 | | - flags: Flags, |
50 | | - name: String, |
51 | | - id: Int, |
52 | | - variance: KmVariance |
53 | | - ): KmTypeParameterVisitor? = null |
54 | | - override fun visitSupertype(flags: Flags): KmTypeVisitor? = null |
55 | | - override fun visitConstructor(flags: Flags): KmConstructorVisitor? = null |
56 | | - override fun visitCompanionObject(name: String) {} |
57 | | - override fun visitNestedClass(name: String) {} |
58 | | - override fun visitEnumEntry(name: String) {} |
59 | | - override fun visitSealedSubclass(name: ClassName) {} |
60 | | - override fun visitInlineClassUnderlyingPropertyName(name: String) {} |
61 | | - override fun visitInlineClassUnderlyingType(flags: Flags): KmTypeVisitor? = null |
62 | | - |
63 | | - @OptIn(ExperimentalContextReceivers::class) |
64 | | - override fun visitContextReceiverType(flags: Flags): KmTypeVisitor? = null |
65 | | - override fun visitVersionRequirement(): KmVersionRequirementVisitor? = null |
66 | | - override fun visitEnd() {} |
67 | | -} |
68 | | - |
69 | 20 | // Jackson Metadata Class |
70 | 21 | internal sealed interface JmClass { |
71 | 22 | class CompanionObject(declaringClass: Class<*>, companionObject: String) { |
72 | | - private class ReducedCompanionVisitor(companionClass: Class<*>) : ReducedKmClassVisitor() { |
73 | | - val functions: MutableList<KmFunction> = arrayListOf() |
74 | | - |
75 | | - init { |
76 | | - companionClass.getAnnotation(Metadata::class.java)!!.accept(this) |
77 | | - } |
78 | | - |
79 | | - override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor = KmFunction(flags, name) |
80 | | - .apply { functions.add(this) } |
81 | | - } |
82 | | - |
83 | 23 | private val companionField: Field = declaringClass.getDeclaredField(companionObject) |
84 | 24 | val type: Class<*> = companionField.type |
85 | 25 | val isAccessible: Boolean = companionField.isAccessible |
86 | | - private val functions by lazy { ReducedCompanionVisitor(type).functions } |
| 26 | + private val functions by lazy { type.toKmClass()!!.functions } |
87 | 27 | val instance: Any by lazy { |
88 | 28 | // To prevent the call from failing, save the initial value and then rewrite the flag. |
89 | 29 | if (!companionField.isAccessible) companionField.isAccessible = true |
@@ -111,34 +51,35 @@ internal sealed interface JmClass { |
111 | 51 |
|
112 | 52 | private class JmClassImpl( |
113 | 53 | clazz: Class<*>, |
114 | | - metadata: Metadata, |
| 54 | + kmClass: KmClass, |
115 | 55 | superJmClass: JmClass?, |
116 | 56 | interfaceJmClasses: List<JmClass> |
117 | | -) : ReducedKmClassVisitor(), JmClass { |
118 | | - private val allPropsMap: MutableMap<String, KmProperty> = mutableMapOf() |
| 57 | +) : JmClass { |
| 58 | + private val allPropsMap: Map<String, KmProperty> |
119 | 59 |
|
120 | 60 | // Defined as non-lazy because it is always read in both serialization and deserialization |
121 | 61 | override val properties: List<KmProperty> |
122 | 62 |
|
123 | | - private var companionPropName: String? = null |
124 | | - override lateinit var kind: ClassKind |
125 | | - override val constructors: MutableList<KmConstructor> = mutableListOf() |
126 | | - override val sealedSubclasses: MutableList<ClassName> = mutableListOf() |
127 | | - override var inlineClassUnderlyingType: KmType? = null |
| 63 | + private val companionPropName: String? = kmClass.companionObject |
| 64 | + override val kind: ClassKind = ClassKind.values()[ProtoFlags.CLASS_KIND.get(kmClass.flags).number] |
| 65 | + override val constructors: List<KmConstructor> = kmClass.constructors |
| 66 | + override val sealedSubclasses: List<ClassName> = kmClass.sealedSubclasses |
| 67 | + override val inlineClassUnderlyingType: KmType? = kmClass.inlineClassUnderlyingType |
128 | 68 |
|
129 | 69 | init { |
130 | | - metadata.accept(this) |
131 | | - |
132 | 70 | // Add properties of inherited classes and interfaces |
133 | 71 | // If an `interface` is implicitly implemented by an abstract class, |
134 | 72 | // it is necessary to obtain a more specific type, so always add it from the abstract class first. |
135 | | - (superJmClass as JmClassImpl?)?.allPropsMap?.forEach { |
136 | | - this.allPropsMap.putIfAbsent(it.key, it.value) |
| 73 | + val tempPropsMap = ((superJmClass as JmClassImpl?)?.allPropsMap?.toMutableMap() ?: mutableMapOf()).apply { |
| 74 | + kmClass.properties.forEach { |
| 75 | + this[it.name] = it |
| 76 | + } |
137 | 77 | } |
138 | | - @Suppress("UNCHECKED_CAST") |
139 | | - (interfaceJmClasses as List<JmClassImpl>).forEach { i -> |
140 | | - i.allPropsMap.forEach { |
141 | | - this.allPropsMap.putIfAbsent(it.key, it.value) |
| 78 | + |
| 79 | + allPropsMap = interfaceJmClasses.fold(tempPropsMap) { acc, cur -> |
| 80 | + val curProps = (cur as JmClassImpl).allPropsMap |
| 81 | + acc.apply { |
| 82 | + curProps.forEach { acc.putIfAbsent(it.key, it.value) } |
142 | 83 | } |
143 | 84 | } |
144 | 85 |
|
@@ -179,38 +120,11 @@ private class JmClassImpl( |
179 | 120 | val getterName = getter.name |
180 | 121 | return properties.find { it.getterSignature?.name == getterName } |
181 | 122 | } |
182 | | - |
183 | | - // KmClassVisitor |
184 | | - override fun visit(flags: Flags, name: ClassName) { |
185 | | - kind = ClassKind.values()[ProtoFlags.CLASS_KIND.get(flags).number] |
186 | | - } |
187 | | - |
188 | | - override fun visitProperty(flags: Flags, name: String, getterFlags: Flags, setterFlags: Flags): KmPropertyVisitor = |
189 | | - KmProperty(flags, name, getterFlags, setterFlags).apply { allPropsMap[name] = this } |
190 | | - |
191 | | - override fun visitConstructor(flags: Flags): KmConstructorVisitor = |
192 | | - KmConstructor(flags).apply { constructors.add(this) } |
193 | | - |
194 | | - override fun visitCompanionObject(name: String) { |
195 | | - this.companionPropName = name |
196 | | - } |
197 | | - |
198 | | - override fun visitSealedSubclass(name: ClassName) { |
199 | | - sealedSubclasses.add(name) |
200 | | - } |
201 | | - |
202 | | - override fun visitInlineClassUnderlyingType(flags: Flags): KmTypeVisitor = |
203 | | - KmType(flags).also { inlineClassUnderlyingType = it } |
204 | | -} |
205 | | - |
206 | | -private fun Metadata.accept(visitor: ReducedKmClassVisitor) { |
207 | | - val (strings, proto) = JvmProtoBufUtil.readClassDataFrom(data1.takeIf(Array<*>::isNotEmpty)!!, data2) |
208 | | - proto.accept(visitor, strings) |
209 | 123 | } |
210 | 124 |
|
211 | 125 | internal fun JmClass( |
212 | 126 | clazz: Class<*>, |
213 | | - metadata: Metadata, |
| 127 | + kmClass: KmClass, |
214 | 128 | superJmClass: JmClass?, |
215 | 129 | interfaceJmClasses: List<JmClass> |
216 | | -): JmClass = JmClassImpl(clazz, metadata, superJmClass, interfaceJmClasses) |
| 130 | +): JmClass = JmClassImpl(clazz, kmClass, superJmClass, interfaceJmClasses) |
0 commit comments