@@ -12,6 +12,21 @@ import java.util.concurrent.ConcurrentHashMap
12
12
typealias DocWriter = () -> Any
13
13
typealias InlineModuleCreator = (Symbol , Writable ) -> Unit
14
14
15
+
16
+ /* *
17
+ * Initializes RustCrate -> InnerModule data structure.
18
+ */
19
+ fun RustCrate.initializeInlineModuleWriter (debugMode : Boolean ): InnerModule =
20
+ crateToInlineModule
21
+ .getOrPut(this ) { InnerModule (debugMode) }
22
+
23
+ /* *
24
+ * Returns the InnerModule for the given RustCrate
25
+ */
26
+ fun RustCrate.getInlineModuleWriter () : InnerModule {
27
+ return crateToInlineModule.getOrPut(this ) { InnerModule (false ) }
28
+ }
29
+
15
30
/* *
16
31
* Returns a function that can be used to create an inline module writer.
17
32
*/
@@ -23,6 +38,80 @@ fun RustCrate.createInlineModuleCreator(): InlineModuleCreator {
23
38
}
24
39
}
25
40
41
+ /* *
42
+ * If the passed in `shape` is a synthetic extracted shape resulting from a constrained struct member,
43
+ * the `Writable` is called using the structure's builder module. Otherwise the `Writable` is called
44
+ * using the given `module`.
45
+ */
46
+ fun RustCrate.withModuleOrWithStructureBuilderModule (
47
+ module : RustModule ,
48
+ shape : Shape ,
49
+ codegenContext : ServerCodegenContext ,
50
+ codeWritable : Writable ,
51
+ ) {
52
+ // All structure constrained-member-shapes code is generated inside the structure builder's module.
53
+ val parentAndInlineModuleInfo =
54
+ shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, ! codegenContext.settings.codegenConfig.publicConstrainedTypes)
55
+ if (parentAndInlineModuleInfo == null ) {
56
+ this .withModule(module, codeWritable)
57
+ } else {
58
+ val (parent, inline) = parentAndInlineModuleInfo
59
+ val inlineWriter = this .getInlineModuleWriter()
60
+
61
+ inlineWriter.withInlineModuleHierarchyUsingCrate(this , parent) {
62
+ inlineWriter.withInlineModuleHierarchy(this , inline) {
63
+ codeWritable(this )
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ /* *
70
+ * If the passed in `shape` is a synthetic extracted shape resulting from a constrained struct member,
71
+ * the `Writable` is called using the structure's builder module. Otherwise the `Writable` is called
72
+ * using shape's `module`.
73
+ */
74
+ fun RustCrate.useShapeWriterOrUseWithStructureBuilder (
75
+ shape : Shape ,
76
+ codegenContext : ServerCodegenContext ,
77
+ docWriter : DocWriter ? = null,
78
+ writable : Writable ,
79
+ ) {
80
+ // All structure constrained-member-shapes code is generated inside the structure builder's module.
81
+ val parentAndInlineModuleInfo =
82
+ shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, ! codegenContext.settings.codegenConfig.publicConstrainedTypes)
83
+ if (parentAndInlineModuleInfo == null ) {
84
+ docWriter?.invoke()
85
+ this .useShapeWriter(shape, writable)
86
+ } else {
87
+ val (parent, inline) = parentAndInlineModuleInfo
88
+ val inlineWriter = this .getInlineModuleWriter()
89
+
90
+ inlineWriter.withInlineModuleHierarchyUsingCrate(this , parent) {
91
+ inlineWriter.withInlineModuleHierarchy(this , inline) {
92
+ writable(this )
93
+ }
94
+ }
95
+ }
96
+ }
97
+
98
+ /* *
99
+ * Given a `RustWriter` calls the `Writable` using a `RustWriter` for the `inlineModule`
100
+ */
101
+ fun RustCrate.withInMemoryInlineModule (
102
+ outerWriter : RustWriter ,
103
+ inlineModule : RustModule .LeafModule ,
104
+ docWriter : DocWriter ? ,
105
+ codeWritable : Writable ,
106
+ ) {
107
+ check(inlineModule.isInline()) {
108
+ " module has to be an inline module for it to be used with the InlineModuleWriter"
109
+ }
110
+ this .getInlineModuleWriter().withInlineModuleHierarchy(outerWriter, inlineModule, docWriter) {
111
+ codeWritable(this )
112
+ }
113
+ }
114
+
26
115
fun RustWriter.createTestInlineModuleCreator (): InlineModuleCreator {
27
116
return { symbol: Symbol , writable: Writable ->
28
117
this .withInlineModule(symbol.module()) {
@@ -31,14 +120,27 @@ fun RustWriter.createTestInlineModuleCreator(): InlineModuleCreator {
31
120
}
32
121
}
33
122
34
-
123
+ /* *
124
+ * Maintains the `RustWriter` that has been created for a `RustModule.LeafModule`.
125
+ */
35
126
private data class InlineModuleWithWriter (val inlineModule : RustModule .LeafModule , val writer : RustWriter )
36
127
128
+ /* *
129
+ * For each RustCrate a separate mapping of inline-module to `RustWriter` is maintained.
130
+ */
131
+ private val crateToInlineModule: ConcurrentHashMap <RustCrate , InnerModule > =
132
+ ConcurrentHashMap ()
133
+
37
134
class InnerModule (private val debugMode : Boolean ) {
38
- private val topLevelModuleWriters: HashMap <RustWriter , MutableList < InlineModuleWithWriter >> = hashMapOf ()
135
+ private val topLevelModuleWriters: MutableSet <RustWriter > = mutableSetOf ()
39
136
private val inlineModuleWriters: HashMap <RustWriter , MutableList <InlineModuleWithWriter >> = hashMapOf()
40
137
private val docWriters: HashMap <RustModule .LeafModule , MutableList <DocWriter >> = hashMapOf()
41
138
private val writerCreator = RustWriter .factory(debugMode)
139
+ private val emptyLineCount: Int = writerCreator
140
+ .apply (" lines-it-always-writes.rs" , " crate" )
141
+ .toString()
142
+ .split(" \n " )[0 ]
143
+ .length
42
144
43
145
private fun createNewInlineModule (): RustWriter {
44
146
val writer = writerCreator.apply (" unknown-module-would-never-be-written.rs" , " crate" )
@@ -67,7 +169,9 @@ class InnerModule(private val debugMode : Boolean) {
67
169
val bottomMost = hierarchy.removeLast()
68
170
69
171
// In case it is a top level module that has been passed (e.g. ModelsModule, OutputsModule) then
70
- // register it with the topLevel HashMap and call the writable on it.
172
+ // register it with the topLevel writers and call the writable on it. Otherwise, go over the
173
+ // complete hierarchy, registering each of the inner modules and then call the `Writable`
174
+ // with the bottom most inline module that has been passed.
71
175
if (hierarchy.isNotEmpty()) {
72
176
val topMost = hierarchy.removeFirst()
73
177
@@ -80,8 +184,7 @@ class InnerModule(private val debugMode : Boolean) {
80
184
81
185
withInlineModule(writer, bottomMost as RustModule .LeafModule , docWriter, writable)
82
186
}
83
- }
84
- else {
187
+ } else {
85
188
check(! bottomMost.isInline()) {
86
189
" there is only one module in hierarchy so it has to be non-inlined"
87
190
}
@@ -137,55 +240,63 @@ class InnerModule(private val debugMode : Boolean) {
137
240
* Writes out each inline module's code (`toString`) to the respective top level `RustWriter`.
138
241
*/
139
242
fun render () {
140
- fun renderDescendents (writer : RustWriter , inMemoryWriter : RustWriter ) {
141
- val innerModuleCode = inMemoryWriter.toString()
142
- writer.writeWithNoFormatting(innerModuleCode)
243
+ fun writeInlineCode (rustWriter : RustWriter , code : String ) {
244
+ val inlineCode = code.drop(emptyLineCount)
245
+ rustWriter.writeWithNoFormatting(inlineCode)
246
+ }
247
+
248
+ fun renderDescendents (topLevelWriter : RustWriter , inMemoryWriter : RustWriter ) {
249
+ // Traverse all descendent inline modules and render them.
250
+ inlineModuleWriters[inMemoryWriter]?.forEach {
251
+ writeDocs(it.inlineModule)
143
252
144
- inlineModuleWriters.get(inMemoryWriter)?.forEach {
145
- writeDocs(it.inlineModule, it.writer)
146
- writer.withInlineModule(it.inlineModule) {
253
+ topLevelWriter.withInlineModule(it.inlineModule) {
254
+ writeInlineCode(this , it.writer.toString())
147
255
renderDescendents(this , it.writer)
148
256
}
149
- it.writer.dependencies.forEach { dep -> writer.addDependency(dep) }
257
+
258
+ // Add dependencies introduced by the inline module to the
259
+ it.writer.dependencies.forEach { dep -> topLevelWriter.addDependency(dep) }
150
260
}
151
261
}
152
262
153
263
// Go over all the top level modules, create an `inlineModule` on the `RustWriter`
154
264
// and call the descendent hierarchy renderer using the `inlineModule::RustWriter`
155
- topLevelModuleWriters.forEach { (outerWriter, list) ->
156
- list.forEach {
157
- writeDocs(it.inlineModule, it.writer)
158
- outerWriter.withInlineModule(it.inlineModule) {
159
- renderDescendents(this , it.writer)
160
- }
161
- it.writer.dependencies.forEach { dep -> outerWriter.addDependency(dep) }
265
+ topLevelModuleWriters.forEach {
266
+ val inlineModuleWithWriter = inlineModuleWriters[it]
267
+ if (inlineModuleWithWriter != null ) {
268
+ renderDescendents(it, it)
162
269
}
163
270
}
164
271
}
165
272
273
+ /* *
274
+ * Given the inline-module returns an existing `RustWriter`, or if that inline module
275
+ * has never been registered before then a new `RustWriter` is created and returned.
276
+ */
166
277
private fun getWriter (outerWriter : RustWriter , inlineModule : RustModule .LeafModule ): RustWriter {
167
278
// Is this one of our inner writers?
168
279
val nestedModuleWriter = inlineModuleWriters[outerWriter]
169
280
if (nestedModuleWriter != null ) {
170
281
return findOrAddToList(nestedModuleWriter, inlineModule)
171
282
}
172
283
173
- val existing = topLevelModuleWriters[outerWriter]
174
- return if (existing == null ) {
175
- val inlineWriter = createNewInlineModule()
176
- topLevelModuleWriters[outerWriter] = mutableListOf (InlineModuleWithWriter (inlineModule, inlineWriter))
177
- inlineWriter
178
- } else {
179
- return findOrAddToList(existing, inlineModule)
180
- }
284
+ val inlineWriters = registerTopMostWriter(outerWriter)
285
+ return findOrAddToList(inlineWriters, inlineModule)
181
286
}
182
287
183
- private fun registerTopMostWriter (outerWriter : RustWriter ) {
184
- topLevelModuleWriters.getOrPut(outerWriter) {
185
- mutableListOf ()
186
- }
288
+ /* *
289
+ * Records the root of a dependency graph of inline modules.
290
+ */
291
+ private fun registerTopMostWriter (outerWriter : RustWriter ) : MutableList <InlineModuleWithWriter > {
292
+ topLevelModuleWriters.add(outerWriter)
293
+ return inlineModuleWriters.getOrPut(outerWriter) { mutableListOf () }
187
294
}
188
295
296
+ /* *
297
+ * Either gets a new `RustWriter` for the inline module or creates a new one and adds it to
298
+ * the list of inline modules.
299
+ */
189
300
private fun findOrAddToList (
190
301
inlineModuleList : MutableList <InlineModuleWithWriter >,
191
302
lookForModule : RustModule .LeafModule
@@ -202,98 +313,9 @@ class InnerModule(private val debugMode : Boolean) {
202
313
}
203
314
}
204
315
205
- private fun writeDocs (innerModule : RustModule .LeafModule , rustWriter : RustWriter ) {
316
+ private fun writeDocs (innerModule : RustModule .LeafModule ) {
206
317
docWriters[innerModule]?.forEach{
207
318
it()
208
319
}
209
320
}
210
321
}
211
-
212
- // A map of RustCrate to InlineModule
213
- private val crateToInlineModule: ConcurrentHashMap <RustCrate , InnerModule > =
214
- ConcurrentHashMap ()
215
- private val writerToCrateLookup: ConcurrentHashMap <RustWriter , RustCrate > =
216
- ConcurrentHashMap ()
217
-
218
- fun RustCrate.initializeInlineModuleWriter (codegenContext : ServerCodegenContext ): InnerModule =
219
- crateToInlineModule
220
- .getOrPut(this ) { InnerModule (codegenContext.settings.codegenConfig.debugMode) }
221
-
222
- fun RustCrate.getInlineModuleWriter () : InnerModule {
223
- return crateToInlineModule.getOrPut(this ) { InnerModule (false ) }
224
- }
225
-
226
-
227
- /* *
228
- * If the passed in `shape` is a synthetic extracted shape resulting from a constrained struct member,
229
- * the `Writable` is called using the structure's builder module. Otherwise the `Writable` is called
230
- * using the given `module`.
231
- */
232
- fun RustCrate.withModuleOrWithStructureBuilderModule (
233
- module : RustModule ,
234
- shape : Shape ,
235
- codegenContext : ServerCodegenContext ,
236
- codeWritable : Writable ,
237
- ) {
238
- // All structure constrained-member-shapes code is generated inside the structure builder's module.
239
- val parentAndInlineModuleInfo =
240
- shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, ! codegenContext.settings.codegenConfig.publicConstrainedTypes)
241
- if (parentAndInlineModuleInfo == null ) {
242
- this .withModule(module, codeWritable)
243
- } else {
244
- val (parent, inline) = parentAndInlineModuleInfo
245
- val inlineWriter = this .getInlineModuleWriter()
246
-
247
- inlineWriter.withInlineModuleHierarchyUsingCrate(this , parent) {
248
- inlineWriter.withInlineModuleHierarchy(this , inline) {
249
- codeWritable(this )
250
- }
251
- }
252
- }
253
- }
254
-
255
- /* *
256
- * If the passed in `shape` is a synthetic extracted shape resulting from a constrained struct member,
257
- * the `Writable` is called using the structure's builder module. Otherwise the `Writable` is called
258
- * using shape's `module`.
259
- */
260
- fun RustCrate.useShapeWriterOrUseWithStructureBuilder (
261
- shape : Shape ,
262
- codegenContext : ServerCodegenContext ,
263
- docWriter : DocWriter ? = null,
264
- writable : Writable ,
265
- ) {
266
- // All structure constrained-member-shapes code is generated inside the structure builder's module.
267
- val parentAndInlineModuleInfo =
268
- shape.getParentAndInlineModuleForConstrainedMember(codegenContext.symbolProvider, ! codegenContext.settings.codegenConfig.publicConstrainedTypes)
269
- if (parentAndInlineModuleInfo == null ) {
270
- docWriter?.invoke()
271
- this .useShapeWriter(shape, writable)
272
- } else {
273
- val (parent, inline) = parentAndInlineModuleInfo
274
- val inlineWriter = this .getInlineModuleWriter()
275
-
276
- inlineWriter.withInlineModuleHierarchyUsingCrate(this , parent) {
277
- inlineWriter.withInlineModuleHierarchy(this , inline) {
278
- writable(this )
279
- }
280
- }
281
- }
282
- }
283
-
284
- /* *
285
- * Given a `RustWriter` calls the `Writable` using a `RustWriter` for the `inlineModule`
286
- */
287
- fun RustCrate.withInMemoryInlineModule (
288
- outerWriter : RustWriter ,
289
- inlineModule : RustModule .LeafModule ,
290
- docWriter : DocWriter ? ,
291
- codeWritable : Writable ,
292
- ) {
293
- check(inlineModule.isInline()) {
294
- " module has to be an inline module for it to be used with the InlineModuleWriter"
295
- }
296
- this .getInlineModuleWriter().withInlineModuleHierarchy(outerWriter, inlineModule, docWriter) {
297
- codeWritable(this )
298
- }
299
- }
0 commit comments