Skip to content

Commit fad911c

Browse files
committed
Add unwrapping and inlining to expand-generics
1 parent eabe414 commit fad911c

File tree

1 file changed

+60
-3
lines changed

1 file changed

+60
-3
lines changed

compiler/src/transform/expand-generics.ts

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,42 @@ import { sortTypeDefinitions } from '../model/utils'
3535
import { argv } from 'zx'
3636
import { join } from 'path'
3737

38+
export class ExpansionConfig {
39+
unwrappedTypes?: TypeName[] | string[]
40+
inlinedTypes?: TypeName[] | string[]
41+
}
42+
3843
/**
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.
4045
*
4146
* The resulting model has no generics anymore. Top-level generic parameters (e.g. SearchRequest's TDocument) are
4247
* replaced by user_defined_data.
4348
*
4449
* @param inputModel the input model
50+
* @param unwrappedTypes types that should not be expanded but unwrapped as their generic parameter.
4551
* @return a new model with generics expanded
4652
*/
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+
4874
const typesSeen = new Set<string>()
4975

5076
const types = new Array<TypeDefinition>()
@@ -306,6 +332,34 @@ export function expandGenerics (inputModel: Model): Model {
306332
}
307333

308334
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+
309363
// If this is a generic parameter, return its mapping
310364
const mapping = mappings.get(nameKey(value.type))
311365
if (mapping !== undefined) {
@@ -430,7 +484,10 @@ async function expandGenericsFromFile (inPath: string, outPath: string): Promise
430484
)
431485

432486
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+
})
434491

435492
await writeFile(
436493
outPath,

0 commit comments

Comments
 (0)