@@ -35,16 +35,42 @@ import { sortTypeDefinitions } from '../model/utils'
35
35
import { argv } from 'zx'
36
36
import { join } from 'path'
37
37
38
+ export class ExpansionConfig {
39
+ unwrappedTypes ?: TypeName [ ] | string [ ]
40
+ inlinedTypes ?: TypeName [ ] | string [ ]
41
+ }
42
+
38
43
/**
39
- * Expand all generics by creating new concrete types for every instanciation of a generic type.
44
+ * Expand all generics by creating new concrete types for every instantiation of a generic type.
40
45
*
41
46
* The resulting model has no generics anymore. Top-level generic parameters (e.g. SearchRequest's TDocument) are
42
47
* replaced by user_defined_data.
43
48
*
44
49
* @param inputModel the input model
50
+ * @param unwrappedTypes types that should not be expanded but unwrapped as their generic parameter.
45
51
* @return a new model with generics expanded
46
52
*/
47
- export function expandGenerics ( inputModel : Model ) : Model {
53
+ export function expandGenerics ( inputModel : Model , config ?: ExpansionConfig ) : Model {
54
+
55
+ const typesToUnwrap = new Set < string > ( )
56
+ const typesToInline : Set < string > = new Set < string > ( )
57
+
58
+ for ( const name of config ?. unwrappedTypes || [ ] ) {
59
+ if ( typeof name === 'string' ) {
60
+ typesToUnwrap . add ( name )
61
+ } else {
62
+ typesToUnwrap . add ( nameKey ( name ) )
63
+ }
64
+ }
65
+
66
+ for ( const name of config ?. inlinedTypes || [ ] ) {
67
+ if ( typeof name === 'string' ) {
68
+ typesToInline . add ( name )
69
+ } else {
70
+ typesToInline . add ( nameKey ( name ) )
71
+ }
72
+ }
73
+
48
74
const typesSeen = new Set < string > ( )
49
75
50
76
const types = new Array < TypeDefinition > ( )
@@ -306,6 +332,34 @@ export function expandGenerics (inputModel: Model): Model {
306
332
}
307
333
308
334
case 'instance_of' : {
335
+ const valueOfType = nameKey ( value . type )
336
+
337
+ // If this is a type that has to be unwrapped, return its generic parameter's type
338
+ if ( typesToUnwrap . has ( valueOfType ) ) {
339
+ // @ts -ignore
340
+ return expandValueOf ( value . generics [ 0 ] , mappings )
341
+ }
342
+
343
+ // If this is a type that has to be inlined
344
+ if ( typesToInline . has ( valueOfType ) ) {
345
+ // It has to be an alias (e.g. Stringified or WithNullValue
346
+ const inlinedTypeDef = inputTypeByName . get ( valueOfType )
347
+ if ( ! inlinedTypeDef || inlinedTypeDef . kind !== 'type_alias' ) {
348
+ throw Error ( `Inlined type ${ valueOfType } should be an alias definition` )
349
+ }
350
+
351
+ const inlineMappings = new Map < string , ValueOf > ( )
352
+ for ( let i = 0 ; i < ( inlinedTypeDef . generics ?. length || 0 ) ; i ++ ) {
353
+ // @ts -ignore
354
+ const source = inlinedTypeDef . generics [ i ]
355
+ // @ts -ignore
356
+ const dest = value . generics [ i ] ;
357
+ inlineMappings . set ( nameKey ( source ) , dest )
358
+ }
359
+
360
+ return expandValueOf ( inlinedTypeDef . type , inlineMappings ) ;
361
+ }
362
+
309
363
// If this is a generic parameter, return its mapping
310
364
const mapping = mappings . get ( nameKey ( value . type ) )
311
365
if ( mapping !== undefined ) {
@@ -430,7 +484,10 @@ async function expandGenericsFromFile (inPath: string, outPath: string): Promise
430
484
)
431
485
432
486
const inputModel = JSON . parse ( inputText )
433
- const outputModel = expandGenerics ( inputModel )
487
+ const outputModel = expandGenerics ( inputModel , {
488
+ // unwrappedTypes: ["_spec_utils:Stringified"],
489
+ inlinedTypes : [ "_spec_utils:WithNullValue" ]
490
+ } )
434
491
435
492
await writeFile (
436
493
outPath ,
0 commit comments