@@ -7,6 +7,7 @@ import dev.adamko.kxstsgen.core.TsElement
7
7
import dev.adamko.kxstsgen.core.TsElementConverter
8
8
import dev.adamko.kxstsgen.core.TsElementId
9
9
import dev.adamko.kxstsgen.core.TsElementIdConverter
10
+ import dev.adamko.kxstsgen.core.TsLiteral
10
11
import dev.adamko.kxstsgen.core.TsMapTypeConverter
11
12
import dev.adamko.kxstsgen.core.TsTypeRef
12
13
import dev.adamko.kxstsgen.core.TsTypeRefConverter
@@ -18,71 +19,117 @@ import kotlinx.serialization.descriptors.SerialDescriptor
18
19
* Generate TypeScript from [`@Serializable`][Serializable] Kotlin.
19
20
*
20
21
* The output can be controlled by the settings in [config],
21
- * or by setting hardcoded values in [serializerDescriptors ] or [descriptorElements ],
22
+ * or by setting hardcoded values in [serializerDescriptorOverrides ] or [descriptorOverrides ],
22
23
* or changed by overriding any converter.
23
24
*
24
25
* @param[config] General settings that affect how KxTsGen works
25
- * @param[descriptorsExtractor] Given a [KSerializer], extract all [SerialDescriptor]s
26
- * @param[elementIdConverter] Create an [TsElementId] from a [SerialDescriptor]
27
- * @param[mapTypeConverter] Decides how [Map]s should be converted
28
- * @param[typeRefConverter] Creates [TsTypeRef]s
29
- * @param[elementConverter] Converts [SerialDescriptor]s to [TsElement]s
30
26
* @param[sourceCodeGenerator] Convert [TsElement]s to TypeScript source code
31
27
*/
32
28
open class KxsTsGenerator (
33
29
open val config : KxsTsConfig = KxsTsConfig (),
34
30
35
- open val descriptorsExtractor : SerializerDescriptorsExtractor = SerializerDescriptorsExtractor .Default ,
31
+ open val sourceCodeGenerator : KxsTsSourceCodeGenerator = KxsTsSourceCodeGenerator .Default (config),
32
+ ) {
33
+
34
+
35
+ val serializerDescriptorOverrides: MutableMap <KSerializer <* >, Set <SerialDescriptor >> =
36
+ mutableMapOf ()
37
+
38
+ val descriptorOverrides: MutableMap <SerialDescriptor , TsElement > = mutableMapOf ()
39
+
40
+
41
+ open val descriptorsExtractor = object : SerializerDescriptorsExtractor {
42
+ val extractor: SerializerDescriptorsExtractor = SerializerDescriptorsExtractor .Default
43
+ val cache: MutableMap <KSerializer <* >, Set <SerialDescriptor >> = mutableMapOf ()
44
+
45
+ override fun invoke (serializer : KSerializer <* >): Set <SerialDescriptor > =
46
+ cache.getOrPut(serializer) {
47
+ serializerDescriptorOverrides[serializer] ? : extractor(serializer)
48
+ }
49
+ }
50
+
51
+
52
+ val elementIdConverter: TsElementIdConverter = object : TsElementIdConverter {
53
+ private val converter: TsElementIdConverter = TsElementIdConverter .Default
54
+ private val cache: MutableMap <SerialDescriptor , TsElementId > = mutableMapOf ()
55
+
56
+ override fun invoke (descriptor : SerialDescriptor ): TsElementId =
57
+ cache.getOrPut(descriptor) {
58
+ when (val override = descriptorOverrides[descriptor]) {
59
+ is TsDeclaration -> override .id
60
+ else -> converter(descriptor)
61
+ }
62
+ }
63
+ }
36
64
37
- open val elementIdConverter : TsElementIdConverter = TsElementIdConverter .Default ,
38
65
39
- open val mapTypeConverter : TsMapTypeConverter = TsMapTypeConverter .Default ,
66
+ val mapTypeConverter: TsMapTypeConverter = object : TsMapTypeConverter {
67
+ private val converter = TsMapTypeConverter .Default
68
+ private val cache: MutableMap <Pair <SerialDescriptor , SerialDescriptor >, TsLiteral .TsMap .Type > =
69
+ mutableMapOf ()
70
+
71
+ override fun invoke (
72
+ keyDescriptor : SerialDescriptor ,
73
+ valDescriptor : SerialDescriptor ,
74
+ ): TsLiteral .TsMap .Type =
75
+ cache.getOrPut(keyDescriptor to valDescriptor) {
76
+ when (val override = descriptorOverrides[keyDescriptor]) {
77
+ is TsLiteral .TsMap -> override .type
78
+ else -> converter(keyDescriptor, valDescriptor)
79
+ }
80
+ }
81
+ }
82
+
83
+
84
+ val typeRefConverter: TsTypeRefConverter = object : TsTypeRefConverter {
85
+ private val converter = TsTypeRefConverter .Default (elementIdConverter, mapTypeConverter)
86
+ val cache: MutableMap <SerialDescriptor , TsTypeRef > = mutableMapOf ()
40
87
41
- open val typeRefConverter : TsTypeRefConverter =
42
- TsTypeRefConverter .Default (elementIdConverter, mapTypeConverter),
88
+ override fun invoke (descriptor : SerialDescriptor ): TsTypeRef =
89
+ cache.getOrPut(descriptor) {
90
+ when (val override = descriptorOverrides[descriptor]) {
91
+ null -> converter(descriptor)
92
+ is TsLiteral -> TsTypeRef .Literal (override , descriptor.isNullable)
93
+ is TsDeclaration -> TsTypeRef .Declaration (override .id, null , descriptor.isNullable)
94
+ }
95
+ }
96
+ }
43
97
44
- open val elementConverter : TsElementConverter =
45
- TsElementConverter .Default (
98
+
99
+ val elementConverter: TsElementConverter = object : TsElementConverter {
100
+ private val converter = TsElementConverter .Default (
46
101
elementIdConverter,
47
102
mapTypeConverter,
48
103
typeRefConverter,
49
- ),
50
-
51
- open val sourceCodeGenerator : KxsTsSourceCodeGenerator = KxsTsSourceCodeGenerator .Default (config),
52
- ) {
104
+ )
105
+ val cache: MutableMap <SerialDescriptor , Set <TsElement >> = mutableMapOf ()
106
+
107
+ override fun invoke (descriptor : SerialDescriptor ): Set <TsElement > =
108
+ cache.getOrPut(descriptor) {
109
+ when (val override = descriptorOverrides[descriptor]) {
110
+ null -> converter(descriptor)
111
+ else -> setOf (override )
112
+ }
113
+ }
114
+ }
53
115
54
- /* *
55
- * Stateful cache of all [descriptors][SerialDescriptor] extracted from a
56
- * [serializer][KSerializer].
57
- *
58
- * To customise the descriptors that a serializer produces, set value into this map.
59
- */
60
- open val serializerDescriptors: MutableMap <KSerializer <* >, Set <SerialDescriptor >> = mutableMapOf ()
61
-
62
- /* *
63
- * Cache of all [elements][TsElement] that are created from any [descriptor][SerialDescriptor].
64
- *
65
- * To customise the elements that a descriptor produces, set value into this map.
66
- */
67
- open val descriptorElements: MutableMap <SerialDescriptor , Set <TsElement >> = mutableMapOf ()
68
116
69
117
open fun generate (vararg serializers : KSerializer <* >): String {
70
118
return serializers
71
119
.toSet()
72
120
73
121
// 1. get all SerialDescriptors from a KSerializer
74
- .flatMap { serializer ->
75
- serializerDescriptors.getOrPut(serializer) { descriptorsExtractor(serializer) }
76
- }
122
+ .flatMap { serializer -> descriptorsExtractor(serializer) }
77
123
.toSet()
78
124
79
125
// 2. convert each SerialDescriptor to some TsElements
80
- .flatMap { descriptor ->
81
- descriptorElements.getOrPut(descriptor) { elementConverter(descriptor) }
82
- }
126
+ .flatMap { descriptor -> elementConverter(descriptor) }
83
127
.toSet()
84
128
129
+ // 3. group by namespaces
85
130
.groupBy { element -> sourceCodeGenerator.groupElementsBy(element) }
131
+
132
+ // 4. convert to source code
86
133
.mapValues { (_, elements) ->
87
134
elements
88
135
.filterIsInstance<TsDeclaration >()
0 commit comments