@azure-tools/typespec-go 0.17.5-dev.4 → 0.17.5-dev.6

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 (57) hide show
  1. package/dist/src/codegen/core/example.js +11 -11
  2. package/dist/src/codegen/core/example.js.map +1 -1
  3. package/dist/src/codegen/core/helpers.d.ts +3 -8
  4. package/dist/src/codegen/core/helpers.d.ts.map +1 -1
  5. package/dist/src/codegen/core/helpers.js +28 -44
  6. package/dist/src/codegen/core/helpers.js.map +1 -1
  7. package/dist/src/codegen/core/imports.d.ts.map +1 -1
  8. package/dist/src/codegen/core/imports.js +3 -0
  9. package/dist/src/codegen/core/imports.js.map +1 -1
  10. package/dist/src/codegen/core/models.d.ts.map +1 -1
  11. package/dist/src/codegen/core/models.js +171 -129
  12. package/dist/src/codegen/core/models.js.map +1 -1
  13. package/dist/src/codegen/core/operations.js +4 -4
  14. package/dist/src/codegen/core/operations.js.map +1 -1
  15. package/dist/src/codegen/core/options.js +1 -5
  16. package/dist/src/codegen/core/options.js.map +1 -1
  17. package/dist/src/codegen/core/request-handler.d.ts.map +1 -1
  18. package/dist/src/codegen/core/request-handler.js +23 -19
  19. package/dist/src/codegen/core/request-handler.js.map +1 -1
  20. package/dist/src/codegen/core/response-handler.js +12 -10
  21. package/dist/src/codegen/core/response-handler.js.map +1 -1
  22. package/dist/src/codegen/core/responses.js +4 -17
  23. package/dist/src/codegen/core/responses.js.map +1 -1
  24. package/dist/src/codegen/core/unions.js +21 -16
  25. package/dist/src/codegen/core/unions.js.map +1 -1
  26. package/dist/src/codegen/fake/servers.js +81 -68
  27. package/dist/src/codegen/fake/servers.js.map +1 -1
  28. package/dist/src/codemodel/client.js +1 -1
  29. package/dist/src/codemodel/client.js.map +1 -1
  30. package/dist/src/codemodel/method.d.ts +1 -3
  31. package/dist/src/codemodel/method.d.ts.map +1 -1
  32. package/dist/src/codemodel/method.js +1 -2
  33. package/dist/src/codemodel/method.js.map +1 -1
  34. package/dist/src/codemodel/param.d.ts +41 -29
  35. package/dist/src/codemodel/param.d.ts.map +1 -1
  36. package/dist/src/codemodel/param.js +33 -33
  37. package/dist/src/codemodel/param.js.map +1 -1
  38. package/dist/src/codemodel/result.d.ts +12 -10
  39. package/dist/src/codemodel/result.d.ts.map +1 -1
  40. package/dist/src/codemodel/result.js +2 -4
  41. package/dist/src/codemodel/result.js.map +1 -1
  42. package/dist/src/codemodel/type.d.ts +80 -51
  43. package/dist/src/codemodel/type.d.ts.map +1 -1
  44. package/dist/src/codemodel/type.js +65 -27
  45. package/dist/src/codemodel/type.js.map +1 -1
  46. package/dist/src/tcgcadapter/clients.d.ts.map +1 -1
  47. package/dist/src/tcgcadapter/clients.js +46 -51
  48. package/dist/src/tcgcadapter/clients.js.map +1 -1
  49. package/dist/src/tcgcadapter/helpers.d.ts +2 -23
  50. package/dist/src/tcgcadapter/helpers.d.ts.map +1 -1
  51. package/dist/src/tcgcadapter/helpers.js +16 -82
  52. package/dist/src/tcgcadapter/helpers.js.map +1 -1
  53. package/dist/src/tcgcadapter/types.d.ts +5 -3
  54. package/dist/src/tcgcadapter/types.d.ts.map +1 -1
  55. package/dist/src/tcgcadapter/types.js +92 -42
  56. package/dist/src/tcgcadapter/types.js.map +1 -1
  57. package/package.json +11 -11
@@ -3,6 +3,7 @@
3
3
  * Licensed under the MIT License. See License.txt in the project root for license information.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import * as go from "../../codemodel/index.js";
6
+ import * as naming from "../../naming/index.js";
6
7
  import * as helpers from "./helpers.js";
7
8
  import { ImportManager } from "./imports.js";
8
9
  /**
@@ -333,21 +334,22 @@ function generateModelDefs(modelImports, serdeImports, pkg, options, indent) {
333
334
  const modelDefs = new Array();
334
335
  for (const model of models) {
335
336
  for (const field of model.fields) {
337
+ const fieldType = go.unwrapPtr(field.type);
336
338
  const descriptionMods = new Array();
337
339
  if (field.annotations.readOnly) {
338
340
  descriptionMods.push("READ-ONLY");
339
341
  }
340
342
  else if (field.annotations.required &&
341
- (field.type.kind !== "literal" || model.usage === go.UsageFlags.Output)) {
343
+ (fieldType.kind !== "literal" || model.usage === go.UsageFlags.Output)) {
342
344
  descriptionMods.push("REQUIRED");
343
345
  }
344
- else if (field.type.kind === "literal") {
346
+ else if (fieldType.kind === "literal") {
345
347
  if (!field.annotations.required) {
346
348
  descriptionMods.push("FLAG");
347
349
  }
348
350
  descriptionMods.push("CONSTANT");
349
351
  }
350
- if (field.type.kind === "literal" && model.usage !== go.UsageFlags.Output) {
352
+ if (fieldType.kind === "literal" && model.usage !== go.UsageFlags.Output) {
351
353
  // add a comment with the const value for const properties that are sent over the wire
352
354
  if (field.docs.description) {
353
355
  field.docs.description += "\n";
@@ -355,9 +357,9 @@ function generateModelDefs(modelImports, serdeImports, pkg, options, indent) {
355
357
  else {
356
358
  field.docs.description = "";
357
359
  }
358
- field.docs.description += `Field has constant value ${helpers.formatLiteralValue(field.type, false)}, any specified value is ignored.`;
360
+ field.docs.description += `Field has constant value ${helpers.formatLiteralValue(fieldType, false)}, any specified value is ignored.`;
359
361
  }
360
- else if (field.type.kind === "rawJSON") {
362
+ else if (fieldType.kind === "rawJSON") {
361
363
  // raw JSON is emitted as []byte, so document that the field contains raw
362
364
  // JSON and that the caller is responsible for marshaling their data structure.
363
365
  if (field.docs.description) {
@@ -392,24 +394,26 @@ function generateModelDefs(modelImports, serdeImports, pkg, options, indent) {
392
394
  let needsDateTimeMarshalling = false;
393
395
  let byteArrayFormat = false;
394
396
  for (const field of model.fields) {
395
- if (field.type.kind !== "etag") {
397
+ const fieldType = go.unwrapPtr(field.type);
398
+ if (fieldType.kind !== "etag") {
396
399
  // azcore.ETag un/marshals on its own so no need to
397
400
  // import azcore as we don't explicitly reference the type
398
- serdeImports.addForType(field.type);
401
+ serdeImports.addForType(fieldType);
399
402
  }
400
- if (field.type.kind === "time") {
403
+ if (fieldType.kind === "time") {
401
404
  needsDateTimeMarshalling = true;
402
405
  }
403
- else if (field.type.kind === "encodedBytes") {
406
+ else if (fieldType.kind === "encodedBytes") {
404
407
  byteArrayFormat = true;
405
408
  }
406
409
  }
407
410
  // due to differences in XML marshallers/unmarshallers, we use different codegen than for JSON
408
411
  const needsXMLDictionaryUnmarshalling = needsXMLDictionaryHelper(model);
409
412
  if (needsDateTimeMarshalling ||
410
- model.xml?.name ||
413
+ model.xmlName ||
411
414
  needsXMLArrayMarshalling(model) ||
412
- byteArrayFormat) {
415
+ byteArrayFormat ||
416
+ needsXMLNestedModelMarshalling(model)) {
413
417
  generateXMLMarshaller(modelDef, serdeImports, indent);
414
418
  if (needsDateTimeMarshalling || needsXMLDictionaryUnmarshalling || byteArrayFormat) {
415
419
  generateXMLUnmarshaller(modelDef, serdeImports, indent);
@@ -466,6 +470,34 @@ function needsXMLArrayMarshalling(modelType) {
466
470
  }
467
471
  return false;
468
472
  }
473
+ /**
474
+ * returns true if the model contains one or more nested models
475
+ * where the field's serialized name is different from the model's
476
+ * XML name. the field's serialized name takes precedence.
477
+ *
478
+ * @param modelType the model to inspect
479
+ * @returns true if a custom marshaller is required
480
+ */
481
+ function needsXMLNestedModelMarshalling(modelType) {
482
+ for (const field of modelType.fields) {
483
+ if (fieldNeedsXMLNestedModelMarshalling(field)) {
484
+ return true;
485
+ }
486
+ }
487
+ return false;
488
+ }
489
+ /**
490
+ * narrows field to a Model or Ptr<Model> type that requires custom
491
+ * marshalling due to the field's serialized name being different from
492
+ * the model's XML name.
493
+ *
494
+ * @param field the field to inspect
495
+ * @returns a Model or Ptr<Model> that requires custom marshalling
496
+ */
497
+ function fieldNeedsXMLNestedModelMarshalling(field) {
498
+ const fieldType = go.unwrapPtr(field.type);
499
+ return fieldType.kind === "model" && !!fieldType.xmlName && field.serializedName !== fieldType.xmlName;
500
+ }
469
501
  // generates discriminator marker method
470
502
  function generateDiscriminatorMarkerMethod(type, modelDef, indent) {
471
503
  const typeName = type.rootType.name;
@@ -497,15 +529,12 @@ function generateToMultipartForm(modelDef, indent) {
497
529
  let method = `func (${receiver} ${modelDef.Model.name}) toMultipartFormData() (map[string]any, error) {\n`;
498
530
  method += `${indent.get()}objectMap := make(map[string]any)\n`;
499
531
  for (const field of modelDef.Model.fields) {
500
- const fieldType = helpers.recursiveUnwrapMapSlice(field.type);
501
- let star = "";
502
- if (!field.byValue) {
503
- star = "*";
504
- }
505
- if (!field.byValue) {
532
+ const star = helpers.deref(field.type);
533
+ if (field.type.kind === "ptr") {
506
534
  method += `${indent.get()}if ${receiver}.${field.name} != nil {\n`;
507
535
  indent.push();
508
536
  }
537
+ const fieldType = helpers.recursiveUnwrapMapSlice(field.type);
509
538
  if (fieldType.kind === "model" && !fieldType.annotations.multipartFormData) {
510
539
  method += `${indent.get()}if err := populateMultipartJSON(objectMap, "${field.serializedName}", ${star}${receiver}.${field.name}); err != nil {\n`;
511
540
  method += `${indent.push().get()}return nil, err\n`;
@@ -514,7 +543,7 @@ function generateToMultipartForm(modelDef, indent) {
514
543
  else {
515
544
  method += `${indent.get()}objectMap["${field.serializedName}"] = ${star}${receiver}.${field.name}\n`;
516
545
  }
517
- if (!field.byValue) {
546
+ if (field.type.kind === "ptr") {
518
547
  indent.pop();
519
548
  method += `${indent.get()}}\n`;
520
549
  }
@@ -571,6 +600,10 @@ function generateJSONMarshallerBody(modelDef, receiver, imports, indent) {
571
600
  addlProps = field.type;
572
601
  continue;
573
602
  }
603
+ // pointer-ness is captured in the code model, so dispatch on the unwrapped
604
+ // type and read isPtr to decide pointer-to-type emission.
605
+ const fieldType = go.unwrapPtr(field.type);
606
+ const deref = helpers.deref(field.type);
574
607
  if (field.annotations.isDiscriminator) {
575
608
  if (field.defaultValue) {
576
609
  marshaller += `${indent.get()}objectMap["${field.serializedName}"] = ${helpers.formatLiteralValue(field.defaultValue, true)}\n`;
@@ -581,31 +614,28 @@ function generateJSONMarshallerBody(modelDef, receiver, imports, indent) {
581
614
  marshaller += `${indent.get()}objectMap["${field.serializedName}"] = ${receiver}.${field.name}\n`;
582
615
  }
583
616
  }
584
- else if (field.type.kind === "encodedBytes") {
617
+ else if (fieldType.kind === "encodedBytes") {
585
618
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime");
586
619
  marshaller += `${indent.get()}populateByteArray(objectMap, "${field.serializedName}", ${receiver}.${field.name}, func() any {\n`;
587
- marshaller += `${indent.push().get()}return runtime.EncodeByteArray(${receiver}.${field.name}, runtime.Base64${field.type.encoding}Format)\n`;
620
+ marshaller += `${indent.push().get()}return runtime.EncodeByteArray(${receiver}.${field.name}, runtime.Base64${fieldType.encoding}Format)\n`;
588
621
  marshaller += `${indent.pop().get()}})\n`;
589
622
  modelDef.SerDe.needsJSONPopulateByteArray = true;
590
623
  }
591
- else if (go.isSlice(field.type, "encodedBytes")) {
624
+ else if (go.isSlice(fieldType, "encodedBytes")) {
592
625
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime");
593
626
  marshaller += `${indent.get()}populateByteArray(objectMap, "${field.serializedName}", ${receiver}.${field.name}, func() any {\n`;
594
627
  marshaller += `${indent.push().get()}encodedValue := make([]string, len(${receiver}.${field.name}))\n`;
595
628
  marshaller += `${indent.get()}for i := 0; i < len(${receiver}.${field.name}); i++ {\n`;
596
- marshaller += `${indent.push().get()}encodedValue[i] = runtime.EncodeByteArray(${receiver}.${field.name}[i], runtime.Base64${field.type.elementType.encoding}Format)\n`;
629
+ marshaller += `${indent.push().get()}encodedValue[i] = runtime.EncodeByteArray(${receiver}.${field.name}[i], runtime.Base64${fieldType.elementType.encoding}Format)\n`;
597
630
  marshaller += `${indent.pop().get()}}\n`;
598
631
  marshaller += `${indent.get()}return encodedValue\n`;
599
632
  marshaller += `${indent.pop().get()}})\n`;
600
633
  modelDef.SerDe.needsJSONPopulateByteArray = true;
601
634
  }
602
- else if (go.isSlice(field.type, "time")) {
635
+ else if (go.isSlice(fieldType, "time")) {
603
636
  const source = `${receiver}.${field.name}`;
604
- const elementType = field.type.elementType;
605
- let elementPtr = "*";
606
- if (field.type.elementTypeByValue) {
607
- elementPtr = "";
608
- }
637
+ const elementType = go.unwrapPtr(fieldType.elementType);
638
+ const elementPtr = helpers.deref(fieldType.elementType);
609
639
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime");
610
640
  marshaller += `${indent.get()}aux := make([]${elementPtr}datetime.${elementType.format}, len(${source}), len(${source}))\n`;
611
641
  marshaller += `${indent.get()}for i := 0; i < len(${source}); i++ {\n`;
@@ -626,8 +656,8 @@ function generateJSONMarshallerBody(modelDef, receiver, imports, indent) {
626
656
  marshaller += `${indent.get()}populate(objectMap, "${field.serializedName}", aux)\n`;
627
657
  modelDef.SerDe.needsJSONPopulate = true;
628
658
  }
629
- else if (field.type.kind === "literal") {
630
- const setter = `objectMap["${field.serializedName}"] = ${helpers.formatLiteralValue(field.type, true)}`;
659
+ else if (fieldType.kind === "literal") {
660
+ const setter = `objectMap["${field.serializedName}"] = ${helpers.formatLiteralValue(fieldType, true)}`;
631
661
  if (!field.annotations.required) {
632
662
  marshaller += `${indent.get()}if ${receiver}.${field.name} != nil {\n`;
633
663
  marshaller += `${indent.push().get()}${setter}\n`;
@@ -637,7 +667,7 @@ function generateJSONMarshallerBody(modelDef, receiver, imports, indent) {
637
667
  marshaller += `${indent.get()}${setter}\n`;
638
668
  }
639
669
  }
640
- else if (field.type.kind === "rawJSON") {
670
+ else if (fieldType.kind === "rawJSON") {
641
671
  marshaller += `${indent.get()}populate(objectMap, "${field.serializedName}", json.RawMessage(${receiver}.${field.name}))\n`;
642
672
  modelDef.SerDe.needsJSONPopulate = true;
643
673
  }
@@ -648,24 +678,24 @@ function generateJSONMarshallerBody(modelDef, receiver, imports, indent) {
648
678
  marshaller += `${indent.push().get()}${receiver}.${field.name} = to.Ptr(${helpers.formatLiteralValue(field.defaultValue, true)})\n`;
649
679
  marshaller += `${indent.pop().get()}}\n`;
650
680
  }
651
- if (go.isScalar(field.type, "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64") &&
652
- field.type.encodeAsString) {
681
+ if (go.isScalar(fieldType, "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64") &&
682
+ fieldType.encodeAsString) {
653
683
  imports.add("strconv");
654
684
  marshaller += `${indent.get()}populateAsString(objectMap, "${field.serializedName}", ${receiver}.${field.name}, func() string {\n`;
655
- const isSigned = field.type.type.startsWith("int");
656
- let fieldExpr = `*${receiver}.${field.name}`;
657
- if ((field.type.type.startsWith("uint") && field.type.type !== "uint64") ||
658
- (field.type.type.startsWith("int") && field.type.type !== "int64")) {
685
+ const isSigned = fieldType.type.startsWith("int");
686
+ let fieldExpr = `${deref}${receiver}.${field.name}`;
687
+ if ((fieldType.type.startsWith("uint") && fieldType.type !== "uint64") ||
688
+ (fieldType.type.startsWith("int") && fieldType.type !== "int64")) {
659
689
  fieldExpr = `${isSigned ? "int64" : "uint64"}(${fieldExpr})`;
660
690
  }
661
691
  marshaller += `${indent.push().get()}return strconv.${isSigned ? "FormatInt" : "FormatUint"}(${fieldExpr}, 10)\n`;
662
692
  marshaller += `${indent.pop().get()}})\n`;
663
693
  modelDef.SerDe.needsJSONPopulateAsString = true;
664
694
  }
665
- else if (go.isScalar(field.type, "bool") && field.type.encodeAsString) {
695
+ else if (go.isScalar(fieldType, "bool") && fieldType.encodeAsString) {
666
696
  imports.add("strconv");
667
697
  marshaller += `${indent.get()}populateAsString(objectMap, "${field.serializedName}", ${receiver}.${field.name}, func() string {\n`;
668
- marshaller += `${indent.push().get()}return strconv.FormatBool(*${receiver}.${field.name})\n`;
698
+ marshaller += `${indent.push().get()}return strconv.FormatBool(${deref}${receiver}.${field.name})\n`;
669
699
  marshaller += `${indent.pop().get()}})\n`;
670
700
  modelDef.SerDe.needsJSONPopulateAsString = true;
671
701
  }
@@ -673,19 +703,19 @@ function generateJSONMarshallerBody(modelDef, receiver, imports, indent) {
673
703
  let populate;
674
704
  // some helpers require extra args after the common ones
675
705
  let populateArgs = "";
676
- if (field.type.kind === "time") {
706
+ if (fieldType.kind === "time") {
677
707
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime");
678
- populate = `populateTime[datetime.${field.type.format}]`;
679
- populateArgs = `, ${field.type.utc}`;
708
+ populate = `populateTime[datetime.${fieldType.format}]`;
709
+ populateArgs = `, ${fieldType.utc}`;
680
710
  modelDef.SerDe.needsJSONPopulateTime = true;
681
711
  }
682
- else if (field.type.kind === "any") {
712
+ else if (fieldType.kind === "any") {
683
713
  populate = "populateAny";
684
714
  modelDef.SerDe.needsJSONPopulateAny = true;
685
715
  }
686
- else if (field.type.kind === "sliceArray") {
716
+ else if (fieldType.kind === "sliceArray") {
687
717
  populate = "populateStringArray";
688
- populateArgs = `, "${getSliceArrayDelimiter(field.type.delimiter)}"`;
718
+ populateArgs = `, "${getSliceArrayDelimiter(fieldType.delimiter)}"`;
689
719
  modelDef.SerDe.needsJSONPopulateStringArray = true;
690
720
  }
691
721
  else {
@@ -699,20 +729,20 @@ function generateJSONMarshallerBody(modelDef, receiver, imports, indent) {
699
729
  if (addlProps) {
700
730
  marshaller += `${indent.get()}if ${receiver}.AdditionalProperties != nil {\n`;
701
731
  marshaller += `${indent.push().get()}for key, val := range ${receiver}.AdditionalProperties {\n`;
702
- if (addlProps.valueType.kind === "time" && addlProps.valueType.utc) {
732
+ if (go.isPtr(addlProps.valueType, "time") && addlProps.valueType.ptrType.utc) {
703
733
  // normalize utc datetimes before casting the (pointer) map value
704
734
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime");
705
735
  marshaller += `${indent.push().get()}if val != nil {\n`;
706
736
  marshaller += `${indent.push().get()}utcTime := val.UTC()\n`;
707
- marshaller += `${indent.get()}objectMap[key] = (*datetime.${addlProps.valueType.format})(&utcTime)\n`;
737
+ marshaller += `${indent.get()}objectMap[key] = (*datetime.${addlProps.valueType.ptrType.format})(&utcTime)\n`;
708
738
  marshaller += `${indent.pop().get()}} else {\n`;
709
739
  marshaller += `${indent.push().get()}objectMap[key] = nil\n`;
710
740
  marshaller += `${indent.pop().get()}}\n`;
711
741
  }
712
742
  else {
713
743
  let assignment = "val";
714
- if (addlProps.valueType.kind === "time") {
715
- assignment = `(*${addlProps.valueType.format})(val)`;
744
+ if (go.isPtr(addlProps.valueType, "time")) {
745
+ assignment = `(*${addlProps.valueType.ptrType.format})(val)`;
716
746
  }
717
747
  marshaller += `${indent.push().get()}objectMap[key] = ${assignment}\n`;
718
748
  }
@@ -772,18 +802,15 @@ function generateJSONUnmarshallerBody(modelDef, receiver, options, imports, inde
772
802
  const emitAddlProps = function (addlProps) {
773
803
  // indent is at the case body level when called
774
804
  let addlPropsText = `${indent.get()}if ${receiver}.AdditionalProperties == nil {\n`;
775
- let ref = "";
776
- if (!addlProps.valueTypeByValue) {
777
- ref = "&";
778
- }
805
+ const ref = addlProps.valueType.kind === "ptr" ? "&" : "";
779
806
  addlPropsText += `${indent.push().get()}${receiver}.AdditionalProperties = ${go.getTypeDeclaration(addlProps, modelDef.Model.pkg)}{}\n`;
780
807
  addlPropsText += `${indent.pop().get()}}\n`;
781
808
  addlPropsText += `${indent.get()}if val != nil {\n`;
782
- let auxType = go.getTypeDeclaration(addlProps.valueType, modelDef.Model.pkg);
809
+ let auxType = go.getTypeDeclaration(go.unwrapPtr(addlProps.valueType), modelDef.Model.pkg);
783
810
  let assignment = `${ref}aux`;
784
- if (addlProps.valueType.kind === "time") {
811
+ if (go.isPtr(addlProps.valueType, "time")) {
785
812
  imports.add("time");
786
- auxType = addlProps.valueType.format;
813
+ auxType = addlProps.valueType.ptrType.format;
787
814
  assignment = `(*time.Time)(${assignment})`;
788
815
  }
789
816
  addlPropsText += `${indent.push().get()}var aux ${auxType}\n`;
@@ -804,30 +831,30 @@ function generateJSONUnmarshallerBody(modelDef, receiver, options, imports, inde
804
831
  addlProps = field.type;
805
832
  continue;
806
833
  }
834
+ // dispatch on the unwrapped type; pointer-ness is captured in the code model.
835
+ const fieldType = go.unwrapPtr(field.type);
807
836
  unmarshalBody += `${indent.get()}case "${field.serializedName}":\n`;
808
837
  indent.push(); // case body level
809
- if (hasDiscriminatorInterface(field.type)) {
838
+ if (hasDiscriminatorInterface(fieldType)) {
810
839
  unmarshalBody += generateDiscriminatorUnmarshaller(modelDef.Model, field, receiver, indent);
811
840
  needsErrCheck = true;
812
841
  }
813
- else if (field.type.kind === "sliceArray") {
814
- unmarshalBody += `${indent.get()}err = unpopulateStringArray(val, "${field.name}", &${receiver}.${field.name}, "${getSliceArrayDelimiter(field.type.delimiter)}")\n`;
842
+ else if (fieldType.kind === "sliceArray") {
843
+ unmarshalBody += `${indent.get()}err = unpopulateStringArray(val, "${field.name}", &${receiver}.${field.name}, "${getSliceArrayDelimiter(fieldType.delimiter)}")\n`;
815
844
  modelDef.SerDe.needsJSONUnpopulateStringArray = true;
816
845
  needsErrCheck = true;
817
846
  }
818
- else if (field.type.kind === "time") {
819
- unmarshalBody += `${indent.get()}err = unpopulateTime[datetime.${field.type.format}](val, "${field.name}", &${receiver}.${field.name})\n`;
847
+ else if (fieldType.kind === "time") {
848
+ unmarshalBody += `${indent.get()}err = unpopulateTime[datetime.${fieldType.format}](val, "${field.name}", &${receiver}.${field.name})\n`;
820
849
  modelDef.SerDe.needsJSONUnpopulateTime = true;
821
850
  needsErrCheck = true;
822
851
  }
823
- else if (go.isSlice(field.type, "time")) {
852
+ else if (go.isSlice(fieldType, "time")) {
824
853
  imports.add("time");
825
854
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime");
826
- let elementPtr = "*";
827
- if (field.type.elementTypeByValue) {
828
- elementPtr = "";
829
- }
830
- unmarshalBody += `${indent.get()}var aux []${elementPtr}datetime.${field.type.elementType.format}\n`;
855
+ const elementType = go.unwrapPtr(fieldType.elementType);
856
+ const elementPtr = helpers.deref(fieldType.elementType);
857
+ unmarshalBody += `${indent.get()}var aux []${elementPtr}datetime.${elementType.format}\n`;
831
858
  unmarshalBody += `${indent.get()}err = unpopulate(val, "${field.name}", &aux)\n`;
832
859
  unmarshalBody += `${indent.get()}for _, au := range aux {\n`;
833
860
  unmarshalBody += `${indent.push().get()}${receiver}.${field.name} = append(${receiver}.${field.name}, (${elementPtr}time.Time)(au))\n`;
@@ -835,14 +862,14 @@ function generateJSONUnmarshallerBody(modelDef, receiver, options, imports, inde
835
862
  modelDef.SerDe.needsJSONUnpopulate = true;
836
863
  needsErrCheck = true;
837
864
  }
838
- else if (field.type.kind === "encodedBytes") {
865
+ else if (fieldType.kind === "encodedBytes") {
839
866
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime");
840
867
  unmarshalBody += `${indent.get()}if val != nil && string(val) != "null" {\n`;
841
- unmarshalBody += `${indent.push().get()}err = runtime.DecodeByteArray(string(val), &${receiver}.${field.name}, runtime.Base64${field.type.encoding}Format)\n`;
868
+ unmarshalBody += `${indent.push().get()}err = runtime.DecodeByteArray(string(val), &${receiver}.${field.name}, runtime.Base64${fieldType.encoding}Format)\n`;
842
869
  unmarshalBody += `${indent.pop().get()}}\n`;
843
870
  needsErrCheck = true;
844
871
  }
845
- else if (go.isSlice(field.type, "encodedBytes")) {
872
+ else if (go.isSlice(fieldType, "encodedBytes")) {
846
873
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime");
847
874
  unmarshalBody += `${indent.get()}var encodedValue []string\n`;
848
875
  unmarshalBody += `${indent.get()}err = unpopulate(val, "${field.name}", &encodedValue)\n`;
@@ -850,19 +877,19 @@ function generateJSONUnmarshallerBody(modelDef, receiver, options, imports, inde
850
877
  indent.push();
851
878
  unmarshalBody += `${indent.get()}${receiver}.${field.name} = make([][]byte, len(encodedValue))\n`;
852
879
  unmarshalBody += `${indent.get()}for i := 0; i < len(encodedValue) && err == nil; i++ {\n`;
853
- unmarshalBody += `${indent.push().get()}err = runtime.DecodeByteArray(encodedValue[i], &${receiver}.${field.name}[i], runtime.Base64${field.type.elementType.encoding}Format)\n`;
880
+ unmarshalBody += `${indent.push().get()}err = runtime.DecodeByteArray(encodedValue[i], &${receiver}.${field.name}[i], runtime.Base64${fieldType.elementType.encoding}Format)\n`;
854
881
  unmarshalBody += `${indent.pop().get()}}\n`;
855
882
  indent.pop();
856
883
  unmarshalBody += `${indent.get()}}\n`;
857
884
  modelDef.SerDe.needsJSONUnpopulate = true;
858
885
  needsErrCheck = true;
859
886
  }
860
- else if (field.type.kind === "rawJSON") {
887
+ else if (fieldType.kind === "rawJSON") {
861
888
  unmarshalBody += `${indent.get()}if string(val) != "null" {\n`;
862
889
  unmarshalBody += `${indent.push().get()}${receiver}.${field.name} = val\n`;
863
890
  unmarshalBody += `${indent.pop().get()}}\n`;
864
891
  }
865
- else if (go.isScalar(field.type, "bool") && field.type.encodeAsString) {
892
+ else if (go.isScalar(fieldType, "bool") && fieldType.encodeAsString) {
866
893
  imports.add("strconv");
867
894
  imports.add("strings");
868
895
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/to");
@@ -877,13 +904,13 @@ function generateJSONUnmarshallerBody(modelDef, receiver, options, imports, inde
877
904
  modelDef.SerDe.needsJSONUnpopulateFromString = true;
878
905
  needsErrCheck = true;
879
906
  }
880
- else if (go.isScalar(field.type, "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64") &&
881
- field.type.encodeAsString) {
882
- const scalarType = field.type.type;
907
+ else if (go.isScalar(fieldType, "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64") &&
908
+ fieldType.encodeAsString) {
909
+ const scalarType = fieldType.type;
883
910
  imports.add("strconv");
884
911
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/to");
885
912
  unmarshalBody += `${indent.get()}err = unpopulateFromString(val, "${field.name}", func(encodedValue string) error {\n`;
886
- unmarshalBody += `${indent.push().get()}v, parseErr := strconv.${field.type.type.startsWith("int") ? "ParseInt" : "ParseUint"}(encodedValue, 10, 0)\n`;
913
+ unmarshalBody += `${indent.push().get()}v, parseErr := strconv.${fieldType.type.startsWith("int") ? "ParseInt" : "ParseUint"}(encodedValue, 10, 0)\n`;
887
914
  unmarshalBody += `${indent.get()}${helpers.buildIfBlock(indent, {
888
915
  condition: "parseErr == nil",
889
916
  body: (indent) => {
@@ -902,7 +929,7 @@ function generateJSONUnmarshallerBody(modelDef, receiver, options, imports, inde
902
929
  }
903
930
  else {
904
931
  const unpopulateField = `err = unpopulate(val, "${field.name}", &${receiver}.${field.name})\n`;
905
- if (field.type.kind === "string" && field.annotations.unmarshalEmptyStringAsNil) {
932
+ if (fieldType.kind === "string" && field.annotations.unmarshalEmptyStringAsNil) {
906
933
  unmarshalBody += `${indent.get()}${helpers.buildIfBlock(indent, {
907
934
  condition: `string(val) != \`""\``,
908
935
  body: (indent) => `${indent.get()}${unpopulateField}`,
@@ -1099,6 +1126,11 @@ function recursivePopulateDiscriminator(modelType, item, receiver, rawSrc, dest,
1099
1126
  text += `${indent.pop().get()}}\n`;
1100
1127
  return text;
1101
1128
  }
1129
+ /** returns the alias type name to use when aliasing a model type */
1130
+ function getXMLNestedModelAliasTypeName(type) {
1131
+ const fieldType = go.unwrapPtr(type);
1132
+ return naming.uncapitalize(fieldType.name);
1133
+ }
1102
1134
  /**
1103
1135
  * generates an implementation of MarshalXML for the provided type.
1104
1136
  * the method impl is added to modelDef.SerDe.methods.
@@ -1111,28 +1143,43 @@ function generateXMLMarshaller(modelDef, imports, indent) {
1111
1143
  const receiver = modelDef.receiverName();
1112
1144
  const desc = `MarshalXML implements the xml.Marshaller interface for type ${modelDef.Model.name}.`;
1113
1145
  let text = `func (${receiver} ${modelDef.Model.name}) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {\n`;
1114
- if (modelDef.Model.xml?.name) {
1115
- text += `${indent.get()}start.Name.Local = "${modelDef.Model.xml.name}"\n`;
1146
+ if (modelDef.Model.xmlName) {
1147
+ text += `${indent.get()}start.Name.Local = "${modelDef.Model.xmlName}"\n`;
1148
+ }
1149
+ // declare the type aliases for custom marshalling first
1150
+ // as the containing type's alias type depends on them
1151
+ for (const field of modelDef.Model.fields) {
1152
+ if (fieldNeedsXMLNestedModelMarshalling(field)) {
1153
+ const fieldType = go.unwrapPtr(field.type);
1154
+ text += `${indent.get()}type ${getXMLNestedModelAliasTypeName(field.type)} ${fieldType.name}\n`;
1155
+ }
1116
1156
  }
1117
1157
  text += generateAliasType(modelDef.Model, receiver, true, imports, indent);
1118
1158
  for (const field of modelDef.Model.fields) {
1119
- if (field.type.kind === "slice") {
1159
+ const fieldType = go.unwrapPtr(field.type);
1160
+ if (fieldType.kind === "slice") {
1120
1161
  text += `${indent.get()}if ${receiver}.${field.name} != nil {\n`;
1121
1162
  text += `${indent.push().get()}aux.${field.name} = &${receiver}.${field.name}\n`;
1122
1163
  text += `${indent.pop().get()}}\n`;
1123
1164
  }
1124
- else if (go.isAdditionalProperties(field) || field.type.kind === "map") {
1165
+ else if (go.isAdditionalProperties(field) || fieldType.kind === "map") {
1125
1166
  text += `${indent.get()}aux.${field.name} = (additionalProperties)(${receiver}.${field.name})\n`;
1126
1167
  }
1127
- else if (field.type.kind === "encodedBytes") {
1168
+ else if (fieldType.kind === "encodedBytes") {
1128
1169
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime");
1129
1170
  text += `${indent.get()}if ${receiver}.${field.name} != nil {\n`;
1130
1171
  indent.push();
1131
- text += `${indent.get()}encoded${field.name} := runtime.EncodeByteArray(${receiver}.${field.name}, runtime.Base64${field.type.encoding}Format)\n`;
1172
+ text += `${indent.get()}encoded${field.name} := runtime.EncodeByteArray(${receiver}.${field.name}, runtime.Base64${fieldType.encoding}Format)\n`;
1132
1173
  text += `${indent.get()}aux.${field.name} = &encoded${field.name}\n`;
1133
1174
  indent.pop();
1134
1175
  text += `${indent.get()}}\n`;
1135
1176
  }
1177
+ else if (fieldNeedsXMLNestedModelMarshalling(field)) {
1178
+ text += `${indent.get()}${helpers.buildIfBlock(indent, {
1179
+ condition: `${receiver}.${field.name} != nil`,
1180
+ body: (indent) => `${indent.get()}aux.${field.name} = (*${getXMLNestedModelAliasTypeName(field.type)})(${receiver}.${field.name})\n`,
1181
+ })}\n`;
1182
+ }
1136
1183
  }
1137
1184
  text += `${indent.get()}return enc.EncodeElement(aux, start)\n`;
1138
1185
  text += "}\n\n";
@@ -1155,19 +1202,20 @@ function generateXMLUnmarshaller(modelDef, imports, indent) {
1155
1202
  text += `${indent.push().get()}return err\n`;
1156
1203
  text += `${indent.pop().get()}}\n`;
1157
1204
  for (const field of modelDef.Model.fields) {
1158
- if (field.type.kind === "time") {
1205
+ const fieldType = go.unwrapPtr(field.type);
1206
+ if (fieldType.kind === "time") {
1159
1207
  text += `${indent.get()}if aux.${field.name} != nil && !(*time.Time)(aux.${field.name}).IsZero() {\n`;
1160
1208
  text += `${indent.push().get()}${receiver}.${field.name} = (*time.Time)(aux.${field.name})\n`;
1161
1209
  text += `${indent.pop().get()}}\n`;
1162
1210
  }
1163
- else if (go.isAdditionalProperties(field) || field.type.kind === "map") {
1211
+ else if (go.isAdditionalProperties(field) || fieldType.kind === "map") {
1164
1212
  text += `${indent.get()}${receiver}.${field.name} = (map[string]*string)(aux.${field.name})\n`;
1165
1213
  }
1166
- else if (field.type.kind === "encodedBytes") {
1214
+ else if (fieldType.kind === "encodedBytes") {
1167
1215
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime");
1168
1216
  text += `${indent.get()}if aux.${field.name} != nil {\n`;
1169
1217
  indent.push();
1170
- text += `${indent.get()}if err := runtime.DecodeByteArray(*aux.${field.name}, &${receiver}.${field.name}, runtime.Base64${field.type.encoding}Format); err != nil {\n`;
1218
+ text += `${indent.get()}if err := runtime.DecodeByteArray(*aux.${field.name}, &${receiver}.${field.name}, runtime.Base64${fieldType.encoding}Format); err != nil {\n`;
1171
1219
  text += `${indent.push().get()}return err\n`;
1172
1220
  text += `${indent.pop().get()}}\n`;
1173
1221
  indent.pop();
@@ -1191,20 +1239,24 @@ function generateAliasType(modelType, receiver, forMarshal, imports, indent) {
1191
1239
  text += `${indent.get()}aux := &struct {\n`;
1192
1240
  text += `${indent.push().get()}*alias\n`;
1193
1241
  for (const field of modelType.fields) {
1194
- const sn = getXMLSerialization(field);
1195
- if (field.type.kind === "time") {
1242
+ const fieldType = go.unwrapPtr(field.type);
1243
+ const sn = getXMLSerialization(field, modelType.pkg);
1244
+ if (fieldType.kind === "time") {
1196
1245
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime");
1197
- text += `${indent.get()}${field.name} *datetime.${field.type.format} \`xml:"${sn}"\`\n`;
1246
+ text += `${indent.get()}${field.name} *datetime.${fieldType.format} \`xml:"${sn}"\`\n`;
1198
1247
  }
1199
- else if (go.isAdditionalProperties(field) || field.type.kind === "map") {
1248
+ else if (go.isAdditionalProperties(field) || fieldType.kind === "map") {
1200
1249
  text += `${indent.get()}${field.name} additionalProperties \`xml:"${sn}"\`\n`;
1201
1250
  }
1202
- else if (field.type.kind === "slice") {
1203
- text += `${indent.get()}${field.name} *${go.getTypeDeclaration(field.type, modelType.pkg)} \`xml:"${sn}"\`\n`;
1251
+ else if (fieldType.kind === "slice") {
1252
+ text += `${indent.get()}${field.name} *${go.getTypeDeclaration(fieldType, modelType.pkg)} \`xml:"${sn}"\`\n`;
1204
1253
  }
1205
- else if (field.type.kind === "encodedBytes") {
1254
+ else if (fieldType.kind === "encodedBytes") {
1206
1255
  text += `${indent.get()}${field.name} *string \`xml:"${sn}"\`\n`;
1207
1256
  }
1257
+ else if (fieldNeedsXMLNestedModelMarshalling(field)) {
1258
+ text += `${indent.get()}${field.name} *${getXMLNestedModelAliasTypeName(field.type)} \`xml:"${field.serializedName}"\`\n`;
1259
+ }
1208
1260
  }
1209
1261
  text += `${indent.pop().get()}}{\n`;
1210
1262
  let rec = receiver;
@@ -1215,11 +1267,12 @@ function generateAliasType(modelType, receiver, forMarshal, imports, indent) {
1215
1267
  if (forMarshal) {
1216
1268
  // emit code to initialize time fields
1217
1269
  for (const field of modelType.fields) {
1218
- if (field.type.kind !== "time") {
1270
+ const fieldType = go.unwrapPtr(field.type);
1271
+ if (fieldType.kind !== "time") {
1219
1272
  continue;
1220
1273
  }
1221
1274
  imports.add("github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime");
1222
- text += `${indent.get()}${field.name}: (*datetime.${field.type.format})(${receiver}.${field.name}),\n`;
1275
+ text += `${indent.get()}${field.name}: (*datetime.${fieldType.format})(${receiver}.${field.name}),\n`;
1223
1276
  }
1224
1277
  }
1225
1278
  text += `${indent.pop().get()}}\n`;
@@ -1296,23 +1349,24 @@ class ModelDef {
1296
1349
  text += helpers.formatDocComment(field.docs);
1297
1350
  }
1298
1351
  let typeName = go.getTypeDeclaration(field.type, this.Model.pkg);
1299
- if (field.type.kind === "literal") {
1300
- // for constants we use the underlying type name
1301
- typeName = go.getLiteralTypeDeclaration(field.type.type);
1352
+ const fieldType = go.unwrapPtr(field.type);
1353
+ if (fieldType.kind === "literal") {
1354
+ // for constants we use the underlying type name; getTypeDeclaration above emits the pointer.
1355
+ typeName = `${helpers.deref(field.type)}${go.getLiteralTypeDeclaration(fieldType.type)}`;
1302
1356
  }
1303
1357
  let serialization = field.serializedName;
1304
1358
  if (this.Format === "JSON") {
1305
1359
  serialization += ",omitempty";
1306
1360
  }
1307
1361
  else if (this.Format === "XML") {
1308
- serialization = getXMLSerialization(field);
1362
+ serialization = getXMLSerialization(field, this.Model.pkg);
1309
1363
  }
1310
1364
  let tag = "";
1311
1365
  // only emit tags for XML; JSON uses custom marshallers/unmarshallers
1312
1366
  if (this.Format === "XML" && !go.isAdditionalProperties(field)) {
1313
1367
  tag = ` \`xml:"${serialization}"\``;
1314
1368
  }
1315
- text += `${indent.get()}${field.name} ${helpers.star(field.byValue)}${typeName}${tag}\n`;
1369
+ text += `${indent.get()}${field.name} ${typeName}${tag}\n`;
1316
1370
  first = false;
1317
1371
  }
1318
1372
  text += "}\n\n";
@@ -1330,28 +1384,17 @@ class ModelDef {
1330
1384
  * @param field the field for which to construct the tag's contents
1331
1385
  * @returns the contents for the XML tag
1332
1386
  */
1333
- function getXMLSerialization(field) {
1387
+ function getXMLSerialization(field, pkg) {
1334
1388
  let serialization = field.serializedName;
1335
- // default to using the serialization name
1336
- if (field.xml?.name) {
1337
- // xml can specify its own name, prefer that if available
1338
- serialization = field.xml.name;
1339
- }
1340
- else if (field.xml?.text) {
1341
- // type has the x-ms-text attribute applied so it should be character data, not a node (https://github.com/Azure/autorest/tree/main/docs/extensions#x-ms-text)
1342
- // see https://pkg.go.dev/encoding/xml#Unmarshal for what ,chardata actually means
1343
- serialization = ",chardata";
1389
+ switch (field.xmlKind) {
1390
+ case "attribute":
1391
+ serialization += ",attr";
1392
+ return serialization;
1393
+ case "text":
1394
+ serialization = ",chardata";
1395
+ return serialization;
1344
1396
  }
1345
- if (field.xml?.attribute) {
1346
- // value comes from an xml attribute
1347
- serialization += ",attr";
1348
- }
1349
- else if (field.type.kind === "slice") {
1350
- // start with the serialized name of the element, preferring xml name if available
1351
- let inner = field.serializedName;
1352
- if (field.xml?.name) {
1353
- inner = field.xml.name;
1354
- }
1397
+ if (field.type.kind === "slice") {
1355
1398
  // arrays can be wrapped or unwrapped. here's a wrapped example
1356
1399
  // note how the array of apple objects is "wrapped" in GoodApples
1357
1400
  // <AppleBarrel>
@@ -1370,13 +1413,12 @@ function getXMLSerialization(field) {
1370
1413
  // <title>Overview</title>
1371
1414
  // </slide>
1372
1415
  // </slideshow>
1373
- // arrays in the response type are handled slightly different as we
1374
- // unmarshal directly into them so no need to add the unwrapping.
1375
- if (field.xml?.wraps) {
1376
- serialization += `>${field.xml.wraps}`;
1377
- }
1378
- else {
1379
- serialization = inner;
1416
+ // for unwrapped lists we use the serialized name on the field
1417
+ if (field.xmlKind !== "unwrappedList") {
1418
+ // start with the serialized name of the element, preferring xml name if available
1419
+ const unwrappedPtrType = go.unwrapPtr(field.type.elementType);
1420
+ const inner = field.type.xmlName ? field.type.xmlName : go.hasXMLName(unwrappedPtrType) ?? go.getTypeDeclaration(unwrappedPtrType, pkg);
1421
+ serialization += `>${inner}`;
1380
1422
  }
1381
1423
  }
1382
1424
  return serialization;