@azure-tools/typespec-go 0.8.7 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/codegen.go/src/core/clientFactory.js +5 -5
  2. package/dist/codegen.go/src/core/clientFactory.js.map +1 -1
  3. package/dist/codegen.go/src/core/cloudConfig.js +1 -1
  4. package/dist/codegen.go/src/core/cloudConfig.js.map +1 -1
  5. package/dist/codegen.go/src/core/constants.js +1 -1
  6. package/dist/codegen.go/src/core/constants.js.map +1 -1
  7. package/dist/codegen.go/src/core/example.d.ts +1 -1
  8. package/dist/codegen.go/src/core/example.d.ts.map +1 -1
  9. package/dist/codegen.go/src/core/example.js +34 -36
  10. package/dist/codegen.go/src/core/example.js.map +1 -1
  11. package/dist/codegen.go/src/core/helpers.d.ts +4 -13
  12. package/dist/codegen.go/src/core/helpers.d.ts.map +1 -1
  13. package/dist/codegen.go/src/core/helpers.js +16 -37
  14. package/dist/codegen.go/src/core/helpers.js.map +1 -1
  15. package/dist/codegen.go/src/core/imports.d.ts +39 -3
  16. package/dist/codegen.go/src/core/imports.d.ts.map +1 -1
  17. package/dist/codegen.go/src/core/imports.js +68 -18
  18. package/dist/codegen.go/src/core/imports.js.map +1 -1
  19. package/dist/codegen.go/src/core/interfaces.d.ts.map +1 -1
  20. package/dist/codegen.go/src/core/interfaces.js +1 -2
  21. package/dist/codegen.go/src/core/interfaces.js.map +1 -1
  22. package/dist/codegen.go/src/core/models.d.ts +0 -1
  23. package/dist/codegen.go/src/core/models.d.ts.map +1 -1
  24. package/dist/codegen.go/src/core/models.js +163 -84
  25. package/dist/codegen.go/src/core/models.js.map +1 -1
  26. package/dist/codegen.go/src/core/operations.js +18 -18
  27. package/dist/codegen.go/src/core/operations.js.map +1 -1
  28. package/dist/codegen.go/src/core/options.js +14 -6
  29. package/dist/codegen.go/src/core/options.js.map +1 -1
  30. package/dist/codegen.go/src/core/polymorphics.d.ts +1 -2
  31. package/dist/codegen.go/src/core/polymorphics.d.ts.map +1 -1
  32. package/dist/codegen.go/src/core/polymorphics.js +13 -12
  33. package/dist/codegen.go/src/core/polymorphics.js.map +1 -1
  34. package/dist/codegen.go/src/core/responses.js +34 -11
  35. package/dist/codegen.go/src/core/responses.js.map +1 -1
  36. package/dist/codegen.go/src/core/time.d.ts +1 -2
  37. package/dist/codegen.go/src/core/time.d.ts.map +1 -1
  38. package/dist/codegen.go/src/core/time.js +51 -18
  39. package/dist/codegen.go/src/core/time.js.map +1 -1
  40. package/dist/codegen.go/src/core/version.js +1 -1
  41. package/dist/codegen.go/src/core/version.js.map +1 -1
  42. package/dist/codegen.go/src/core/xmlAdditionalProps.js +2 -2
  43. package/dist/codegen.go/src/core/xmlAdditionalProps.js.map +1 -1
  44. package/dist/codegen.go/src/emitter.js +6 -5
  45. package/dist/codegen.go/src/emitter.js.map +1 -1
  46. package/dist/codegen.go/src/fake/factory.d.ts +1 -1
  47. package/dist/codegen.go/src/fake/factory.d.ts.map +1 -1
  48. package/dist/codegen.go/src/fake/factory.js +9 -8
  49. package/dist/codegen.go/src/fake/factory.js.map +1 -1
  50. package/dist/codegen.go/src/fake/internal.d.ts +1 -1
  51. package/dist/codegen.go/src/fake/internal.d.ts.map +1 -1
  52. package/dist/codegen.go/src/fake/internal.js +3 -3
  53. package/dist/codegen.go/src/fake/internal.js.map +1 -1
  54. package/dist/codegen.go/src/fake/servers.d.ts +1 -1
  55. package/dist/codegen.go/src/fake/servers.d.ts.map +1 -1
  56. package/dist/codegen.go/src/fake/servers.js +127 -77
  57. package/dist/codegen.go/src/fake/servers.js.map +1 -1
  58. package/dist/codemodel.go/src/client.d.ts +13 -5
  59. package/dist/codemodel.go/src/client.d.ts.map +1 -1
  60. package/dist/codemodel.go/src/client.js +9 -5
  61. package/dist/codemodel.go/src/client.js.map +1 -1
  62. package/dist/codemodel.go/src/module.d.ts +29 -0
  63. package/dist/codemodel.go/src/module.d.ts.map +1 -1
  64. package/dist/codemodel.go/src/module.js +36 -0
  65. package/dist/codemodel.go/src/module.js.map +1 -1
  66. package/dist/codemodel.go/src/param.d.ts +4 -1
  67. package/dist/codemodel.go/src/param.d.ts.map +1 -1
  68. package/dist/codemodel.go/src/param.js +2 -1
  69. package/dist/codemodel.go/src/param.js.map +1 -1
  70. package/dist/codemodel.go/src/result.d.ts +1 -0
  71. package/dist/codemodel.go/src/result.d.ts.map +1 -1
  72. package/dist/codemodel.go/src/result.js +1 -0
  73. package/dist/codemodel.go/src/result.js.map +1 -1
  74. package/dist/codemodel.go/src/type.d.ts +23 -13
  75. package/dist/codemodel.go/src/type.d.ts.map +1 -1
  76. package/dist/codemodel.go/src/type.js +50 -28
  77. package/dist/codemodel.go/src/type.js.map +1 -1
  78. package/dist/typespec-go/src/emitter.d.ts.map +1 -1
  79. package/dist/typespec-go/src/emitter.js +9 -2
  80. package/dist/typespec-go/src/emitter.js.map +1 -1
  81. package/dist/typespec-go/src/tcgcadapter/adapter.d.ts +23 -2
  82. package/dist/typespec-go/src/tcgcadapter/adapter.d.ts.map +1 -1
  83. package/dist/typespec-go/src/tcgcadapter/adapter.js +96 -67
  84. package/dist/typespec-go/src/tcgcadapter/adapter.js.map +1 -1
  85. package/dist/typespec-go/src/tcgcadapter/clients.d.ts +11 -9
  86. package/dist/typespec-go/src/tcgcadapter/clients.d.ts.map +1 -1
  87. package/dist/typespec-go/src/tcgcadapter/clients.js +141 -100
  88. package/dist/typespec-go/src/tcgcadapter/clients.js.map +1 -1
  89. package/dist/typespec-go/src/tcgcadapter/errors.d.ts +1 -1
  90. package/dist/typespec-go/src/tcgcadapter/errors.d.ts.map +1 -1
  91. package/dist/typespec-go/src/tcgcadapter/errors.js +2 -1
  92. package/dist/typespec-go/src/tcgcadapter/errors.js.map +1 -1
  93. package/dist/typespec-go/src/tcgcadapter/types.d.ts +11 -4
  94. package/dist/typespec-go/src/tcgcadapter/types.d.ts.map +1 -1
  95. package/dist/typespec-go/src/tcgcadapter/types.js +38 -33
  96. package/dist/typespec-go/src/tcgcadapter/types.js.map +1 -1
  97. package/package.json +5 -5
@@ -22,9 +22,9 @@ export function generateModels(pkg, options) {
22
22
  };
23
23
  }
24
24
  // this list of packages to import
25
- const modelImports = new ImportManager();
26
- const serdeImports = new ImportManager();
27
- let modelText = helpers.contentPreamble(helpers.getPackageName(pkg));
25
+ const modelImports = new ImportManager(pkg);
26
+ const serdeImports = new ImportManager(pkg);
27
+ let modelText = helpers.contentPreamble(pkg);
28
28
  // we do model generation first as it can add imports to the imports list
29
29
  const modelDefs = generateModelDefs(modelImports, serdeImports, pkg, options);
30
30
  modelText += modelImports.text();
@@ -127,7 +127,7 @@ export function generateModels(pkg, options) {
127
127
  }
128
128
  let serdeText = '';
129
129
  if (serdeTextBody.length > 0) {
130
- serdeText = helpers.contentPreamble(helpers.getPackageName(pkg));
130
+ serdeText = helpers.contentPreamble(pkg);
131
131
  serdeText += serdeImports.text();
132
132
  serdeText += serdeTextBody;
133
133
  }
@@ -136,6 +136,15 @@ export function generateModels(pkg, options) {
136
136
  serDe: serdeText
137
137
  };
138
138
  }
139
+ /**
140
+ * converts model types to an array of ModelDef types
141
+ *
142
+ * @param modelImports the import manager for the models file
143
+ * @param serdeImports the import manager for the models_serde file
144
+ * @param pkg contains the package content
145
+ * @param options the Go emitter options
146
+ * @returns an array of ModelDefs
147
+ */
139
148
  function generateModelDefs(modelImports, serdeImports, pkg, options) {
140
149
  const models = pkg.models;
141
150
  const modelDefs = new Array();
@@ -174,16 +183,16 @@ function generateModelDefs(modelImports, serdeImports, pkg, options) {
174
183
  field.docs.description = descriptionMods.join('; ');
175
184
  }
176
185
  const serDeFormat = helpers.getSerDeFormat(model, pkg);
177
- const modelDef = new ModelDef(model.name, serDeFormat, model.fields, model.docs);
178
- for (const field of values(modelDef.Fields)) {
179
- modelImports.addImportForType(field.type);
186
+ const modelDef = new ModelDef(model, serDeFormat);
187
+ for (const field of modelDef.Model.fields) {
188
+ modelImports.addForType(field.type);
180
189
  }
181
190
  if (model.kind === 'model' && serDeFormat === 'XML' && !model.annotations.omitSerDeMethods) {
182
191
  serdeImports.add('encoding/xml');
183
192
  let needsDateTimeMarshalling = false;
184
193
  let byteArrayFormat = false;
185
194
  for (const field of values(model.fields)) {
186
- serdeImports.addImportForType(field.type);
195
+ serdeImports.addForType(field.type);
187
196
  if (field.type.kind === 'time') {
188
197
  needsDateTimeMarshalling = true;
189
198
  }
@@ -193,14 +202,14 @@ function generateModelDefs(modelImports, serdeImports, pkg, options) {
193
202
  }
194
203
  // due to differences in XML marshallers/unmarshallers, we use different codegen than for JSON
195
204
  if (needsDateTimeMarshalling || model.xml?.wrapper || needsXMLArrayMarshalling(model) || byteArrayFormat) {
196
- generateXMLMarshaller(model, modelDef, serdeImports);
205
+ generateXMLMarshaller(modelDef, serdeImports);
197
206
  if (needsDateTimeMarshalling || byteArrayFormat) {
198
- generateXMLUnmarshaller(model, modelDef, serdeImports);
207
+ generateXMLUnmarshaller(modelDef, serdeImports);
199
208
  }
200
209
  }
201
210
  else if (needsXMLDictionaryHelper(model)) {
202
- generateXMLMarshaller(model, modelDef, serdeImports);
203
- generateXMLUnmarshaller(model, modelDef, serdeImports);
211
+ generateXMLMarshaller(modelDef, serdeImports);
212
+ generateXMLUnmarshaller(modelDef, serdeImports);
204
213
  }
205
214
  modelDefs.push(modelDef);
206
215
  continue;
@@ -216,8 +225,8 @@ function generateModelDefs(modelImports, serdeImports, pkg, options) {
216
225
  modelDef.SerDe.needsJSONPopulateMultipart = true;
217
226
  }
218
227
  else if (!model.annotations.omitSerDeMethods) {
219
- generateJSONMarshaller(model, modelDef, serdeImports);
220
- generateJSONUnmarshaller(model, modelDef, serdeImports, options);
228
+ generateJSONMarshaller(modelDef, serdeImports);
229
+ generateJSONUnmarshaller(modelDef, serdeImports, options);
221
230
  }
222
231
  modelDefs.push(modelDef);
223
232
  }
@@ -245,8 +254,8 @@ function generateDiscriminatorMarkerMethod(type, modelDef) {
245
254
  const typeName = type.rootType.name;
246
255
  const receiver = modelDef.receiverName();
247
256
  const interfaceMethod = `Get${typeName}`;
248
- let method = `func (${receiver} *${modelDef.Name}) ${interfaceMethod}() *${typeName} {`;
249
- if (type.rootType.name === modelDef.Name) {
257
+ let method = `func (${receiver} *${modelDef.Model.name}) ${interfaceMethod}() *${typeName} {`;
258
+ if (type.rootType.name === modelDef.Model.name) {
250
259
  // the marker method is on the discriminator itself, so just return the receiver
251
260
  method += ` return ${receiver} }\n\n`;
252
261
  }
@@ -259,13 +268,13 @@ function generateDiscriminatorMarkerMethod(type, modelDef) {
259
268
  }
260
269
  method += '\t}\n}\n\n';
261
270
  }
262
- modelDef.Methods.push({ name: interfaceMethod, desc: `${interfaceMethod} implements the ${type.name} interface for type ${modelDef.Name}.`, text: method });
271
+ modelDef.Methods.push({ name: interfaceMethod, desc: `${interfaceMethod} implements the ${type.name} interface for type ${modelDef.Model.name}.`, text: method });
263
272
  }
264
273
  function generateToMultipartForm(modelDef) {
265
274
  const receiver = modelDef.receiverName();
266
- let method = `func (${receiver} ${modelDef.Name}) toMultipartFormData() (map[string]any, error) {\n`;
275
+ let method = `func (${receiver} ${modelDef.Model.name}) toMultipartFormData() (map[string]any, error) {\n`;
267
276
  method += '\tobjectMap := make(map[string]any)\n';
268
- for (const field of modelDef.Fields) {
277
+ for (const field of modelDef.Model.fields) {
269
278
  const fieldType = helpers.recursiveUnwrapMapSlice(field.type);
270
279
  let setField;
271
280
  let star = '';
@@ -284,28 +293,43 @@ function generateToMultipartForm(modelDef) {
284
293
  method += setField;
285
294
  }
286
295
  method += '\treturn objectMap, nil\n}\n\n';
287
- modelDef.SerDe.methods.push({ name: 'toMultipartFormData', desc: `toMultipartFormData converts ${modelDef.Name} to multipart/form data.`, text: method });
296
+ modelDef.SerDe.methods.push({ name: 'toMultipartFormData', desc: `toMultipartFormData converts ${modelDef.Model.name} to multipart/form data.`, text: method });
288
297
  }
289
- function generateJSONMarshaller(modelType, modelDef, imports) {
290
- if (modelType.kind === 'model' && modelType.fields.length === 0) {
298
+ /**
299
+ * generates the MarshalJSON method for the provided type.
300
+ * the method impl is added to modelDef.SerDe.methods.
301
+ *
302
+ * @param modelDef the type for which to emit the method
303
+ * @param imports the import manager currently in scope
304
+ */
305
+ function generateJSONMarshaller(modelDef, imports) {
306
+ if (modelDef.Model.kind === 'model' && modelDef.Model.fields.length === 0) {
291
307
  // non-discriminated types without content don't need a custom marshaller.
292
308
  // there is a case in network where child is allOf base and child has no properties.
293
309
  return;
294
310
  }
295
311
  imports.add('encoding/json');
296
- const typeName = modelDef.Name;
312
+ const typeName = modelDef.Model.name;
297
313
  const receiver = modelDef.receiverName();
298
314
  let marshaller = `func (${receiver} ${typeName}) MarshalJSON() ([]byte, error) {\n`;
299
315
  marshaller += '\tobjectMap := make(map[string]any)\n';
300
- marshaller += generateJSONMarshallerBody(modelType, modelDef, receiver, imports);
316
+ marshaller += generateJSONMarshallerBody(modelDef, receiver, imports);
301
317
  marshaller += '\treturn json.Marshal(objectMap)\n';
302
318
  marshaller += '}\n\n';
303
319
  modelDef.SerDe.methods.push({ name: 'MarshalJSON', desc: `MarshalJSON implements the json.Marshaller interface for type ${typeName}.`, text: marshaller });
304
320
  }
305
- function generateJSONMarshallerBody(modelType, modelDef, receiver, imports) {
321
+ /**
322
+ * generates the contents of MarshalJSON that encode the target type
323
+ *
324
+ * @param modelDef the type being encoded
325
+ * @param receiver the name of the receiver in the MarshalJSON method
326
+ * @param imports the import manager currently in scope
327
+ * @returns the text for encoding the target type
328
+ */
329
+ function generateJSONMarshallerBody(modelDef, receiver, imports) {
306
330
  let marshaller = '';
307
331
  let addlProps;
308
- for (const field of values(modelType.fields)) {
332
+ for (const field of modelDef.Model.fields) {
309
333
  if (field.type.kind === 'map' && field.annotations.isAdditionalProperties) {
310
334
  addlProps = field.type;
311
335
  continue;
@@ -407,26 +431,43 @@ function generateJSONMarshallerBody(modelType, modelDef, receiver, imports) {
407
431
  }
408
432
  return marshaller;
409
433
  }
410
- function generateJSONUnmarshaller(modelType, modelDef, imports, options) {
434
+ /**
435
+ * generates the UnmarshalJSON method for the provided type.
436
+ * the method impl is added to modelDef.SerDe.methods.
437
+ *
438
+ * @param modelDef the type for which to emit the method
439
+ * @param imports the import manager currently in scope
440
+ * @param options the Go emitter options
441
+ */
442
+ function generateJSONUnmarshaller(modelDef, imports, options) {
411
443
  // there's a corner-case where a derived type might not add any new fields (Cookiecuttershark).
412
444
  // in this case skip adding the unmarshaller as it's not necessary and doesn't compile.
413
- if (modelDef.Fields.length === 0) {
445
+ if (modelDef.Model.fields.length === 0) {
414
446
  return;
415
447
  }
416
448
  imports.add('encoding/json');
417
449
  imports.add('fmt');
418
- const typeName = modelDef.Name;
450
+ const typeName = modelDef.Model.name;
419
451
  const receiver = modelDef.receiverName();
420
452
  let unmarshaller = `func (${receiver} *${typeName}) UnmarshalJSON(data []byte) error {\n`;
421
453
  unmarshaller += '\tvar rawMsg map[string]json.RawMessage\n';
422
454
  unmarshaller += '\tif err := json.Unmarshal(data, &rawMsg); err != nil {\n';
423
455
  unmarshaller += `\t\treturn fmt.Errorf("unmarshalling type %T: %v", ${receiver}, err)\n`;
424
456
  unmarshaller += '\t}\n';
425
- unmarshaller += generateJSONUnmarshallerBody(modelType, modelDef, receiver, imports, options);
457
+ unmarshaller += generateJSONUnmarshallerBody(modelDef, receiver, imports, options);
426
458
  unmarshaller += '}\n\n';
427
459
  modelDef.SerDe.methods.push({ name: 'UnmarshalJSON', desc: `UnmarshalJSON implements the json.Unmarshaller interface for type ${typeName}.`, text: unmarshaller });
428
460
  }
429
- function generateJSONUnmarshallerBody(modelType, modelDef, receiver, imports, options) {
461
+ /**
462
+ * generates the contents of UnmarshalJSON that decode the target type
463
+ *
464
+ * @param modelDef the type being decoded
465
+ * @param receiver the receiver for the UnmarshalJSON method
466
+ * @param imports the import manager currently in scope
467
+ * @param options the Go emitter options
468
+ * @returns the text for decoding the target type
469
+ */
470
+ function generateJSONUnmarshallerBody(modelDef, receiver, imports, options) {
430
471
  // we almost always need to have an error check when unmarshaling the values.
431
472
  // however, fields that are raw JSON don't require any unmarshaling. so, if all
432
473
  // of the fields in a type are raw JSON, then the error check isn't necessary
@@ -438,10 +479,10 @@ function generateJSONUnmarshallerBody(modelType, modelDef, receiver, imports, op
438
479
  if (!addlProps.valueTypeByValue) {
439
480
  ref = '&';
440
481
  }
441
- addlPropsText += `${tab}\t\t\t${receiver}.AdditionalProperties = ${go.getTypeDeclaration(addlProps)}{}\n`;
482
+ addlPropsText += `${tab}\t\t\t${receiver}.AdditionalProperties = ${go.getTypeDeclaration(addlProps, modelDef.Model.pkg)}{}\n`;
442
483
  addlPropsText += `${tab}\t\t}\n`;
443
484
  addlPropsText += `${tab}\t\tif val != nil {\n`;
444
- let auxType = go.getTypeDeclaration(addlProps.valueType);
485
+ let auxType = go.getTypeDeclaration(addlProps.valueType, modelDef.Model.pkg);
445
486
  let assignment = `${ref}aux`;
446
487
  if (addlProps.valueType.kind === 'time') {
447
488
  imports.add('time');
@@ -460,14 +501,14 @@ function generateJSONUnmarshallerBody(modelType, modelDef, receiver, imports, op
460
501
  let unmarshalBody = '';
461
502
  let addlProps;
462
503
  unmarshalBody += '\t\tswitch key {\n';
463
- for (const field of values(modelType.fields)) {
504
+ for (const field of modelDef.Model.fields) {
464
505
  if (field.type.kind === 'map' && field.annotations.isAdditionalProperties) {
465
506
  addlProps = field.type;
466
507
  continue;
467
508
  }
468
509
  unmarshalBody += `\t\tcase "${field.serializedName}":\n`;
469
510
  if (hasDiscriminatorInterface(field.type)) {
470
- unmarshalBody += generateDiscriminatorUnmarshaller(field, receiver);
511
+ unmarshalBody += generateDiscriminatorUnmarshaller(modelDef.Model, field, receiver);
471
512
  needsErrCheck = true;
472
513
  }
473
514
  else if (field.type.kind === 'time') {
@@ -581,7 +622,7 @@ function hasDiscriminatorInterface(item) {
581
622
  }
582
623
  }
583
624
  // returns the text for unmarshalling a discriminated type
584
- function generateDiscriminatorUnmarshaller(field, receiver) {
625
+ function generateDiscriminatorUnmarshaller(modelType, field, receiver) {
585
626
  const startingIndentation = '\t\t\t';
586
627
  const propertyName = field.name;
587
628
  // these are the simple, non-nested cases (e.g. IterfaceType, []InterfaceType, map[string]InterfaceType)
@@ -597,12 +638,12 @@ function generateDiscriminatorUnmarshaller(field, receiver) {
597
638
  // nested case (e.g. [][]InterfaceType, map[string]map[string]InterfaceType etc)
598
639
  // first, unmarshal the raw data
599
640
  const rawTargetVar = `${field.serializedName}Raw`;
600
- let text = `${startingIndentation}var ${rawTargetVar} ${recursiveGetDiscriminatorTypeName(field.type, true)}\n`;
641
+ let text = `${startingIndentation}var ${rawTargetVar} ${recursiveGetDiscriminatorTypeName(modelType, field.type, true)}\n`;
601
642
  text += `${startingIndentation}if err = json.Unmarshal(val, &${rawTargetVar}); err != nil {\n`;
602
643
  text += `${startingIndentation}\treturn err\n${startingIndentation}}\n`;
603
644
  // create a local instantiation of the final type
604
645
  const finalTargetVar = field.serializedName;
605
- let finalTargetCtor = recursiveGetDiscriminatorTypeName(field.type, false);
646
+ let finalTargetCtor = recursiveGetDiscriminatorTypeName(modelType, field.type, false);
606
647
  if (field.type.kind === 'slice') {
607
648
  finalTargetCtor = `make(${finalTargetCtor}, len(${rawTargetVar}))`;
608
649
  }
@@ -612,7 +653,7 @@ function generateDiscriminatorUnmarshaller(field, receiver) {
612
653
  }
613
654
  text += `${startingIndentation}${finalTargetVar} := ${finalTargetCtor}\n`;
614
655
  // now populate the final type
615
- text += recursivePopulateDiscriminator(field.type, receiver, rawTargetVar, finalTargetVar, startingIndentation, 1);
656
+ text += recursivePopulateDiscriminator(modelType, field.type, receiver, rawTargetVar, finalTargetVar, startingIndentation, 1);
616
657
  // finally, assign the final target to the property
617
658
  text += `${startingIndentation}${receiver}.${propertyName} = ${finalTargetVar}\n`;
618
659
  return text;
@@ -620,25 +661,36 @@ function generateDiscriminatorUnmarshaller(field, receiver) {
620
661
  // constructs the type name for a nested discriminated type
621
662
  // raw e.g. map[string]json.RawMessage, []json.RawMessage etc
622
663
  // !raw e.g. map[string]map[string]InterfaceType, [][]InterfaceType etc
623
- function recursiveGetDiscriminatorTypeName(item, raw) {
664
+ function recursiveGetDiscriminatorTypeName(modelType, item, raw) {
624
665
  // when raw is true, stop recursing at the level before the leaf schema
625
666
  if (item.kind === 'slice') {
626
667
  if (!raw || item.elementType.kind !== 'interface') {
627
- return `[]${recursiveGetDiscriminatorTypeName(item.elementType, raw)}`;
668
+ return `[]${recursiveGetDiscriminatorTypeName(modelType, item.elementType, raw)}`;
628
669
  }
629
670
  }
630
671
  else if (item.kind === 'map') {
631
672
  if (!raw || item.valueType.kind !== 'interface') {
632
- return `map[string]${recursiveGetDiscriminatorTypeName(item.valueType, raw)}`;
673
+ return `map[string]${recursiveGetDiscriminatorTypeName(modelType, item.valueType, raw)}`;
633
674
  }
634
675
  }
635
676
  if (raw) {
636
677
  return 'json.RawMessage';
637
678
  }
638
- return go.getTypeDeclaration(item);
679
+ return go.getTypeDeclaration(item, modelType.pkg);
639
680
  }
640
- // recursively constructs the text to populate a nested discriminator
641
- function recursivePopulateDiscriminator(item, receiver, rawSrc, dest, indent, nesting) {
681
+ /**
682
+ * recursively constructs the text to populate a nested discriminator
683
+ *
684
+ * @param modelType the type that contains item
685
+ * @param item the type for which to create the population
686
+ * @param receiver the name of the receiver for the method to contain the expression
687
+ * @param rawSrc contains the raw unmarshaled JSON source
688
+ * @param dest the variable that will contain the result of the expression
689
+ * @param indent the current level of indentation (increases with each recursive call)
690
+ * @param nesting the current level of nesting (increments with each recursive call)
691
+ * @returns the text populating the discriminator
692
+ */
693
+ function recursivePopulateDiscriminator(modelType, item, receiver, rawSrc, dest, indent, nesting) {
642
694
  let text = '';
643
695
  let interfaceName = '';
644
696
  let targetType = '';
@@ -646,50 +698,57 @@ function recursivePopulateDiscriminator(item, receiver, rawSrc, dest, indent, ne
646
698
  if (item.elementType.kind !== 'interface') {
647
699
  if (nesting > 1) {
648
700
  // at nestling level 1, the destination var was already created in generateDiscriminatorUnmarshaller()
649
- text += `${indent}${dest} = make(${recursiveGetDiscriminatorTypeName(item, false)}, len(${rawSrc}))\n`;
701
+ text += `${indent}${dest} = make(${recursiveGetDiscriminatorTypeName(modelType, item, false)}, len(${rawSrc}))\n`;
650
702
  }
651
703
  text += `${indent}for i${nesting} := range ${rawSrc} {\n`;
652
704
  rawSrc = `${rawSrc}[i${nesting}]`; // source becomes each element in the source slice
653
705
  dest = `${dest}[i${nesting}]`; // update destination to each element in the destination slice
654
- text += recursivePopulateDiscriminator(item.elementType, receiver, rawSrc, dest, indent + '\t', nesting + 1);
706
+ text += recursivePopulateDiscriminator(modelType, item.elementType, receiver, rawSrc, dest, indent + '\t', nesting + 1);
655
707
  text += `${indent}}\n`;
656
708
  return text;
657
709
  }
658
710
  // we're at leaf node - 1, so get the interface from the element's type
659
- interfaceName = go.getTypeDeclaration(item.elementType);
711
+ interfaceName = go.getTypeDeclaration(item.elementType, modelType.pkg);
660
712
  targetType = 'Array';
661
713
  }
662
714
  else if (item.kind === 'map') {
663
715
  if (item.valueType.kind !== 'interface') {
664
716
  if (nesting > 1) {
665
717
  // at nestling level 1, the destination var was already created in generateDiscriminatorUnmarshaller()
666
- text += `${indent}${dest} = ${recursiveGetDiscriminatorTypeName(item, false)}{}\n`;
718
+ text += `${indent}${dest} = ${recursiveGetDiscriminatorTypeName(modelType, item, false)}{}\n`;
667
719
  }
668
720
  text += `${indent}for k${nesting}, v${nesting} := range ${rawSrc} {\n`;
669
721
  rawSrc = `v${nesting}`; // source becomes the current value in the source map
670
722
  dest = `${dest}[k${nesting}]`; // update destination to the destination map's value for the current key
671
- text += recursivePopulateDiscriminator(item.valueType, receiver, rawSrc, dest, indent + '\t', nesting + 1);
723
+ text += recursivePopulateDiscriminator(modelType, item.valueType, receiver, rawSrc, dest, indent + '\t', nesting + 1);
672
724
  text += `${indent}}\n`;
673
725
  return text;
674
726
  }
675
727
  // we're at leaf node - 1, so get the interface from the element's type
676
- interfaceName = go.getTypeDeclaration(item.valueType);
728
+ interfaceName = go.getTypeDeclaration(item.valueType, modelType.pkg);
677
729
  targetType = 'Map';
678
730
  }
679
731
  text += `${indent}${dest}, err = unmarshal${interfaceName}${targetType}(${rawSrc})\n`;
680
732
  text += `${indent}if err != nil {\n${indent}\treturn fmt.Errorf("unmarshalling type %T: %v", ${receiver}, err)\n${indent}}\n`;
681
733
  return text;
682
734
  }
683
- function generateXMLMarshaller(modelType, modelDef, imports) {
735
+ /**
736
+ * generates an implementation of MarshalXML for the provided type.
737
+ * the method impl is added to modelDef.SerDe.methods.
738
+ *
739
+ * @param modelDef the type for which to implement MarshalXML
740
+ * @param imports the import manager currently in scope
741
+ */
742
+ function generateXMLMarshaller(modelDef, imports) {
684
743
  // only needed for types with time.Time, maps, or where the XML name doesn't match the type name
685
744
  const receiver = modelDef.receiverName();
686
- const desc = `MarshalXML implements the xml.Marshaller interface for type ${modelDef.Name}.`;
687
- let text = `func (${receiver} ${modelDef.Name}) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {\n`;
688
- if (modelType.xml?.wrapper) {
689
- text += `\tstart.Name.Local = "${modelType.xml.wrapper}"\n`;
745
+ const desc = `MarshalXML implements the xml.Marshaller interface for type ${modelDef.Model.name}.`;
746
+ let text = `func (${receiver} ${modelDef.Model.name}) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {\n`;
747
+ if (modelDef.Model.xml?.wrapper) {
748
+ text += `\tstart.Name.Local = "${modelDef.Model.xml.wrapper}"\n`;
690
749
  }
691
- text += generateAliasType(modelType, receiver, true);
692
- for (const field of values(modelDef.Fields)) {
750
+ text += generateAliasType(modelDef.Model, receiver, true);
751
+ for (const field of modelDef.Model.fields) {
693
752
  if (field.type.kind === 'slice') {
694
753
  text += `\tif ${receiver}.${field.name} != nil {\n`;
695
754
  text += `\t\taux.${field.name} = &${receiver}.${field.name}\n`;
@@ -710,16 +769,23 @@ function generateXMLMarshaller(modelType, modelDef, imports) {
710
769
  text += '}\n\n';
711
770
  modelDef.SerDe.methods.push({ name: 'MarshalXML', desc: desc, text: text });
712
771
  }
713
- function generateXMLUnmarshaller(modelType, modelDef, imports) {
772
+ /**
773
+ * generates an implementation of UnmarshalXML for the provided type.
774
+ * the method impl is added to modelDef.SerDe.methods.
775
+ *
776
+ * @param modelDef the type for which to implement UnmarshalXML
777
+ * @param imports the import manager currently in scope
778
+ */
779
+ function generateXMLUnmarshaller(modelDef, imports) {
714
780
  // non-polymorphic case, must be something with time.Time
715
781
  const receiver = modelDef.receiverName();
716
- const desc = `UnmarshalXML implements the xml.Unmarshaller interface for type ${modelDef.Name}.`;
717
- let text = `func (${receiver} *${modelDef.Name}) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error {\n`;
718
- text += generateAliasType(modelType, receiver, false);
782
+ const desc = `UnmarshalXML implements the xml.Unmarshaller interface for type ${modelDef.Model.name}.`;
783
+ let text = `func (${receiver} *${modelDef.Model.name}) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error {\n`;
784
+ text += generateAliasType(modelDef.Model, receiver, false);
719
785
  text += '\tif err := dec.DecodeElement(aux, &start); err != nil {\n';
720
786
  text += '\t\treturn err\n';
721
787
  text += '\t}\n';
722
- for (const field of values(modelDef.Fields)) {
788
+ for (const field of modelDef.Model.fields) {
723
789
  if (field.type.kind === 'time') {
724
790
  text += `\tif aux.${field.name} != nil && !(*time.Time)(aux.${field.name}).IsZero() {\n`;
725
791
  text += `\t\t${receiver}.${field.name} = (*time.Time)(aux.${field.name})\n\t}\n`;
@@ -740,13 +806,20 @@ function generateXMLUnmarshaller(modelType, modelDef, imports) {
740
806
  text += '}\n\n';
741
807
  modelDef.SerDe.methods.push({ name: 'UnmarshalXML', desc: desc, text: text });
742
808
  }
743
- // generates an alias type used by custom XML marshaller/unmarshaller
809
+ /**
810
+ * generates an alias type used by custom XML marshaller/unmarshaller
811
+ *
812
+ * @param modelType the type for which to create the alias
813
+ * @param receiver the name of the receiver for the type's serde method
814
+ * @param forMarshal when true, indicates type is to be used in a marshaller (else an unmarshaller)
815
+ * @returns the text for an initialized type alias
816
+ */
744
817
  function generateAliasType(modelType, receiver, forMarshal) {
745
818
  let text = `\ttype alias ${modelType.name}\n`;
746
819
  text += '\taux := &struct {\n';
747
820
  text += '\t\t*alias\n';
748
821
  for (const field of values(modelType.fields)) {
749
- const sn = getXMLSerialization(field, false);
822
+ const sn = getXMLSerialization(modelType, field);
750
823
  if (field.type.kind === 'time') {
751
824
  text += `\t\t${field.name} *${field.type.format} \`xml:"${sn}"\`\n`;
752
825
  }
@@ -754,7 +827,7 @@ function generateAliasType(modelType, receiver, forMarshal) {
754
827
  text += `\t\t${field.name} additionalProperties \`xml:"${sn}"\`\n`;
755
828
  }
756
829
  else if (field.type.kind === 'slice') {
757
- text += `\t\t${field.name} *${go.getTypeDeclaration(field.type)} \`xml:"${sn}"\`\n`;
830
+ text += `\t\t${field.name} *${go.getTypeDeclaration(field.type, modelType.pkg)} \`xml:"${sn}"\`\n`;
758
831
  }
759
832
  else if (field.type.kind === 'encodedBytes') {
760
833
  text += `\t\t${field.name} *string \`xml:"${sn}"\`\n`;
@@ -778,6 +851,7 @@ function generateAliasType(modelType, receiver, forMarshal) {
778
851
  text += '\t}\n';
779
852
  return text;
780
853
  }
854
+ /** used to track which serde helpers and methods are required for a struct */
781
855
  class SerDeInfo {
782
856
  methods;
783
857
  needsJSONPopulate;
@@ -794,27 +868,24 @@ class SerDeInfo {
794
868
  this.needsJSONPopulateMultipart = false;
795
869
  }
796
870
  }
797
- // represents model definition as a Go struct
871
+ /** represents model definition as a Go struct */
798
872
  class ModelDef {
799
- Name;
873
+ Model;
800
874
  Format;
801
- Docs;
802
- Fields;
803
875
  SerDe;
804
876
  Methods;
805
- constructor(name, format, fields, docs) {
806
- this.Name = name;
877
+ constructor(model, format) {
878
+ this.Model = model;
807
879
  this.Format = format;
808
- this.Docs = docs;
809
- this.Fields = fields;
810
880
  this.SerDe = new SerDeInfo();
811
881
  this.Methods = new Array();
812
882
  }
883
+ /** returns the text for the struct definition */
813
884
  text() {
814
- let text = helpers.formatDocComment(this.Docs);
815
- text += `type ${this.Name} struct {\n`;
885
+ let text = helpers.formatDocComment(this.Model.docs);
886
+ text += `type ${this.Model.name} struct {\n`;
816
887
  // group fields by required/optional/read-only in that order
817
- this.Fields?.sort((lhs, rhs) => {
888
+ this.Model.fields.sort((lhs, rhs) => {
818
889
  if ((lhs.annotations.required && !rhs.annotations.required) || (!lhs.annotations.readOnly && rhs.annotations.readOnly)) {
819
890
  return -1;
820
891
  }
@@ -827,7 +898,7 @@ class ModelDef {
827
898
  });
828
899
  // used to track when to add an extra \n between fields that have comments
829
900
  let first = true;
830
- for (const field of values(this.Fields)) {
901
+ for (const field of this.Model.fields) {
831
902
  if (field.docs.summary || field.docs.description) {
832
903
  if (!first) {
833
904
  // add an extra new-line between fields IFF the field
@@ -836,7 +907,7 @@ class ModelDef {
836
907
  }
837
908
  text += helpers.formatDocComment(field.docs);
838
909
  }
839
- let typeName = go.getTypeDeclaration(field.type);
910
+ let typeName = go.getTypeDeclaration(field.type, this.Model.pkg);
840
911
  if (field.type.kind === 'literal') {
841
912
  // for constants we use the underlying type name
842
913
  typeName = go.getLiteralTypeDeclaration(field.type.type);
@@ -846,7 +917,7 @@ class ModelDef {
846
917
  serialization += ',omitempty';
847
918
  }
848
919
  else if (this.Format === 'XML') {
849
- serialization = getXMLSerialization(field, false);
920
+ serialization = getXMLSerialization(this.Model, field);
850
921
  }
851
922
  let tag = '';
852
923
  // only emit tags for XML; JSON uses custom marshallers/unmarshallers
@@ -859,12 +930,20 @@ class ModelDef {
859
930
  text += '}\n\n';
860
931
  return text;
861
932
  }
933
+ /** returns the name to use for method receivers on this struct */
862
934
  receiverName() {
863
- const typeName = this.Name;
935
+ const typeName = this.Model.name;
864
936
  return typeName[0].toLowerCase();
865
937
  }
866
938
  }
867
- export function getXMLSerialization(field, isResponseEnvelope) {
939
+ /**
940
+ * returns the serialization options to use in the XML tag on a model field
941
+ *
942
+ * @param modelType the type that contains the field
943
+ * @param field the field for which to construct the tag's contents
944
+ * @returns the contents for the XML tag
945
+ */
946
+ function getXMLSerialization(modelType, field) {
868
947
  let serialization = field.serializedName;
869
948
  // default to using the serialization name
870
949
  if (field.xml?.name) {
@@ -882,7 +961,7 @@ export function getXMLSerialization(field, isResponseEnvelope) {
882
961
  }
883
962
  else if (field.type.kind === 'slice') {
884
963
  // start with the serialized name of the element, preferring xml name if available
885
- let inner = go.getTypeDeclaration(field.type.elementType);
964
+ let inner = go.getTypeDeclaration(field.type.elementType, modelType.pkg);
886
965
  if (field.xml?.name) {
887
966
  inner = field.xml.name;
888
967
  }
@@ -906,7 +985,7 @@ export function getXMLSerialization(field, isResponseEnvelope) {
906
985
  // </slideshow>
907
986
  // arrays in the response type are handled slightly different as we
908
987
  // unmarshal directly into them so no need to add the unwrapping.
909
- if (field.xml?.wraps && !isResponseEnvelope) {
988
+ if (field.xml?.wraps) {
910
989
  serialization += `>${field.xml.wraps}`;
911
990
  }
912
991
  else {