@azure-tools/typespec-go 0.10.7 → 0.11.0

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 (65) hide show
  1. package/dist/codegen.go/src/core/clientFactory.d.ts.map +1 -1
  2. package/dist/codegen.go/src/core/clientFactory.js +18 -15
  3. package/dist/codegen.go/src/core/clientFactory.js.map +1 -1
  4. package/dist/codegen.go/src/core/cloudConfig.d.ts.map +1 -1
  5. package/dist/codegen.go/src/core/cloudConfig.js +4 -3
  6. package/dist/codegen.go/src/core/cloudConfig.js.map +1 -1
  7. package/dist/codegen.go/src/core/constants.d.ts.map +1 -1
  8. package/dist/codegen.go/src/core/constants.js +6 -4
  9. package/dist/codegen.go/src/core/constants.js.map +1 -1
  10. package/dist/codegen.go/src/core/example.js +51 -52
  11. package/dist/codegen.go/src/core/example.js.map +1 -1
  12. package/dist/codegen.go/src/core/helpers.d.ts +27 -11
  13. package/dist/codegen.go/src/core/helpers.d.ts.map +1 -1
  14. package/dist/codegen.go/src/core/helpers.js +39 -15
  15. package/dist/codegen.go/src/core/helpers.js.map +1 -1
  16. package/dist/codegen.go/src/core/interfaces.d.ts.map +1 -1
  17. package/dist/codegen.go/src/core/interfaces.js +4 -3
  18. package/dist/codegen.go/src/core/interfaces.js.map +1 -1
  19. package/dist/codegen.go/src/core/models.d.ts.map +1 -1
  20. package/dist/codegen.go/src/core/models.js +289 -230
  21. package/dist/codegen.go/src/core/models.js.map +1 -1
  22. package/dist/codegen.go/src/core/operations.d.ts.map +1 -1
  23. package/dist/codegen.go/src/core/operations.js +585 -382
  24. package/dist/codegen.go/src/core/operations.js.map +1 -1
  25. package/dist/codegen.go/src/core/options.js +3 -2
  26. package/dist/codegen.go/src/core/options.js.map +1 -1
  27. package/dist/codegen.go/src/core/polymorphics.d.ts.map +1 -1
  28. package/dist/codegen.go/src/core/polymorphics.js +55 -48
  29. package/dist/codegen.go/src/core/polymorphics.js.map +1 -1
  30. package/dist/codegen.go/src/core/responses.d.ts.map +1 -1
  31. package/dist/codegen.go/src/core/responses.js +28 -19
  32. package/dist/codegen.go/src/core/responses.js.map +1 -1
  33. package/dist/codegen.go/src/core/version.d.ts.map +1 -1
  34. package/dist/codegen.go/src/core/version.js +3 -2
  35. package/dist/codegen.go/src/core/version.js.map +1 -1
  36. package/dist/codegen.go/src/fake/factory.d.ts.map +1 -1
  37. package/dist/codegen.go/src/fake/factory.js +2 -2
  38. package/dist/codegen.go/src/fake/factory.js.map +1 -1
  39. package/dist/codegen.go/src/fake/servers.d.ts.map +1 -1
  40. package/dist/codegen.go/src/fake/servers.js +311 -256
  41. package/dist/codegen.go/src/fake/servers.js.map +1 -1
  42. package/dist/codemodel.go/src/client.d.ts +37 -2
  43. package/dist/codemodel.go/src/client.d.ts.map +1 -1
  44. package/dist/codemodel.go/src/client.js +13 -0
  45. package/dist/codemodel.go/src/client.js.map +1 -1
  46. package/dist/codemodel.go/src/type.d.ts +2 -0
  47. package/dist/codemodel.go/src/type.d.ts.map +1 -1
  48. package/dist/codemodel.go/src/type.js +1 -0
  49. package/dist/codemodel.go/src/type.js.map +1 -1
  50. package/dist/typespec-go/src/tcgcadapter/adapter.d.ts.map +1 -1
  51. package/dist/typespec-go/src/tcgcadapter/adapter.js +1 -2
  52. package/dist/typespec-go/src/tcgcadapter/adapter.js.map +1 -1
  53. package/dist/typespec-go/src/tcgcadapter/clients.d.ts +8 -0
  54. package/dist/typespec-go/src/tcgcadapter/clients.d.ts.map +1 -1
  55. package/dist/typespec-go/src/tcgcadapter/clients.js +130 -50
  56. package/dist/typespec-go/src/tcgcadapter/clients.js.map +1 -1
  57. package/dist/typespec-go/src/tcgcadapter/helpers.d.ts +15 -0
  58. package/dist/typespec-go/src/tcgcadapter/helpers.d.ts.map +1 -1
  59. package/dist/typespec-go/src/tcgcadapter/helpers.js +34 -0
  60. package/dist/typespec-go/src/tcgcadapter/helpers.js.map +1 -1
  61. package/dist/typespec-go/src/tcgcadapter/types.d.ts +1 -0
  62. package/dist/typespec-go/src/tcgcadapter/types.d.ts.map +1 -1
  63. package/dist/typespec-go/src/tcgcadapter/types.js +43 -0
  64. package/dist/typespec-go/src/tcgcadapter/types.js.map +1 -1
  65. package/package.json +4 -4
@@ -65,8 +65,9 @@ export function generateOperations(pkg, target, options) {
65
65
  else {
66
66
  clientText += 'a constructor function instead.\n';
67
67
  }
68
+ const indent = new helpers.Indentation();
68
69
  clientText += `type ${client.name} struct {\n`;
69
- clientText += `\tinternal *${azureARM ? 'arm' : 'azcore'}.Client\n`;
70
+ clientText += `${indent.get()}internal *${azureARM ? 'arm' : 'azcore'}.Client\n`;
70
71
  // check for any optional host params
71
72
  const optionalParams = new Array();
72
73
  const isParamPointer = function (param) {
@@ -82,12 +83,12 @@ export function generateOperations(pkg, target, options) {
82
83
  }
83
84
  if (clientParam.group) {
84
85
  if (!addedGroups.has(clientParam.group.groupName)) {
85
- clientText += `\t${naming.uncapitalize(clientParam.group.groupName)} ${!isParamPointer(clientParam) ? '' : '*'}${clientParam.group.groupName}\n`;
86
+ clientText += `${indent.get()}${naming.uncapitalize(clientParam.group.groupName)} ${!isParamPointer(clientParam) ? '' : '*'}${clientParam.group.groupName}\n`;
86
87
  addedGroups.add(clientParam.group.groupName);
87
88
  }
88
89
  continue;
89
90
  }
90
- clientText += `\t${clientParam.name} `;
91
+ clientText += `${indent.get()}${clientParam.name} `;
91
92
  if (!isParamPointer(clientParam)) {
92
93
  clientText += `${go.getTypeDeclaration(clientParam.type, client.pkg)}\n`;
93
94
  }
@@ -101,7 +102,7 @@ export function generateOperations(pkg, target, options) {
101
102
  }
102
103
  // end of client definition
103
104
  clientText += '}\n\n';
104
- clientText += generateConstructors(client, target, imports);
105
+ clientText += generateConstructors(client, target, imports, indent);
105
106
  // generate client accessors and operations
106
107
  let opText = '';
107
108
  for (const clientAccessor of client.clientAccessors) {
@@ -109,7 +110,7 @@ export function generateOperations(pkg, target, options) {
109
110
  const subClientDecl = go.getTypeDeclaration(clientAccessor.returns, pkg);
110
111
  opText += helpers.formatDocComment(clientAccessor.docs);
111
112
  opText += `func (client *${client.name}) ${clientAccessor.name}(${getAPIParametersSig(clientAccessor, imports)}) *${subClientDecl} {\n`;
112
- opText += `\treturn &${subClientDecl}{\n`;
113
+ opText += `${indent.get()}return &${subClientDecl}{\n`;
113
114
  const initFields = new Array('internal: client.internal');
114
115
  // propagate all client params
115
116
  for (const param of clientAccessor.parameters) {
@@ -129,10 +130,12 @@ export function generateOperations(pkg, target, options) {
129
130
  }
130
131
  }
131
132
  initFields.sort();
133
+ indent.push();
132
134
  for (const initField of initFields) {
133
- opText += `\t\t${initField},\n`;
135
+ opText += `${indent.get()}${initField},\n`;
134
136
  }
135
- opText += '\t}\n}\n\n';
137
+ indent.pop();
138
+ opText += `${indent.get()}}\n}\n\n`;
136
139
  }
137
140
  const nextPageMethods = new Array();
138
141
  for (const method of client.methods) {
@@ -140,21 +143,21 @@ export function generateOperations(pkg, target, options) {
140
143
  // it must be done before the imports are written out
141
144
  if (go.isLROMethod(method)) {
142
145
  // generate Begin method
143
- opText += generateLROBeginMethod(method, imports, options);
146
+ opText += generateLROBeginMethod(method, options, imports, indent);
144
147
  }
145
- opText += generateOperation(method, imports, options);
146
- opText += createProtocolRequest(azureARM, method, imports);
148
+ opText += generateOperation(method, options, imports, indent);
149
+ opText += createProtocolRequest(azureARM, method, imports, indent);
147
150
  if (method.kind !== 'lroMethod') {
148
151
  // LRO responses are handled elsewhere, with the exception of pageable LROs
149
- opText += createProtocolResponse(method, imports);
152
+ opText += createProtocolResponse(method, imports, indent);
150
153
  }
151
- if ((method.kind === 'lroPageableMethod' || method.kind === 'pageableMethod') && method.nextPageMethod && !nextPageMethods.includes(method.nextPageMethod)) {
154
+ if (go.isPageableMethod(method) && method.strategy?.kind === 'nextLink' && method.strategy.method && !nextPageMethods.includes(method.strategy.method)) {
152
155
  // track the next page methods to generate as multiple operations can use the same next page operation
153
- nextPageMethods.push(method.nextPageMethod);
156
+ nextPageMethods.push(method.strategy.method);
154
157
  }
155
158
  }
156
159
  for (const method of nextPageMethods) {
157
- opText += createProtocolRequest(azureARM, method, imports);
160
+ opText += createProtocolRequest(azureARM, method, imports, indent);
158
161
  }
159
162
  // stitch it all together
160
163
  let text = helpers.contentPreamble(pkg);
@@ -173,7 +176,7 @@ export function generateOperations(pkg, target, options) {
173
176
  * @param imports the import manager currently in scope
174
177
  * @returns the client constructor code or the empty string
175
178
  */
176
- function generateConstructors(client, type, imports) {
179
+ function generateConstructors(client, type, imports, indent) {
177
180
  if (client.instance?.kind !== 'constructable') {
178
181
  return '';
179
182
  }
@@ -182,7 +185,7 @@ function generateConstructors(client, type, imports) {
182
185
  if (clientOptions.kind === 'clientOptions') {
183
186
  // for non-ARM, the options type will always be a parameter group
184
187
  ctorText += `// ${clientOptions.name} contains the optional values for creating a [${client.name}].\n`;
185
- ctorText += `type ${clientOptions.name} struct {\n\tazcore.ClientOptions\n`;
188
+ ctorText += `type ${clientOptions.name} struct {\n${indent.get()}azcore.ClientOptions\n`;
186
189
  for (const param of clientOptions.parameters) {
187
190
  if (go.isAPIVersionParameter(param)) {
188
191
  // we use azcore.ClientOptions.APIVersion
@@ -193,9 +196,9 @@ function generateConstructors(client, type, imports) {
193
196
  if (!param.docs.description && !param.docs.summary) {
194
197
  ctorText += '\n';
195
198
  }
196
- ctorText += `\t${helpers.comment(`The default value is ${helpers.formatLiteralValue(param.style.defaultValue, false)}`, '// ')}.\n`;
199
+ ctorText += `${indent.get()}${helpers.comment(`The default value is ${helpers.formatLiteralValue(param.style.defaultValue, false)}`, '// ')}.\n`;
197
200
  }
198
- ctorText += `\t${naming.ensureNameCase(param.name)} *${go.getTypeDeclaration(param.type, client.pkg)}\n`;
201
+ ctorText += `${indent.get()}${naming.ensureNameCase(param.name)} *${go.getTypeDeclaration(param.type, client.pkg)}\n`;
199
202
  }
200
203
  ctorText += '}\n\n';
201
204
  }
@@ -228,7 +231,9 @@ function generateConstructors(client, type, imports) {
228
231
  }
229
232
  const emitProlog = function (optionsTypeName, tokenAuth, plOpts) {
230
233
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
231
- let bodyText = `\tif options == nil {\n\t\toptions = &${optionsTypeName}{}\n\t}\n`;
234
+ let bodyText = `${indent.get()}if options == nil {\n`;
235
+ bodyText += `${indent.push().get()}options = &${optionsTypeName}{}\n`;
236
+ bodyText += `${indent.pop().get()}}\n`;
232
237
  let apiVersionConfig = '';
233
238
  // check if there's an api version parameter
234
239
  let apiVersionParam;
@@ -247,13 +252,15 @@ function generateConstructors(client, type, imports) {
247
252
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud');
248
253
  imports.add('fmt');
249
254
  imports.add('reflect');
250
- bodyText += '\tif reflect.ValueOf(options.Cloud).IsZero() {\n';
251
- bodyText += '\t\toptions.Cloud = cloud.AzurePublic\n\t}\n';
252
- bodyText += '\tc, ok := options.Cloud.Services[ServiceName]\n';
253
- bodyText += '\tif !ok {\n';
254
- bodyText += '\t\treturn nil, fmt.Errorf("provided Cloud field is missing configuration for %s", ServiceName)\n';
255
- bodyText += '\t} else if c.Audience == "" {\n';
256
- bodyText += '\t\treturn nil, fmt.Errorf("provided Cloud field is missing Audience for %s", ServiceName)\n\t}\n';
255
+ bodyText += `${indent.get()}if reflect.ValueOf(options.Cloud).IsZero() {\n`;
256
+ bodyText += `${indent.push().get()}options.Cloud = cloud.AzurePublic\n`;
257
+ bodyText += `${indent.pop().get()}}\n`;
258
+ bodyText += `${indent.get()}c, ok := options.Cloud.Services[ServiceName]\n`;
259
+ bodyText += `${indent.get()}if !ok {\n`;
260
+ bodyText += `${indent.push().get()}return nil, fmt.Errorf("provided Cloud field is missing configuration for %s", ServiceName)\n`;
261
+ bodyText += `${indent.pop().get()}} else if c.Audience == "" {\n`;
262
+ bodyText += `${indent.push().get()}return nil, fmt.Errorf("provided Cloud field is missing Audience for %s", ServiceName)\n`;
263
+ bodyText += `${indent.pop().get()}}\n`;
257
264
  }
258
265
  if (apiVersionParam) {
259
266
  let location;
@@ -273,18 +280,23 @@ function generateConstructors(client, type, imports) {
273
280
  name = apiVersionParam.queryParameter;
274
281
  break;
275
282
  }
283
+ indent.push(); // level 2 for PipelineOptions fields
276
284
  if (name) {
277
- name = `\n\t\t\tName: "${name}",`;
285
+ indent.push(); // level 3 for APIVersionOptions fields
286
+ name = `\n${indent.get()}Name: "${name}",`;
287
+ indent.pop(); // back to level 2
278
288
  }
279
289
  else {
280
290
  name = '';
281
291
  }
282
- apiVersionConfig = `\n\t\tAPIVersion: runtime.APIVersionOptions{${name}\n\t\t\tLocation: runtime.APIVersionLocation${location},\n\t\t},`;
292
+ indent.push(); // level 3 for APIVersionOptions fields
293
+ apiVersionConfig = `\n${indent.pop().get()}APIVersion: runtime.APIVersionOptions{${name}\n${indent.push().get()}Location: runtime.APIVersionLocation${location},\n${indent.pop().get()}},`;
294
+ indent.pop(); // back to level 1
283
295
  if (!plOpts) {
284
296
  apiVersionConfig += '\n';
285
297
  }
286
298
  }
287
- bodyText += `\tcl, err := azcore.NewClient(moduleName, moduleVersion, runtime.PipelineOptions{${apiVersionConfig}${plOpts ?? ''}}, &options.ClientOptions)\n`;
299
+ bodyText += `${indent.get()}cl, err := azcore.NewClient(moduleName, moduleVersion, runtime.PipelineOptions{${apiVersionConfig}${plOpts ?? ''}}, &options.ClientOptions)\n`;
288
300
  return bodyText;
289
301
  };
290
302
  // check if there's a credential parameter
@@ -304,16 +316,19 @@ function generateConstructors(client, type, imports) {
304
316
  switch (clientOptions.kind) {
305
317
  case 'clientOptions': {
306
318
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/policy');
307
- const tokenPolicyOpts = '&policy.BearerTokenOptions{\n\t\t\tInsecureAllowCredentialWithHTTP: options.InsecureAllowCredentialWithHTTP,\n\t\t}';
319
+ indent.push(); // level 2 for PipelineOptions fields
320
+ indent.push(); // level 3 for BearerTokenOptions fields
321
+ const tokenPolicyOpts = `&policy.BearerTokenOptions{\n${indent.get()}InsecureAllowCredentialWithHTTP: options.InsecureAllowCredentialWithHTTP,\n${indent.pop().get()}}`;
308
322
  // we assume a single scope. this is enforced when adapting the data from tcgc
309
- const tokenPolicy = `\n\t\tPerCall: []policy.Policy{\n\t\truntime.NewBearerTokenPolicy(credential, []string{c.Audience + "${helpers.splitScope(credentialParam.type.scopes[0]).scope}"}, ${tokenPolicyOpts}),\n\t\t},\n`;
323
+ const tokenPolicy = `\n${indent.get()}PerCall: []policy.Policy{\n${indent.get()}runtime.NewBearerTokenPolicy(credential, []string{c.Audience + "${helpers.splitScope(credentialParam.type.scopes[0]).scope}"}, ${tokenPolicyOpts}),\n${indent.get()}},\n`;
324
+ indent.pop(); // back to level 1
310
325
  prolog = emitProlog(go.getTypeDeclaration(clientOptions, client.pkg), true, tokenPolicy);
311
326
  break;
312
327
  }
313
328
  case 'armClientOptions':
314
329
  // this is the ARM case
315
330
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/arm');
316
- prolog = '\tcl, err := arm.NewClient(moduleName, moduleVersion, credential, options)\n';
331
+ prolog = `${indent.get()}cl, err := arm.NewClient(moduleName, moduleVersion, credential, options)\n`;
317
332
  break;
318
333
  }
319
334
  break;
@@ -331,9 +346,9 @@ function generateConstructors(client, type, imports) {
331
346
  }
332
347
  ctorText += `func ${constructor.name}(${ctorParams.join(', ')}) (*${client.name}, error) {\n`;
333
348
  ctorText += prolog;
334
- ctorText += '\tif err != nil {\n';
335
- ctorText += '\t\treturn nil, err\n';
336
- ctorText += '\t}\n';
349
+ ctorText += `${indent.get()}if err != nil {\n`;
350
+ ctorText += `${indent.push().get()}return nil, err\n`;
351
+ ctorText += `${indent.pop().get()}}\n`;
337
352
  // handle any client-side defaults
338
353
  if (clientOptions.kind === 'clientOptions') {
339
354
  for (const param of clientOptions.parameters) {
@@ -345,8 +360,10 @@ function generateConstructors(client, type, imports) {
345
360
  else {
346
361
  name = naming.ensureNameCase(param.name);
347
362
  }
348
- ctorText += `\t${param.name} := ${helpers.formatLiteralValue(param.style.defaultValue, false)}\n`;
349
- ctorText += `\tif options.${name} != ${helpers.zeroValue(param)} {\n\t\t${param.name} = ${helpers.star(param.byValue)}options.${name}\n\t}\n`;
363
+ ctorText += `${indent.get()}${param.name} := ${helpers.formatLiteralValue(param.style.defaultValue, false)}\n`;
364
+ ctorText += `${indent.get()}if options.${name} != ${helpers.zeroValue(param)} {\n`;
365
+ ctorText += `${indent.push().get()}${param.name} = ${helpers.star(param.byValue)}options.${name}\n`;
366
+ ctorText += `${indent.pop().get()}}\n`;
350
367
  }
351
368
  }
352
369
  }
@@ -356,15 +373,15 @@ function generateConstructors(client, type, imports) {
356
373
  const endpointParam = client.instance.constructors[0].parameters[0];
357
374
  if (client.instance.endpoint.supplemental.parameters.length > 0) {
358
375
  imports.add('strings');
359
- ctorText += `\thost := "${client.instance.endpoint.supplemental.path}"\n`;
376
+ ctorText += `${indent.get()}host := "${client.instance.endpoint.supplemental.path}"\n`;
360
377
  for (const param of client.instance.endpoint.supplemental.parameters) {
361
- ctorText += `\thost = strings.ReplaceAll(host, "{${param.uriPathSegment}}", ${helpers.formatValue(param.name, param.type, imports)})\n`;
378
+ ctorText += `${indent.get()}host = strings.ReplaceAll(host, "{${param.uriPathSegment}}", ${helpers.formatValue(param.name, param.type, imports)})\n`;
362
379
  }
363
- ctorText += `\t${endpointParam.name} = runtime.JoinPaths(${endpointParam.name}, host)\n`;
380
+ ctorText += `${indent.get()}${endpointParam.name} = runtime.JoinPaths(${endpointParam.name}, host)\n`;
364
381
  }
365
382
  else {
366
383
  // there are no params for the supplemental host, so just append it
367
- ctorText += `\t${endpointParam.name} = runtime.JoinPaths(${endpointParam.name}, "${client.instance.endpoint.supplemental.path}")\n`;
384
+ ctorText += `${indent.get()}${endpointParam.name} = runtime.JoinPaths(${endpointParam.name}, "${client.instance.endpoint.supplemental.path}")\n`;
368
385
  }
369
386
  }
370
387
  // construct client literal
@@ -376,122 +393,139 @@ function generateConstructors(client, type, imports) {
376
393
  break;
377
394
  }
378
395
  }
379
- ctorText += `\t${clientVar} := &${client.name}{\n`;
396
+ ctorText += `${indent.get()}${clientVar} := &${client.name}{\n`;
380
397
  // NOTE: we don't enumerate consolidatedCtorParams here
381
398
  // as any supplemental endpoint params are ephemeral and
382
399
  // consumed during client construction.
400
+ indent.push();
383
401
  for (const parameter of client.parameters) {
384
402
  if (go.isLiteralParameter(parameter.style)) {
385
403
  continue;
386
404
  }
387
405
  // each client field will have a matching parameter with the same name
388
- ctorText += `\t\t${parameter.name}: ${parameter.name},\n`;
406
+ ctorText += `${indent.get()}${parameter.name}: ${parameter.name},\n`;
389
407
  }
390
- ctorText += '\tinternal: cl,\n';
391
- ctorText += '\t}\n';
392
- ctorText += `\treturn ${clientVar}, nil\n`;
408
+ ctorText += `${indent.get()}internal: cl,\n`;
409
+ indent.pop();
410
+ ctorText += `${indent.get()}}\n`;
411
+ ctorText += `${indent.get()}return ${clientVar}, nil\n`;
393
412
  ctorText += '}\n\n';
394
413
  }
395
414
  return ctorText;
396
415
  }
397
416
  // use this to generate the code that will help process values returned in response headers
398
- function formatHeaderResponseValue(method, headerResp, imports, respObj, zeroResp) {
417
+ function formatHeaderResponseValue(method, headerResp, respObj, zeroResp, imports, indent) {
399
418
  // dictionaries are handled slightly different so we do that first
400
419
  if (headerResp.kind === 'headerMapResponse') {
401
420
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/to');
402
421
  imports.add('strings');
403
422
  const headerPrefix = headerResp.headerName;
404
- let text = '\tfor hh := range resp.Header {\n';
405
- text += `\t\tif len(hh) > len("${headerPrefix}") && strings.EqualFold(hh[:len("${headerPrefix}")], "${headerPrefix}") {\n`;
406
- text += `\t\t\tif ${respObj}.${headerResp.fieldName} == nil {\n`;
407
- text += `\t\t\t\t${respObj}.${headerResp.fieldName} = map[string]*string{}\n`;
408
- text += '\t\t\t}\n';
409
- text += `\t\t\t${respObj}.${headerResp.fieldName}[hh[len("${headerPrefix}"):]] = to.Ptr(resp.Header.Get(hh))\n`;
410
- text += '\t\t}\n';
411
- text += '\t}\n';
423
+ let text = `${indent.get()}for hh := range resp.Header {\n`;
424
+ text += `${indent.push().get()}if len(hh) > len("${headerPrefix}") && strings.EqualFold(hh[:len("${headerPrefix}")], "${headerPrefix}") {\n`;
425
+ text += `${indent.push().get()}if ${respObj}.${headerResp.fieldName} == nil {\n`;
426
+ text += `${indent.push().get()}${respObj}.${headerResp.fieldName} = map[string]*string{}\n`;
427
+ text += `${indent.pop().get()}}\n`;
428
+ text += `${indent.get()}${respObj}.${headerResp.fieldName}[hh[len("${headerPrefix}"):]] = to.Ptr(resp.Header.Get(hh))\n`;
429
+ text += `${indent.pop().get()}}\n`;
430
+ text += `${indent.pop().get()}}\n`;
412
431
  return text;
413
432
  }
414
- let text = `\tif val := resp.Header.Get("${headerResp.headerName}"); val != "" {\n`;
433
+ let text = `${indent.get()}if val := resp.Header.Get("${headerResp.headerName}"); val != "" {\n`;
434
+ indent.push();
415
435
  let name = naming.uncapitalize(headerResp.fieldName);
416
436
  let byRef = '&';
417
437
  switch (headerResp.type.kind) {
418
438
  case 'constant':
419
439
  case 'etag':
420
- text += `\t\t${respObj}.${headerResp.fieldName} = (*${go.getTypeDeclaration(headerResp.type, method.receiver.type.pkg)})(&val)\n`;
421
- text += '\t}\n';
440
+ text += `${indent.get()}${respObj}.${headerResp.fieldName} = (*${go.getTypeDeclaration(headerResp.type, method.receiver.type.pkg)})(&val)\n`;
441
+ indent.pop();
442
+ text += `${indent.get()}}\n`;
422
443
  return text;
423
444
  case 'encodedBytes':
424
445
  // a base-64 encoded value in string format
425
446
  imports.add('encoding/base64');
426
- text += `\t\t${name}, err := base64.${helpers.formatBytesEncoding(headerResp.type.encoding)}Encoding.DecodeString(val)\n`;
447
+ text += `${indent.get()}${name}, err := base64.${helpers.formatBytesEncoding(headerResp.type.encoding)}Encoding.DecodeString(val)\n`;
427
448
  byRef = '';
428
449
  break;
429
450
  case 'literal':
430
- text += `\t\t${respObj}.${headerResp.fieldName} = &val\n`;
431
- text += '\t}\n';
451
+ text += `${indent.get()}${respObj}.${headerResp.fieldName} = &val\n`;
452
+ indent.pop();
453
+ text += `${indent.get()}}\n`;
432
454
  return text;
433
455
  case 'scalar':
434
456
  imports.add('strconv');
435
457
  switch (headerResp.type.type) {
436
458
  case 'bool':
437
- text += `\t\t${name}, err := strconv.ParseBool(val)\n`;
459
+ text += `${indent.get()}${name}, err := strconv.ParseBool(val)\n`;
438
460
  break;
439
461
  case 'float32':
440
- text += `\t\t${name}32, err := strconv.ParseFloat(val, 32)\n`;
441
- text += `\t\t${name} := float32(${name}32)\n`;
462
+ text += `${indent.get()}${name}32, err := strconv.ParseFloat(val, 32)\n`;
463
+ text += `${indent.get()}${name} := float32(${name}32)\n`;
442
464
  break;
443
465
  case 'float64':
444
- text += `\t\t${name}, err := strconv.ParseFloat(val, 64)\n`;
466
+ text += `${indent.get()}${name}, err := strconv.ParseFloat(val, 64)\n`;
445
467
  break;
446
468
  case 'int32':
447
- text += `\t\t${name}32, err := strconv.ParseInt(val, 10, 32)\n`;
448
- text += `\t\t${name} := int32(${name}32)\n`;
469
+ text += `${indent.get()}${name}32, err := strconv.ParseInt(val, 10, 32)\n`;
470
+ text += `${indent.get()}${name} := int32(${name}32)\n`;
449
471
  break;
450
472
  case 'int64':
451
- text += `\t\t${name}, err := strconv.ParseInt(val, 10, 64)\n`;
473
+ text += `${indent.get()}${name}, err := strconv.ParseInt(val, 10, 64)\n`;
452
474
  break;
453
475
  default:
454
476
  throw new CodegenError('InternalError', `unhandled scalar type ${headerResp.type.type}`);
455
477
  }
456
478
  break;
457
479
  case 'string':
458
- text += `\t\t${respObj}.${headerResp.fieldName} = &val\n`;
459
- text += '\t}\n';
480
+ text += `${indent.get()}${respObj}.${headerResp.fieldName} = &val\n`;
481
+ text += `${indent.pop().get()}}\n`;
460
482
  return text;
461
483
  case 'time':
462
484
  imports.add('time');
463
485
  switch (headerResp.type.format) {
464
486
  case 'RFC1123':
465
487
  case 'RFC3339':
466
- text += `\t\t${name}, err := time.Parse(${headerResp.type.format === 'RFC1123' ? helpers.RFC1123Format : helpers.RFC3339Format}, val)\n`;
488
+ text += `${indent.get()}${name}, err := time.Parse(${headerResp.type.format === 'RFC1123' ? helpers.RFC1123Format : helpers.RFC3339Format}, val)\n`;
467
489
  break;
468
490
  case 'PlainDate':
469
- text += `\t\t${name}, err := time.Parse(${helpers.plainDateFormat}, val)\n`;
491
+ text += `${indent.get()}${name}, err := time.Parse(${helpers.plainDateFormat}, val)\n`;
470
492
  break;
471
493
  case 'PlainTime':
472
- text += `\t\t${name}, err := time.Parse(${helpers.plainTimeFormat}, val)\n`;
494
+ text += `${indent.get()}${name}, err := time.Parse(${helpers.plainTimeFormat}, val)\n`;
473
495
  break;
474
496
  case 'Unix':
475
497
  imports.add('strconv');
476
498
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/to');
477
- text += '\t\tsec, err := strconv.ParseInt(val, 10, 64)\n';
499
+ text += `${indent.get()}sec, err := strconv.ParseInt(val, 10, 64)\n`;
478
500
  name = 'to.Ptr(time.Unix(sec, 0))';
479
501
  byRef = '';
480
502
  break;
481
503
  }
482
504
  }
483
505
  // NOTE: only cases that required parsing will fall through to here
484
- text += '\t\tif err != nil {\n';
485
- text += `\t\t\treturn ${zeroResp}, err\n`;
486
- text += '\t\t}\n';
487
- text += `\t\t${respObj}.${headerResp.fieldName} = ${byRef}${name}\n`;
488
- text += '\t}\n';
506
+ text += `${indent.get()}if err != nil {\n`;
507
+ text += `${indent.push().get()}return ${zeroResp}, err\n`;
508
+ text += `${indent.pop().get()}}\n`;
509
+ text += `${indent.get()}${respObj}.${headerResp.fieldName} = ${byRef}${name}\n`;
510
+ text += `${indent.pop().get()}}\n`;
489
511
  return text;
490
512
  }
513
+ /**
514
+ * returns the zero value for the specified method.
515
+ * note that the zero value will be different depending
516
+ * on which API for the method is being called.
517
+ *
518
+ * @param method the method to determine the zero value
519
+ * @param apiType the method's API that's being invoked
520
+ * lro - the exported LRO API
521
+ * op - the operation method. for sync methods this is the exported API. for LROs it's the internal method called by Begin*
522
+ * handler - the internal response handler method
523
+ * @returns the zero value
524
+ */
491
525
  function getZeroReturnValue(method, apiType) {
492
526
  let returnType = `${method.returns.name}{}`;
493
527
  if (go.isLROMethod(method)) {
494
- if (apiType === 'api' || apiType === 'op') {
528
+ if (apiType === 'lro' || apiType === 'op') {
495
529
  // the api returns a *Poller[T]
496
530
  // the operation returns an *http.Response
497
531
  returnType = 'nil';
@@ -499,96 +533,222 @@ function getZeroReturnValue(method, apiType) {
499
533
  }
500
534
  return returnType;
501
535
  }
502
- // Helper function to generate nil checks for a dotted path
503
- function generateNilChecks(path, prefix = 'page') {
504
- const segments = path.split('.');
536
+ /**
537
+ * Helper function to generate nil checks for a segmented path
538
+ * e.g. page.Foo != nil && page.Foo.Bar != nil
539
+ *
540
+ * @param segments the field segments
541
+ * @param varName optional variable name containing the fields
542
+ * @param omitLastSegment when true, omits the last item in segments.
543
+ * note that this can cause the function to return the empty string when segments.length === 1
544
+ * @returns the sequence of nil checks
545
+ */
546
+ function generateNilChecks(segments, varName = 'page', omitLastSegment = false) {
505
547
  const checks = [];
506
- for (let i = 0; i < segments.length; i++) {
507
- const currentPath = [prefix, ...segments.slice(0, i + 1)].join('.');
548
+ let segmentCount = segments.length;
549
+ if (omitLastSegment) {
550
+ segmentCount -= 1;
551
+ }
552
+ for (let i = 0; i < segmentCount; i++) {
553
+ const currentPath = [varName, ...segments.map((segment) => segment.name).slice(0, i + 1)].join('.');
508
554
  checks.push(`${currentPath} != nil`);
509
555
  }
510
556
  return checks.join(' && ');
511
557
  }
512
- function emitPagerDefinition(method, imports, options) {
558
+ /**
559
+ * emits code that calls runtime.NewPager
560
+ *
561
+ * @param method the pageable method
562
+ * @param options emitter options
563
+ * @param imports the import manager currently in scope
564
+ * @param indent the indentation helper currently in scope
565
+ * @returns the complete call to runtime.NewPager(...)
566
+ */
567
+ function emitPagerDefinition(method, options, imports, indent) {
513
568
  imports.add('context');
514
569
  let text = `runtime.NewPager(runtime.PagingHandler[${method.returns.name}]{\n`;
515
- text += `\t\tMore: func(page ${method.returns.name}) bool {\n`;
516
- // there is no advancer for single-page pagers
517
- if (method.nextLinkName) {
518
- const nilChecks = generateNilChecks(method.nextLinkName);
519
- text += `\t\t\treturn ${nilChecks} && len(*page.${method.nextLinkName}) > 0\n`;
520
- text += '\t\t},\n';
570
+ text += `${indent.push().get()}More: func(page ${method.returns.name}) bool {\n`;
571
+ indent.push();
572
+ if (method.strategy) {
573
+ const moreForNextLinkPath = function (strategy) {
574
+ const nilChecks = generateNilChecks(strategy.nextLinkPath);
575
+ const nextLinkPath = helpers.buildNextLinkPath(strategy);
576
+ text += `${indent.get()}return ${nilChecks} && len(*page.${nextLinkPath}) > 0\n`;
577
+ };
578
+ switch (method.strategy.kind) {
579
+ case 'continuationToken': {
580
+ switch (method.strategy.responseToken.kind) {
581
+ case 'headerScalarResponse':
582
+ const tokenRespField = method.strategy.responseToken.fieldName;
583
+ text += `${indent.get()}return page.${tokenRespField} != nil && len(*page.${tokenRespField}) > 0\n`;
584
+ break;
585
+ case 'nextLink':
586
+ moreForNextLinkPath(method.strategy.responseToken);
587
+ break;
588
+ default:
589
+ method.strategy.responseToken;
590
+ }
591
+ break;
592
+ }
593
+ case 'nextLink': {
594
+ moreForNextLinkPath(method.strategy);
595
+ break;
596
+ }
597
+ default:
598
+ method.strategy;
599
+ }
521
600
  }
522
601
  else {
523
- text += '\t\t\treturn false\n';
524
- text += '\t\t},\n';
602
+ // there is no advancer for single-page pagers
603
+ text += `${indent.get()}return false\n`;
525
604
  }
526
- text += `\t\tFetcher: func(ctx context.Context, page *${method.returns.name}) (${method.returns.name}, error) {\n`;
605
+ text += `${indent.pop().get()}},\n`; // end More func
606
+ text += `${indent.get()}Fetcher: func(ctx context.Context, page *${method.returns.name}) (${method.returns.name}, error) {\n`;
607
+ indent.push();
527
608
  const reqParams = helpers.getCreateRequestParameters(method);
528
609
  if (options.generateFakes) {
529
- text += `\t\tctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "${method.receiver.type.name}.${fixUpMethodName(method)}")\n`;
530
- }
531
- if (method.nextLinkName) {
532
- let nextLinkVar;
533
- if (method.kind === 'pageableMethod') {
534
- text += '\t\t\tnextLink := ""\n';
535
- nextLinkVar = 'nextLink';
536
- text += '\t\t\tif page != nil {\n';
537
- text += `\t\t\t\tnextLink = *page.${method.nextLinkName}\n\t\t\t}\n`;
538
- }
539
- else {
540
- nextLinkVar = `*page.${method.nextLinkName}`;
541
- }
542
- text += `\t\t\tresp, err := runtime.FetcherForNextLink(ctx, client.internal.Pipeline(), ${nextLinkVar}, func(ctx context.Context) (*policy.Request, error) {\n`;
543
- text += `\t\t\t\treturn client.${method.naming.requestMethod}(${reqParams})\n\t\t\t}, `;
544
- // nextPageMethod might be absent in some cases, see https://github.com/Azure/autorest/issues/4393
545
- if (method.nextPageMethod) {
546
- const nextOpParams = helpers.getCreateRequestParametersSig(method.nextPageMethod).split(',');
547
- // keep the parameter names from the name/type tuples and find nextLink param
548
- for (let i = 0; i < nextOpParams.length; ++i) {
549
- const paramName = nextOpParams[i].trim().split(' ')[0];
550
- const paramType = nextOpParams[i].trim().split(' ')[1];
551
- if (paramName.startsWith('next') && paramType === 'string') {
552
- nextOpParams[i] = 'encodedNextLink';
610
+ text += `${indent.get()}ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, "${method.receiver.type.name}.${fixUpMethodName(method)}")\n`;
611
+ }
612
+ /** emits code to check the HTTP status code and conditionally call the response handler */
613
+ const emitStatusCodeCheckAndResponse = function (respVarName, indent) {
614
+ let content = `${indent.get()}${helpers.buildIfBlock(indent, {
615
+ condition: `!runtime.HasStatusCode(${respVarName}, http.StatusOK)`,
616
+ body: (indent) => `${indent.get()}return ${getZeroReturnValue(method, 'op')}, runtime.NewResponseError(${respVarName})\n`,
617
+ })}\n`;
618
+ content += `${indent.get()}return client.${method.naming.responseMethod}(${respVarName})\n`;
619
+ return content;
620
+ };
621
+ if (method.strategy) {
622
+ switch (method.strategy.kind) {
623
+ case 'continuationToken': {
624
+ const ms = method.strategy;
625
+ const optionsCopy = 'nextOpts';
626
+ text += `${indent.get()}${optionsCopy} := ${method.optionalParamsGroup.groupName}{}\n`;
627
+ text += `${indent.get()}${helpers.buildIfBlock(indent, {
628
+ condition: `${method.optionalParamsGroup.name} != nil`,
629
+ body: (indent) => `${indent.get()}${optionsCopy} = *${method.optionalParamsGroup.name}\n`,
630
+ })}\n`;
631
+ let respToken;
632
+ let nestedNilChecks = '';
633
+ switch (ms.responseToken.kind) {
634
+ case 'headerScalarResponse':
635
+ respToken = ms.responseToken.fieldName;
636
+ break;
637
+ case 'nextLink':
638
+ respToken = helpers.buildNextLinkPath(ms.responseToken);
639
+ if (ms.responseToken.nextLinkPath.length > 1) {
640
+ // we don't need to check the last field for nil as we'll just
641
+ // assign it to the corresponding field in the options param
642
+ nestedNilChecks = ` && ${generateNilChecks(ms.responseToken.nextLinkPath, 'page', true)}`;
643
+ }
644
+ break;
645
+ }
646
+ text += `${indent.get()}${helpers.buildIfBlock(indent, {
647
+ condition: `page != nil${nestedNilChecks}`,
648
+ body: (indent) => `${indent.get()}${optionsCopy}.${ms.requestToken.name} = page.${respToken}\n`,
649
+ })}\n`;
650
+ text += callCreateRequestWithErrCheck(method, 'req', indent, `&${optionsCopy}`);
651
+ text += callPipelineDoWithErrCheck(method, 'req', 'resp', indent);
652
+ text += emitStatusCodeCheckAndResponse('resp', indent);
653
+ break;
654
+ }
655
+ case 'nextLink': {
656
+ const nextLinkPath = helpers.buildNextLinkPath(method.strategy);
657
+ let nextLinkVar;
658
+ if (method.kind === 'pageableMethod') {
659
+ text += `${indent.get()}nextLink := ""\n`;
660
+ nextLinkVar = 'nextLink';
661
+ text += `${indent.get()}if page != nil {\n`;
662
+ text += `${indent.push().get()}nextLink = *page.${nextLinkPath}\n`;
663
+ text += `${indent.pop().get()}}\n`;
553
664
  }
554
665
  else {
555
- nextOpParams[i] = paramName;
666
+ nextLinkVar = `*page.${nextLinkPath}`;
667
+ }
668
+ text += `${indent.get()}resp, err := runtime.FetcherForNextLink(ctx, client.internal.Pipeline(), ${nextLinkVar}, func(ctx context.Context) (*policy.Request, error) {\n`;
669
+ text += `${indent.push().get()}return client.${method.naming.requestMethod}(${reqParams})\n`;
670
+ text += `${indent.pop().get()}}, `;
671
+ // nextPageMethod might be absent in some cases, see https://github.com/Azure/autorest/issues/4393
672
+ if (method.strategy.method) {
673
+ const nextOpParams = helpers.getCreateRequestParametersSig(method.strategy.method).split(',');
674
+ // keep the parameter names from the name/type tuples and find nextLink param
675
+ for (let i = 0; i < nextOpParams.length; ++i) {
676
+ const paramName = nextOpParams[i].trim().split(' ')[0];
677
+ const paramType = nextOpParams[i].trim().split(' ')[1];
678
+ if (paramName.startsWith('next') && paramType === 'string') {
679
+ nextOpParams[i] = 'encodedNextLink';
680
+ }
681
+ else {
682
+ nextOpParams[i] = paramName;
683
+ }
684
+ }
685
+ // add a definition for the nextReq func that uses the nextLinkOperation
686
+ indent.push();
687
+ text += `&runtime.FetcherForNextLinkOptions{\n`;
688
+ text += `${indent.get()}NextReq: func(ctx context.Context, encodedNextLink string) (*policy.Request, error) {\n`;
689
+ text += `${indent.push().get()}return client.${method.strategy.method.name}(${nextOpParams.join(', ')})\n`;
690
+ text += `${indent.pop().get()}},\n`;
691
+ text += `${indent.pop().get()}})\n`;
692
+ }
693
+ else if (method.nextLinkVerb !== 'get') {
694
+ text += `&runtime.FetcherForNextLinkOptions{\n`;
695
+ text += `${indent.push().get()}HTTPVerb: http.Method${naming.capitalize(method.nextLinkVerb)},\n`;
696
+ text += `${indent.pop().get()}})\n`;
556
697
  }
698
+ else {
699
+ text += 'nil)\n';
700
+ }
701
+ text += `${indent.get()}if err != nil {\n`;
702
+ text += `${indent.push().get()}return ${method.returns.name}{}, err\n`;
703
+ text += `${indent.pop().get()}}\n`;
704
+ text += `${indent.get()}return client.${method.naming.responseMethod}(resp)\n`;
557
705
  }
558
- // add a definition for the nextReq func that uses the nextLinkOperation
559
- text += '&runtime.FetcherForNextLinkOptions{\n\t\t\t\tNextReq: func(ctx context.Context, encodedNextLink string) (*policy.Request, error) {\n';
560
- text += `\t\t\t\t\treturn client.${method.nextPageMethod.name}(${nextOpParams.join(', ')})\n\t\t\t\t},\n\t\t\t})\n`;
561
706
  }
562
- else if (method.nextLinkVerb !== 'get') {
563
- text += `&runtime.FetcherForNextLinkOptions{\n\t\t\t\tHTTPVerb: http.Method${naming.capitalize(method.nextLinkVerb)},\n\t\t\t})\n`;
564
- }
565
- else {
566
- text += 'nil)\n';
567
- }
568
- text += `\t\t\tif err != nil {\n\t\t\t\treturn ${method.returns.name}{}, err\n\t\t\t}\n`;
569
- text += `\t\t\treturn client.${method.naming.responseMethod}(resp)\n`;
570
- text += '\t\t\t},\n';
571
707
  }
572
708
  else {
573
709
  // this is the singular page case, no fetcher helper required
574
- text += `\t\t\treq, err := client.${method.naming.requestMethod}(${reqParams})\n`;
575
- text += '\t\t\tif err != nil {\n';
576
- text += `\t\t\t\treturn ${method.returns.name}{}, err\n`;
577
- text += '\t\t\t}\n';
578
- text += '\t\t\tresp, err := client.internal.Pipeline().Do(req)\n';
579
- text += '\t\t\tif err != nil {\n';
580
- text += `\t\t\t\treturn ${method.returns.name}{}, err\n`;
581
- text += '\t\t\t}\n';
582
- text += '\t\t\tif !runtime.HasStatusCode(resp, http.StatusOK) {\n';
583
- text += `\t\t\t\treturn ${method.returns.name}{}, runtime.NewResponseError(resp)\n`;
584
- text += '\t\t\t}\n';
585
- text += `\t\t\treturn client.${method.naming.responseMethod}(resp)\n`;
586
- text += '\t\t},\n';
710
+ text += callCreateRequestWithErrCheck(method, 'req', indent);
711
+ text += callPipelineDoWithErrCheck(method, 'req', 'resp', indent);
712
+ text += emitStatusCodeCheckAndResponse('resp', indent);
587
713
  }
714
+ text += `${indent.pop().get()}},\n`; // end Fetcher func
588
715
  if (options.injectSpans) {
589
- text += '\t\tTracer: client.internal.Tracer(),\n';
716
+ text += `${indent.get()}Tracer: client.internal.Tracer(),\n`;
590
717
  }
591
- text += '\t})\n';
718
+ text += `${indent.pop().get()}})\n`; // end runtime.NewPager
719
+ return text;
720
+ }
721
+ /**
722
+ * emits the call to the *CreateRequest method for an SDK method.
723
+ * if the call returns an error, the error is propagated to the caller.
724
+ *
725
+ * @param method the method to call its *CreateRequest method
726
+ * @param reqVarName the var name of the resultant *policy.Request
727
+ * @param indent the indentation helper currently in scope
728
+ * @param optionsParam optional custom param name for the method options param
729
+ * @returns the call to *CreateRequest with an error check
730
+ */
731
+ function callCreateRequestWithErrCheck(method, reqVarName, indent, optionsParam) {
732
+ const reqParams = helpers.getCreateRequestParameters(method, optionsParam);
733
+ let text = `${indent.get()}${reqVarName}, err := client.${method.naming.requestMethod}(${reqParams})\n`;
734
+ const zeroResp = getZeroReturnValue(method, 'op');
735
+ text += `${indent.get()}${helpers.buildErrCheck(indent, 'err', zeroResp)}\n`;
736
+ return text;
737
+ }
738
+ /**
739
+ * emits the call to the pipeline's Do() method on the internal client.
740
+ * if the call returns an error, the error is propagated to the caller.
741
+ *
742
+ * @param method the method that's making the call
743
+ * @param reqVarName the var name of the *policy.Request
744
+ * @param respVarName the var name of the *http.Response
745
+ * @param indent the indentation helper currently in scope
746
+ * @returns the call to Do() with an error check
747
+ */
748
+ function callPipelineDoWithErrCheck(method, reqVarName, respVarName, indent) {
749
+ let text = `${indent.get()}${respVarName}, err := client.internal.Pipeline().Do(${reqVarName})\n`;
750
+ const zeroResp = getZeroReturnValue(method, 'op');
751
+ text += `${indent.get()}${helpers.buildErrCheck(indent, 'err', zeroResp)}\n`;
592
752
  return text;
593
753
  }
594
754
  function genApiVersionDoc(apiVersions) {
@@ -614,7 +774,7 @@ function genRespErrorDoc(method) {
614
774
  function getClientReceiverDefinition(receiver) {
615
775
  return `(${receiver.name} ${receiver.byValue ? '' : '*'}${receiver.type.name})`;
616
776
  }
617
- function generateOperation(method, imports, options) {
777
+ function generateOperation(method, options, imports, indent) {
618
778
  const params = getAPIParametersSig(method, imports);
619
779
  const returns = generateReturnsInfo(method, 'op');
620
780
  let methodName = method.name;
@@ -644,63 +804,57 @@ function generateOperation(method, imports, options) {
644
804
  }
645
805
  }
646
806
  text += `func ${getClientReceiverDefinition(method.receiver)} ${methodName}(${params}) (${returns.join(', ')}) {\n`;
647
- const reqParams = helpers.getCreateRequestParameters(method);
648
807
  if (method.kind === 'pageableMethod') {
649
- text += '\treturn ';
650
- text += emitPagerDefinition(method, imports, options);
808
+ text += `${indent.get()}return `;
809
+ text += emitPagerDefinition(method, options, imports, indent);
651
810
  text += '}\n\n';
652
811
  return text;
653
812
  }
654
- text += '\tvar err error\n';
813
+ text += `${indent.get()}var err error\n`;
655
814
  let operationName = `"${method.receiver.type.name}.${fixUpMethodName(method)}"`;
656
815
  if (options.generateFakes && options.injectSpans) {
657
- text += `\tconst operationName = ${operationName}\n`;
816
+ text += `${indent.get()}const operationName = ${operationName}\n`;
658
817
  operationName = 'operationName';
659
818
  }
660
819
  if (options.generateFakes) {
661
- text += `\tctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, ${operationName})\n`;
820
+ text += `${indent.get()}ctx = context.WithValue(ctx, runtime.CtxAPINameKey{}, ${operationName})\n`;
662
821
  }
663
822
  if (options.injectSpans) {
664
- text += `\tctx, endSpan := runtime.StartSpan(ctx, ${operationName}, client.internal.Tracer(), nil)\n`;
665
- text += '\tdefer func() { endSpan(err) }()\n';
823
+ text += `${indent.get()}ctx, endSpan := runtime.StartSpan(ctx, ${operationName}, client.internal.Tracer(), nil)\n`;
824
+ text += `${indent.get()}defer func() { endSpan(err) }()\n`;
666
825
  }
667
826
  const zeroResp = getZeroReturnValue(method, 'op');
668
- text += `\treq, err := client.${method.naming.requestMethod}(${reqParams})\n`;
669
- text += '\tif err != nil {\n';
670
- text += `\t\treturn ${zeroResp}, err\n`;
671
- text += '\t}\n';
672
- text += '\thttpResp, err := client.internal.Pipeline().Do(req)\n';
673
- text += '\tif err != nil {\n';
674
- text += `\t\treturn ${zeroResp}, err\n`;
675
- text += '\t}\n';
676
- text += `\tif !runtime.HasStatusCode(httpResp, ${helpers.formatStatusCodes(method.httpStatusCodes)}) {\n`;
677
- text += '\t\terr = runtime.NewResponseError(httpResp)\n';
678
- text += `\t\treturn ${zeroResp}, err\n`;
679
- text += '\t}\n';
827
+ text += callCreateRequestWithErrCheck(method, 'req', indent);
828
+ text += callPipelineDoWithErrCheck(method, 'req', 'httpResp', indent);
829
+ text += `${indent.get()}if !runtime.HasStatusCode(httpResp, ${helpers.formatStatusCodes(method.httpStatusCodes)}) {\n`;
830
+ indent.push();
831
+ text += `${indent.get()}err = runtime.NewResponseError(httpResp)\n`;
832
+ text += `${indent.get()}return ${zeroResp}, err\n`;
833
+ text += `${indent.pop().get()}}\n`;
680
834
  // HAB with headers response is handled in protocol responder
681
835
  if (method.returns.result?.kind === 'headAsBooleanResult' && method.returns.headers.length === 0) {
682
- text += `\treturn ${method.returns.name}{${method.returns.result.fieldName}: httpResp.StatusCode >= 200 && httpResp.StatusCode < 300}, nil\n`;
836
+ text += `${indent.get()}return ${method.returns.name}{${method.returns.result.fieldName}: httpResp.StatusCode >= 200 && httpResp.StatusCode < 300}, nil\n`;
683
837
  }
684
838
  else {
685
839
  if (go.isLROMethod(method)) {
686
- text += '\treturn httpResp, nil\n';
840
+ text += `${indent.get()}return httpResp, nil\n`;
687
841
  }
688
842
  else if (needsResponseHandler(method)) {
689
843
  // also cheating here as at present the only param to the responder is an http.Response
690
- text += `\tresp, err := client.${method.naming.responseMethod}(httpResp)\n`;
691
- text += '\treturn resp, err\n';
844
+ text += `${indent.get()}resp, err := client.${method.naming.responseMethod}(httpResp)\n`;
845
+ text += `${indent.get()}return resp, err\n`;
692
846
  }
693
847
  else if (method.returns.result?.kind === 'binaryResult') {
694
- text += `\treturn ${method.returns.name}{${method.returns.result.fieldName}: httpResp.Body}, nil\n`;
848
+ text += `${indent.get()}return ${method.returns.name}{${method.returns.result.fieldName}: httpResp.Body}, nil\n`;
695
849
  }
696
850
  else {
697
- text += `\treturn ${method.returns.name}{}, nil\n`;
851
+ text += `${indent.get()}return ${method.returns.name}{}, nil\n`;
698
852
  }
699
853
  }
700
854
  text += '}\n\n';
701
855
  return text;
702
856
  }
703
- function createProtocolRequest(azureARM, method, imports) {
857
+ function createProtocolRequest(azureARM, method, imports, indent) {
704
858
  let name = method.name;
705
859
  if (method.kind !== 'nextPageMethod') {
706
860
  name = method.naming.requestMethod;
@@ -727,15 +881,15 @@ function createProtocolRequest(azureARM, method, imports) {
727
881
  else if (method.receiver.type.instance?.kind === 'templatedHost') {
728
882
  imports.add('strings');
729
883
  // we have a templated host
730
- text += `\thost := "${method.receiver.type.instance.path}"\n`;
884
+ text += `${indent.get()}host := "${method.receiver.type.instance.path}"\n`;
731
885
  // get all the host params on the client
732
886
  for (const hostParam of hostParams) {
733
- text += `\thost = strings.ReplaceAll(host, "{${hostParam.uriPathSegment}}", ${helpers.formatValue(`client.${hostParam.name}`, hostParam.type, imports)})\n`;
887
+ text += `${indent.get()}host = strings.ReplaceAll(host, "{${hostParam.uriPathSegment}}", ${helpers.formatValue(`client.${hostParam.name}`, hostParam.type, imports)})\n`;
734
888
  }
735
889
  // check for any method local host params
736
890
  for (const param of method.parameters) {
737
891
  if (param.location === 'method' && param.kind === 'uriParam') {
738
- text += `\thost = strings.ReplaceAll(host, "{${param.uriPathSegment}}", ${helpers.formatValue(helpers.getParamName(param), param.type, imports)})\n`;
892
+ text += `${indent.get()}host = strings.ReplaceAll(host, "{${param.uriPathSegment}}", ${helpers.formatValue(helpers.getParamName(param), param.type, imports)})\n`;
739
893
  }
740
894
  }
741
895
  hostParam = 'host';
@@ -758,7 +912,7 @@ function createProtocolRequest(azureARM, method, imports) {
758
912
  const pathContainsParms = pathStr.includes('{');
759
913
  if (hasPathParams || (!pathContainsParms && pathStr.length > 1)) {
760
914
  // there are path params, or the path doesn't contain tokens and is not "/" so emit it
761
- text += `\turlPath := "${method.httpPath}"\n`;
915
+ text += `${indent.get()}urlPath := "${method.httpPath}"\n`;
762
916
  hostParam = `runtime.JoinPaths(${hostParam}, urlPath)`;
763
917
  }
764
918
  // helper to build nil checks for param groups
@@ -775,7 +929,7 @@ function createProtocolRequest(azureARM, method, imports) {
775
929
  if (param.group.required) {
776
930
  optionalParamGroupCheck = '';
777
931
  }
778
- return `\tif ${optionalParamGroupCheck}${client}${paramGroupName}.${naming.capitalize(param.name)} != nil {\n`;
932
+ return `${indent.get()}if ${optionalParamGroupCheck}${client}${paramGroupName}.${naming.capitalize(param.name)} != nil {\n`;
779
933
  };
780
934
  if (hasPathParams) {
781
935
  // swagger defines path params, emit path and replace tokens
@@ -784,7 +938,13 @@ function createProtocolRequest(azureARM, method, imports) {
784
938
  for (const pp of methodParamGroups.pathParams) {
785
939
  let paramValue;
786
940
  let optionalPathSep = false;
787
- if (pp.style !== 'optional') {
941
+ if (pp.style === 'literal') {
942
+ // literals are always scalar types and require no empty checks
943
+ paramValue = helpers.formatParamValue(pp, imports, indent);
944
+ }
945
+ else if (pp.style === 'required' || pp.location === 'client') {
946
+ // NOTE: we include client params here since they behave
947
+ // like required params (i.e. not grouped).
788
948
  // emit check to ensure path param isn't an empty string
789
949
  if (pp.kind === 'pathScalarParam') {
790
950
  const choiceIsString = function (type) {
@@ -794,34 +954,43 @@ function createProtocolRequest(azureARM, method, imports) {
794
954
  if ((pp.type.kind === 'string' || choiceIsString(pp.type)) && !pp.omitEmptyStringCheck) {
795
955
  const paramName = helpers.getParamName(pp);
796
956
  imports.add('errors');
797
- text += `\tif ${paramName} == "" {\n`;
798
- text += `\t\treturn nil, errors.New("parameter ${paramName} cannot be empty")\n`;
799
- text += '\t}\n';
957
+ text += `${indent.get()}if ${paramName} == "" {\n`;
958
+ text += `${indent.push().get()}return nil, errors.New("parameter ${paramName} cannot be empty")\n`;
959
+ text += `${indent.pop().get()}}\n`;
800
960
  }
801
961
  }
802
- paramValue = helpers.formatParamValue(pp, imports);
962
+ paramValue = helpers.formatParamValue(pp, imports, indent);
803
963
  // for collection-based path params, we emit the empty check
804
964
  // after calling helpers.formatParamValue as that will have the
805
965
  // var name that contains the slice.
806
966
  if (pp.kind === 'pathCollectionParam') {
807
967
  const paramName = helpers.getParamName(pp);
808
968
  const joinedParamName = `${paramName}Param`;
809
- text += `\t${joinedParamName} := ${paramValue}\n`;
969
+ text += `${indent.get()}${joinedParamName} := ${paramValue}\n`;
810
970
  imports.add('errors');
811
- text += `\tif len(${joinedParamName}) == 0 {\n`;
812
- text += `\t\treturn nil, errors.New("parameter ${paramName} cannot be empty")\n`;
813
- text += '\t}\n';
971
+ text += `${indent.get()}if len(${joinedParamName}) == 0 {\n`;
972
+ text += `${indent.push().get()}return nil, errors.New("parameter ${paramName} cannot be empty")\n`;
973
+ text += `${indent.pop().get()}}\n`;
814
974
  paramValue = joinedParamName;
815
975
  }
816
976
  }
977
+ else if (go.isClientSideDefault(pp.style)) {
978
+ const defaultValue = naming.uncapitalize(pp.name) + 'Default';
979
+ text += `${indent.get()}${defaultValue} := ${helpers.formatLiteralValue(pp.style.defaultValue, true)}\n`;
980
+ text += emitParamGroupCheck(pp);
981
+ text += `${indent.push().get()}${defaultValue} = ${helpers.getParamName(pp)}\n`;
982
+ text += `${indent.pop().get()}}\n`;
983
+ paramValue = helpers.formatValue(defaultValue, pp.type, imports);
984
+ }
817
985
  else {
818
986
  // param isn't required, so emit a local var with
819
987
  // the correct default value, then populate it with
820
988
  // the optional value when set.
821
989
  paramValue = `optional${naming.capitalize(pp.name)}`;
822
- text += `\t${paramValue} := ""\n`;
990
+ text += `${indent.get()}${paramValue} := ""\n`;
823
991
  text += emitParamGroupCheck(pp);
824
- text += `\t${paramValue} = ${helpers.formatParamValue(pp, imports)}\n\t}\n`;
992
+ text += `${indent.push().get()}${paramValue} = ${helpers.formatParamValue(pp, imports, indent)}\n`;
993
+ text += `${indent.pop().get()}}\n`;
825
994
  // there are two cases for optional path params.
826
995
  // - /foo/bar/{optional}
827
996
  // - /foo/bar{/optional}
@@ -838,20 +1007,20 @@ function createProtocolRequest(azureARM, method, imports) {
838
1007
  return paramValue;
839
1008
  };
840
1009
  if (optionalPathSep) {
841
- text += `\tif len(${paramValue}) > 0 {\n`;
842
- text += `\t\t${paramValue} = "/"+${emitPathEscape()}\n`;
843
- text += '\t}\n';
1010
+ text += `${indent.get()}if len(${paramValue}) > 0 {\n`;
1011
+ text += `${indent.push().get()}${paramValue} = "/"+${emitPathEscape()}\n`;
1012
+ text += `${indent.pop().get()}}\n`;
844
1013
  }
845
1014
  else {
846
1015
  paramValue = emitPathEscape();
847
1016
  }
848
- text += `\turlPath = strings.ReplaceAll(urlPath, "{${pp.pathSegment}}", ${paramValue})\n`;
1017
+ text += `${indent.get()}urlPath = strings.ReplaceAll(urlPath, "{${pp.pathSegment}}", ${paramValue})\n`;
849
1018
  }
850
1019
  }
851
- text += `\treq, err := runtime.NewRequest(ctx, http.Method${naming.capitalize(method.httpMethod)}, ${hostParam})\n`;
852
- text += '\tif err != nil {\n';
853
- text += '\t\treturn nil, err\n';
854
- text += '\t}\n';
1020
+ text += `${indent.get()}req, err := runtime.NewRequest(ctx, http.Method${naming.capitalize(method.httpMethod)}, ${hostParam})\n`;
1021
+ text += `${indent.get()}if err != nil {\n`;
1022
+ text += `${indent.push().get()}return nil, err\n`;
1023
+ text += `${indent.pop().get()}}\n`;
855
1024
  // add query parameters
856
1025
  const encodedParams = methodParamGroups.encodedQueryParams;
857
1026
  const unencodedParams = methodParamGroups.unencodedQueryParams;
@@ -859,34 +1028,34 @@ function createProtocolRequest(azureARM, method, imports) {
859
1028
  let qpText = '';
860
1029
  if (qp.location === 'method' && go.isClientSideDefault(qp.style)) {
861
1030
  qpText = emitClientSideDefault(qp, qp.style, (name, val) => {
862
- return `\treqQP.Set(${name}, ${val})`;
863
- }, imports);
1031
+ return `${indent.get()}reqQP.Set(${name}, ${val})`;
1032
+ }, imports, indent);
864
1033
  }
865
1034
  else if (go.isRequiredParameter(qp.style) || go.isLiteralParameter(qp.style) || (qp.location === 'client' && go.isClientSideDefault(qp.style))) {
866
- qpText = `\t${setter}\n`;
1035
+ qpText = `${indent.get()}${setter}\n`;
867
1036
  }
868
1037
  else if (qp.location === 'client' && !qp.group) {
869
1038
  // global optional param
870
- qpText = `\tif client.${qp.name} != nil {\n`;
871
- qpText += `\t\t${setter}\n`;
872
- qpText += '\t}\n';
1039
+ qpText = `${indent.get()}if client.${qp.name} != nil {\n`;
1040
+ qpText += `${indent.push().get()}${setter}\n`;
1041
+ qpText += `${indent.pop().get()}}\n`;
873
1042
  }
874
1043
  else {
875
1044
  qpText = emitParamGroupCheck(qp);
876
- qpText += `\t\t${setter}\n`;
877
- qpText += '\t}\n';
1045
+ qpText += `${indent.push().get()}${setter}\n`;
1046
+ qpText += `${indent.pop().get()}}\n`;
878
1047
  }
879
1048
  return qpText;
880
1049
  };
881
1050
  // emit encoded params first
882
1051
  if (encodedParams.length > 0) {
883
- text += '\treqQP := req.Raw().URL.Query()\n';
1052
+ text += `${indent.get()}reqQP := req.Raw().URL.Query()\n`;
884
1053
  for (const qp of encodedParams.sort((a, b) => {
885
1054
  return helpers.sortAscending(a.queryParameter, b.queryParameter);
886
1055
  })) {
887
1056
  let setter;
888
1057
  if (qp.kind === 'queryCollectionParam' && qp.collectionFormat === 'multi') {
889
- setter = `\tfor _, qv := range ${helpers.getParamName(qp)} {\n`;
1058
+ setter = `for _, qv := range ${helpers.getParamName(qp)} {\n`;
890
1059
  // emit a type conversion for the qv based on the array's element type
891
1060
  let queryVal;
892
1061
  const arrayQP = qp.type;
@@ -908,63 +1077,63 @@ function createProtocolRequest(azureARM, method, imports) {
908
1077
  imports.add('fmt');
909
1078
  queryVal = 'fmt.Sprintf("%v", qv)';
910
1079
  }
911
- setter += `\t\treqQP.Add("${qp.queryParameter}", ${queryVal})\n`;
912
- setter += '\t}';
1080
+ setter += `${indent.push().get()}reqQP.Add("${qp.queryParameter}", ${queryVal})\n`;
1081
+ setter += `${indent.pop().get()}}`;
913
1082
  }
914
1083
  else {
915
1084
  // cannot initialize setter to this value as helpers.formatParamValue() can change imports
916
- setter = `reqQP.Set("${qp.queryParameter}", ${helpers.formatParamValue(qp, imports)})`;
1085
+ setter = `reqQP.Set("${qp.queryParameter}", ${helpers.formatParamValue(qp, imports, indent)})`;
917
1086
  }
918
1087
  text += emitQueryParam(qp, setter);
919
1088
  }
920
- text += '\treq.Raw().URL.RawQuery = reqQP.Encode()\n';
1089
+ text += `${indent.get()}req.Raw().URL.RawQuery = reqQP.Encode()\n`;
921
1090
  }
922
1091
  // tack on any unencoded params to the end
923
1092
  if (unencodedParams.length > 0) {
924
1093
  if (encodedParams.length > 0) {
925
- text += '\tunencodedParams := []string{req.Raw().URL.RawQuery}\n';
1094
+ text += `${indent.get()}unencodedParams := []string{req.Raw().URL.RawQuery}\n`;
926
1095
  }
927
1096
  else {
928
- text += '\tunencodedParams := []string{}\n';
1097
+ text += `${indent.get()}unencodedParams := []string{}\n`;
929
1098
  }
930
1099
  for (const qp of unencodedParams.sort((a, b) => {
931
1100
  return helpers.sortAscending(a.queryParameter, b.queryParameter);
932
1101
  })) {
933
1102
  let setter;
934
1103
  if (qp.kind === 'queryCollectionParam' && qp.collectionFormat === 'multi') {
935
- setter = `\tfor _, qv := range ${helpers.getParamName(qp)} {\n`;
936
- setter += `\t\tunencodedParams = append(unencodedParams, "${qp.queryParameter}="+qv)\n`;
937
- setter += '\t}';
1104
+ setter = `for _, qv := range ${helpers.getParamName(qp)} {\n`;
1105
+ setter += `${indent.push().get()}unencodedParams = append(unencodedParams, "${qp.queryParameter}="+qv)\n`;
1106
+ setter += `${indent.pop().get()}}`;
938
1107
  }
939
1108
  else {
940
- setter = `unencodedParams = append(unencodedParams, "${qp.queryParameter}="+${helpers.formatParamValue(qp, imports)})`;
1109
+ setter = `unencodedParams = append(unencodedParams, "${qp.queryParameter}="+${helpers.formatParamValue(qp, imports, indent)})`;
941
1110
  }
942
1111
  text += emitQueryParam(qp, setter);
943
1112
  }
944
1113
  imports.add('strings');
945
- text += '\treq.Raw().URL.RawQuery = strings.Join(unencodedParams, "&")\n';
1114
+ text += `${indent.get()}req.Raw().URL.RawQuery = strings.Join(unencodedParams, "&")\n`;
946
1115
  }
947
1116
  if (method.kind !== 'nextPageMethod' && method.returns.result?.kind === 'binaryResult') {
948
1117
  // skip auto-body downloading for binary stream responses
949
- text += '\truntime.SkipBodyDownload(req)\n';
1118
+ text += `${indent.get()}runtime.SkipBodyDownload(req)\n`;
950
1119
  }
951
1120
  // add specific request headers
952
- const emitHeaderSet = function (headerParam, prefix) {
1121
+ const emitHeaderSet = function (headerParam) {
953
1122
  if (headerParam.kind === 'headerMapParam') {
954
- let headerText = `${prefix}for k, v := range ${helpers.getParamName(headerParam)} {\n`;
955
- headerText += `${prefix}\tif v != nil {\n`;
956
- headerText += `${prefix}\t\treq.Raw().Header["${headerParam.headerName}"+k] = []string{*v}\n`;
957
- headerText += `${prefix}}\n`;
958
- headerText += `${prefix}}\n`;
1123
+ let headerText = `${indent.get()}for k, v := range ${helpers.getParamName(headerParam)} {\n`;
1124
+ headerText += `${indent.push().get()}if v != nil {\n`;
1125
+ headerText += `${indent.push().get()}req.Raw().Header["${headerParam.headerName}"+k] = []string{*v}\n`;
1126
+ headerText += `${indent.pop().get()}}\n`;
1127
+ headerText += `${indent.pop().get()}}\n`;
959
1128
  return headerText;
960
1129
  }
961
1130
  else if (headerParam.location === 'method' && go.isClientSideDefault(headerParam.style)) {
962
1131
  return emitClientSideDefault(headerParam, headerParam.style, (name, val) => {
963
- return `${prefix}req.Raw().Header[${name}] = []string{${val}}`;
964
- }, imports);
1132
+ return `${indent.get()}req.Raw().Header[${name}] = []string{${val}}`;
1133
+ }, imports, indent);
965
1134
  }
966
1135
  else {
967
- return `${prefix}req.Raw().Header["${headerParam.headerName}"] = []string{${helpers.formatParamValue(headerParam, imports)}}\n`;
1136
+ return `${indent.get()}req.Raw().Header["${headerParam.headerName}"] = []string{${helpers.formatParamValue(headerParam, imports, indent)}}\n`;
968
1137
  }
969
1138
  };
970
1139
  let contentType;
@@ -980,21 +1149,25 @@ function createProtocolRequest(azureARM, method, imports) {
980
1149
  // to handle cases where the body param is optional. we don't want to set
981
1150
  // the content-type if the body is nil.
982
1151
  // we do it like this as tsp specifies content-type while swagger does not.
983
- contentType = helpers.formatParamValue(param, imports);
1152
+ contentType = helpers.formatParamValue(param, imports, indent);
984
1153
  }
985
1154
  else if (go.isRequiredParameter(param.style) || go.isLiteralParameter(param.style) || go.isClientSideDefault(param.style)) {
986
- text += emitHeaderSet(param, '\t');
1155
+ text += emitHeaderSet(param);
987
1156
  }
988
1157
  else if (param.location === 'client' && !param.group) {
989
1158
  // global optional param
990
- text += `\tif client.${param.name} != nil {\n`;
991
- text += emitHeaderSet(param, '\t');
992
- text += '\t}\n';
1159
+ text += `${indent.get()}if client.${param.name} != nil {\n`;
1160
+ indent.push();
1161
+ text += emitHeaderSet(param);
1162
+ indent.pop();
1163
+ text += `${indent.get()}}\n`;
993
1164
  }
994
1165
  else {
995
1166
  text += emitParamGroupCheck(param);
996
- text += emitHeaderSet(param, '\t\t');
997
- text += '\t}\n';
1167
+ indent.push();
1168
+ text += emitHeaderSet(param);
1169
+ indent.pop();
1170
+ text += `${indent.get()}}\n`;
998
1171
  }
999
1172
  }
1000
1173
  // note that these are mutually exclusive
@@ -1003,10 +1176,13 @@ function createProtocolRequest(azureARM, method, imports) {
1003
1176
  const multipartBodyParams = methodParamGroups.multipartBodyParams;
1004
1177
  const partialBodyParams = methodParamGroups.partialBodyParams;
1005
1178
  const emitSetBodyWithErrCheck = function (setBodyParam, contentType) {
1006
- let content = `if err := ${setBodyParam}; err != nil {\n\treturn nil, err\n}\n;`;
1179
+ let content = '';
1007
1180
  if (contentType) {
1008
- content = `req.Raw().Header["Content-Type"] = []string{${contentType}}\n` + content;
1181
+ content += `${indent.get()}req.Raw().Header["Content-Type"] = []string{${contentType}}\n`;
1009
1182
  }
1183
+ content += `${indent.get()}if err := ${setBodyParam}; err != nil {\n`;
1184
+ content += `${indent.push().get()}return nil, err\n`;
1185
+ content += `${indent.pop().get()}}\n`;
1010
1186
  return content;
1011
1187
  };
1012
1188
  if (bodyParam) {
@@ -1020,7 +1196,8 @@ function createProtocolRequest(azureARM, method, imports) {
1020
1196
  else if (bodyParam.bodyFormat === 'XML' && bodyParam.type.kind === 'slice') {
1021
1197
  // for XML payloads, create a wrapper type if the payload is an array
1022
1198
  imports.add('encoding/xml');
1023
- text += '\ttype wrapper struct {\n';
1199
+ text += `${indent.get()}type wrapper struct {\n`;
1200
+ indent.push();
1024
1201
  let tagName;
1025
1202
  if (bodyParam.xml?.wrapper) {
1026
1203
  tagName = bodyParam.xml.wrapper;
@@ -1028,14 +1205,14 @@ function createProtocolRequest(azureARM, method, imports) {
1028
1205
  else {
1029
1206
  tagName = go.getTypeDeclaration(bodyParam.type, method.receiver.type.pkg);
1030
1207
  }
1031
- text += `\t\tXMLName xml.Name \`xml:"${tagName}"\`\n`;
1208
+ text += `${indent.get()}XMLName xml.Name \`xml:"${tagName}"\`\n`;
1032
1209
  const fieldName = naming.capitalize(bodyParam.name);
1033
1210
  let tag = go.getTypeDeclaration(bodyParam.type.elementType, method.receiver.type.pkg);
1034
1211
  if (bodyParam.type.elementType.kind === 'model' && bodyParam.type.elementType.xml?.name) {
1035
1212
  tag = bodyParam.type.elementType.xml.name;
1036
1213
  }
1037
- text += `\t\t${fieldName} *${go.getTypeDeclaration(bodyParam.type, method.receiver.type.pkg)} \`xml:"${tag}"\`\n`;
1038
- text += '\t}\n';
1214
+ text += `${indent.get()}${fieldName} *${go.getTypeDeclaration(bodyParam.type, method.receiver.type.pkg)} \`xml:"${tag}"\`\n`;
1215
+ text += `${indent.pop().get()}}\n`;
1039
1216
  let addr = '&';
1040
1217
  if (!go.isRequiredParameter(bodyParam.style) && !bodyParam.byValue) {
1041
1218
  addr = '';
@@ -1055,19 +1232,19 @@ function createProtocolRequest(azureARM, method, imports) {
1055
1232
  elementPtr = '';
1056
1233
  }
1057
1234
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime');
1058
- text += `\taux := make([]${elementPtr}datetime.${timeInfo?.format}, len(${body}))\n`;
1059
- text += `\tfor i := 0; i < len(${body}); i++ {\n`;
1060
- text += `\t\taux[i] = (${elementPtr}datetime.${timeInfo?.format})(${body}[i])\n`;
1061
- text += '\t}\n';
1235
+ text += `${indent.get()}aux := make([]${elementPtr}datetime.${timeInfo?.format}, len(${body}))\n`;
1236
+ text += `${indent.get()}for i := 0; i < len(${body}); i++ {\n`;
1237
+ text += `${indent.push().get()}aux[i] = (${elementPtr}datetime.${timeInfo?.format})(${body}[i])\n`;
1238
+ text += `${indent.pop().get()}}\n`;
1062
1239
  body = 'aux';
1063
1240
  }
1064
1241
  else if (isMapOfDateTime(bodyParam.type)) {
1065
1242
  let timeType = isMapOfDateTime(bodyParam.type);
1066
1243
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime');
1067
- text += `\taux := map[string]*datetime.${timeType}{}\n`;
1068
- text += `\tfor k, v := range ${body} {\n`;
1069
- text += `\t\taux[k] = (*datetime.${timeType})(v)\n`;
1070
- text += '\t}\n';
1244
+ text += `${indent.get()}aux := map[string]*datetime.${timeType}{}\n`;
1245
+ text += `${indent.get()}for k, v := range ${body} {\n`;
1246
+ text += `${indent.push().get()}aux[k] = (*datetime.${timeType})(v)\n`;
1247
+ text += `${indent.pop().get()}}\n`;
1071
1248
  body = 'aux';
1072
1249
  }
1073
1250
  let setBody = `runtime.MarshalAs${getMediaFormat(bodyParam.type, bodyParam.bodyFormat, `req, ${body}`)}`;
@@ -1077,134 +1254,152 @@ function createProtocolRequest(azureARM, method, imports) {
1077
1254
  setBody = `req.SetBody(streaming.NopCloser(bytes.NewReader(${body})), "application/${bodyParam.bodyFormat.toLowerCase()}")`;
1078
1255
  }
1079
1256
  if (go.isRequiredParameter(bodyParam.style) || go.isLiteralParameter(bodyParam.style)) {
1080
- text += `\t${emitSetBodyWithErrCheck(setBody, contentType)}`;
1081
- text += '\treturn req, nil\n';
1257
+ text += emitSetBodyWithErrCheck(setBody, contentType);
1258
+ text += `${indent.get()}return req, nil\n`;
1082
1259
  }
1083
1260
  else {
1084
1261
  text += emitParamGroupCheck(bodyParam);
1085
- text += `\t${emitSetBodyWithErrCheck(setBody, contentType)}`;
1086
- text += '\t\treturn req, nil\n';
1087
- text += '\t}\n';
1088
- text += '\treturn req, nil\n';
1262
+ indent.push();
1263
+ text += emitSetBodyWithErrCheck(setBody, contentType);
1264
+ text += `${indent.get()}return req, nil\n`;
1265
+ indent.pop();
1266
+ text += `${indent.get()}}\n`;
1267
+ text += `${indent.get()}return req, nil\n`;
1089
1268
  }
1090
1269
  }
1091
1270
  else if (bodyParam.bodyFormat === 'binary') {
1092
1271
  if (go.isRequiredParameter(bodyParam.style)) {
1093
- text += `\t${emitSetBodyWithErrCheck(`req.SetBody(${bodyParam.name}, ${bodyParam.contentType})`, contentType)}`;
1094
- text += '\treturn req, nil\n';
1272
+ text += emitSetBodyWithErrCheck(`req.SetBody(${bodyParam.name}, ${bodyParam.contentType})`, contentType);
1273
+ text += `${indent.get()}return req, nil\n`;
1095
1274
  }
1096
1275
  else {
1097
1276
  text += emitParamGroupCheck(bodyParam);
1098
- text += `\t${emitSetBodyWithErrCheck(`req.SetBody(${helpers.getParamName(bodyParam)}, ${bodyParam.contentType})`, contentType)}`;
1099
- text += '\treturn req, nil\n';
1100
- text += '\t}\n';
1101
- text += '\treturn req, nil\n';
1277
+ indent.push();
1278
+ text += emitSetBodyWithErrCheck(`req.SetBody(${helpers.getParamName(bodyParam)}, ${bodyParam.contentType})`, contentType);
1279
+ text += `${indent.get()}return req, nil\n`;
1280
+ indent.pop();
1281
+ text += `${indent.get()}}\n`;
1282
+ text += `${indent.get()}return req, nil\n`;
1102
1283
  }
1103
1284
  }
1104
1285
  else if (bodyParam.bodyFormat === 'Text') {
1105
1286
  imports.add('strings');
1106
1287
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming');
1107
1288
  if (go.isRequiredParameter(bodyParam.style)) {
1108
- text += `\tbody := streaming.NopCloser(strings.NewReader(${bodyParam.name}))\n`;
1109
- text += `\t${emitSetBodyWithErrCheck(`req.SetBody(body, ${bodyParam.contentType})`, contentType)}`;
1110
- text += '\treturn req, nil\n';
1289
+ text += `${indent.get()}body := streaming.NopCloser(strings.NewReader(${bodyParam.name}))\n`;
1290
+ text += emitSetBodyWithErrCheck(`req.SetBody(body, ${bodyParam.contentType})`, contentType);
1291
+ text += `${indent.get()}return req, nil\n`;
1111
1292
  }
1112
1293
  else {
1113
1294
  text += emitParamGroupCheck(bodyParam);
1114
- text += `\tbody := streaming.NopCloser(strings.NewReader(${helpers.getParamName(bodyParam)}))\n`;
1115
- text += `\t${emitSetBodyWithErrCheck(`req.SetBody(body, ${bodyParam.contentType})`, contentType)}`;
1116
- text += '\treturn req, nil\n';
1117
- text += '\t}\n';
1118
- text += '\treturn req, nil\n';
1295
+ indent.push();
1296
+ text += `${indent.get()}body := streaming.NopCloser(strings.NewReader(${helpers.getParamName(bodyParam)}))\n`;
1297
+ text += emitSetBodyWithErrCheck(`req.SetBody(body, ${bodyParam.contentType})`, contentType);
1298
+ text += `${indent.get()}return req, nil\n`;
1299
+ indent.pop();
1300
+ text += `${indent.get()}}\n`;
1301
+ text += `${indent.get()}return req, nil\n`;
1119
1302
  }
1120
1303
  }
1121
1304
  }
1122
1305
  else if (partialBodyParams.length > 0) {
1123
1306
  // partial body params are discrete params that are all fields within an internal struct.
1124
1307
  // define and instantiate an instance of the wire type, using the values from each param.
1125
- text += '\tbody := struct {\n';
1308
+ text += `${indent.get()}body := struct {\n`;
1309
+ indent.push();
1126
1310
  for (const partialBodyParam of partialBodyParams) {
1127
- text += `\t\t${naming.capitalize(partialBodyParam.serializedName)} ${helpers.star(partialBodyParam.byValue)}${go.getTypeDeclaration(partialBodyParam.type, method.receiver.type.pkg)} \`${partialBodyParam.format.toLowerCase()}:"${partialBodyParam.serializedName}"\`\n`;
1311
+ text += `${indent.get()}${naming.capitalize(partialBodyParam.serializedName)} ${helpers.star(partialBodyParam.byValue)}${go.getTypeDeclaration(partialBodyParam.type, method.receiver.type.pkg)} \`${partialBodyParam.format.toLowerCase()}:"${partialBodyParam.serializedName}"\`\n`;
1128
1312
  }
1129
- text += '\t}{\n';
1313
+ indent.pop();
1314
+ text += `${indent.get()}}{\n`;
1315
+ indent.push();
1130
1316
  // required params are emitted as initializers in the struct literal
1131
1317
  for (const partialBodyParam of partialBodyParams) {
1132
1318
  if (go.isRequiredParameter(partialBodyParam.style)) {
1133
- text += `\t\t${naming.capitalize(partialBodyParam.serializedName)}: ${naming.uncapitalize(partialBodyParam.name)},\n`;
1319
+ text += `${indent.get()}${naming.capitalize(partialBodyParam.serializedName)}: ${naming.uncapitalize(partialBodyParam.name)},\n`;
1134
1320
  }
1135
1321
  }
1136
- text += '\t}\n';
1322
+ indent.pop();
1323
+ text += `${indent.get()}}\n`;
1137
1324
  // now populate any optional params from the options type
1138
1325
  for (const partialBodyParam of partialBodyParams) {
1139
1326
  if (!go.isRequiredParameter(partialBodyParam.style)) {
1140
1327
  text += emitParamGroupCheck(partialBodyParam);
1141
- text += `\t\tbody.${naming.capitalize(partialBodyParam.serializedName)} = options.${naming.capitalize(partialBodyParam.name)}\n\t}\n`;
1328
+ text += `${indent.push().get()}body.${naming.capitalize(partialBodyParam.serializedName)} = options.${naming.capitalize(partialBodyParam.name)}\n`;
1329
+ text += `${indent.pop().get()}}\n`;
1142
1330
  }
1143
1331
  }
1144
1332
  // TODO: spread params are JSON only https://github.com/Azure/autorest.go/issues/1455
1145
- text += '\treq.Raw().Header["Content-Type"] = []string{"application/json"}\n';
1146
- text += '\tif err := runtime.MarshalAsJSON(req, body); err != nil {\n\t\treturn nil, err\n\t}\n';
1147
- text += '\treturn req, nil\n';
1333
+ text += `${indent.get()}req.Raw().Header["Content-Type"] = []string{"application/json"}\n`;
1334
+ text += `${indent.get()}if err := runtime.MarshalAsJSON(req, body); err != nil {\n`;
1335
+ text += `${indent.push().get()}return nil, err\n`;
1336
+ text += `${indent.pop().get()}}\n`;
1337
+ text += `${indent.get()}return req, nil\n`;
1148
1338
  }
1149
1339
  else if (multipartBodyParams.length > 0) {
1150
1340
  if (multipartBodyParams.length === 1 && multipartBodyParams[0].type.kind === 'model' && multipartBodyParams[0].type.annotations.multipartFormData) {
1151
- text += `\tformData, err := ${multipartBodyParams[0].name}.toMultipartFormData()\n`;
1152
- text += '\tif err != nil {\n\t\treturn nil, err\n\t}\n';
1341
+ text += `${indent.get()}formData, err := ${multipartBodyParams[0].name}.toMultipartFormData()\n`;
1342
+ text += `${indent.get()}if err != nil {\n`;
1343
+ text += `${indent.push().get()}return nil, err\n`;
1344
+ text += `${indent.pop().get()}}\n`;
1153
1345
  }
1154
1346
  else {
1155
- text += '\tformData := map[string]any{}\n';
1347
+ text += `${indent.get()}formData := map[string]any{}\n`;
1156
1348
  for (const param of multipartBodyParams) {
1157
1349
  const setter = `formData["${param.name}"] = ${helpers.getParamName(param)}`;
1158
1350
  if (go.isRequiredParameter(param.style)) {
1159
- text += `\t${setter}\n`;
1351
+ text += `${indent.get()}${setter}\n`;
1160
1352
  }
1161
1353
  else {
1162
1354
  text += emitParamGroupCheck(param);
1163
- text += `\t${setter}\n\t}\n`;
1355
+ text += `${indent.push().get()}${setter}\n`;
1356
+ text += `${indent.pop().get()}}\n`;
1164
1357
  }
1165
1358
  }
1166
1359
  }
1167
- text += '\tif err := runtime.SetMultipartFormData(req, formData); err != nil {\n\t\treturn nil, err\n\t}\n';
1168
- text += '\treturn req, nil\n';
1360
+ text += `${indent.get()}if err := runtime.SetMultipartFormData(req, formData); err != nil {\n`;
1361
+ text += `${indent.push().get()}return nil, err\n`;
1362
+ text += `${indent.pop().get()}}\n`;
1363
+ text += `${indent.get()}return req, nil\n`;
1169
1364
  }
1170
1365
  else if (formBodyParams.length > 0) {
1171
1366
  const emitFormData = function (param, setter) {
1172
1367
  let formDataText = '';
1173
1368
  if (go.isRequiredParameter(param.style)) {
1174
- formDataText = `\t${setter}\n`;
1369
+ formDataText = `${indent.get()}${setter}\n`;
1175
1370
  }
1176
1371
  else {
1177
1372
  formDataText = emitParamGroupCheck(param);
1178
- formDataText += `\t\t${setter}\n`;
1179
- formDataText += '\t}\n';
1373
+ formDataText += `${indent.push().get()}${setter}\n`;
1374
+ formDataText += `${indent.pop().get()}}\n`;
1180
1375
  }
1181
1376
  return formDataText;
1182
1377
  };
1183
1378
  imports.add('net/url');
1184
1379
  imports.add('strings');
1185
1380
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming');
1186
- text += '\tformData := url.Values{}\n';
1381
+ text += `${indent.get()}formData := url.Values{}\n`;
1187
1382
  // find all the form body params
1188
1383
  for (const param of formBodyParams) {
1189
- const setter = `formData.Set("${param.formDataName}", ${helpers.formatParamValue(param, imports)})`;
1384
+ const setter = `formData.Set("${param.formDataName}", ${helpers.formatParamValue(param, imports, indent)})`;
1190
1385
  text += emitFormData(param, setter);
1191
1386
  }
1192
- text += '\tbody := streaming.NopCloser(strings.NewReader(formData.Encode()))\n';
1193
- text += `\t${emitSetBodyWithErrCheck('req.SetBody(body, "application/x-www-form-urlencoded")')}`;
1194
- text += '\treturn req, nil\n';
1387
+ text += `${indent.get()}body := streaming.NopCloser(strings.NewReader(formData.Encode()))\n`;
1388
+ text += emitSetBodyWithErrCheck('req.SetBody(body, "application/x-www-form-urlencoded")');
1389
+ text += `${indent.get()}return req, nil\n`;
1195
1390
  }
1196
1391
  else {
1197
- text += '\treturn req, nil\n';
1392
+ text += `${indent.get()}return req, nil\n`;
1198
1393
  }
1199
1394
  text += '}\n\n';
1200
1395
  return text;
1201
1396
  }
1202
- function emitClientSideDefault(param, csd, setterFormat, imports) {
1397
+ function emitClientSideDefault(param, csd, setterFormat, imports, indent) {
1203
1398
  const defaultVar = naming.uncapitalize(param.name) + 'Default';
1204
- let text = `\t${defaultVar} := ${helpers.formatLiteralValue(csd.defaultValue, true)}\n`;
1205
- text += `\tif options != nil && options.${naming.capitalize(param.name)} != nil {\n`;
1206
- text += `\t\t${defaultVar} = *options.${naming.capitalize(param.name)}\n`;
1207
- text += '}\n';
1399
+ let text = `${indent.get()}${defaultVar} := ${helpers.formatLiteralValue(csd.defaultValue, true)}\n`;
1400
+ text += `${indent.get()}if options != nil && options.${naming.capitalize(param.name)} != nil {\n`;
1401
+ text += `${indent.push().get()}${defaultVar} = *options.${naming.capitalize(param.name)}\n`;
1402
+ text += `${indent.pop().get()}}\n`;
1208
1403
  let serializedName;
1209
1404
  switch (param.kind) {
1210
1405
  case 'headerCollectionParam':
@@ -1254,17 +1449,17 @@ function isArrayOfDateTimeForMarshalling(paramType) {
1254
1449
  function needsResponseHandler(method) {
1255
1450
  return helpers.hasSchemaResponse(method) || method.returns.headers.length > 0;
1256
1451
  }
1257
- function generateResponseUnmarshaller(method, type, format, unmarshalTarget, imports) {
1452
+ function generateResponseUnmarshaller(method, type, format, unmarshalTarget, imports, indent) {
1258
1453
  let unmarshallerText = '';
1259
1454
  const zeroValue = getZeroReturnValue(method, 'handler');
1260
1455
  if (type.kind === 'time') {
1261
1456
  // use the designated time type for unmarshalling
1262
1457
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime');
1263
- unmarshallerText += `\tvar aux *datetime.${type.format}\n`;
1264
- unmarshallerText += `\tif err := runtime.UnmarshalAs${format}(resp, &aux); err != nil {\n`;
1265
- unmarshallerText += `\t\treturn ${zeroValue}, err\n`;
1266
- unmarshallerText += '\t}\n';
1267
- unmarshallerText += `\tresult.${helpers.getResultFieldName(method)} = (*time.Time)(aux)\n`;
1458
+ unmarshallerText += `${indent.get()}var aux *datetime.${type.format}\n`;
1459
+ unmarshallerText += `${indent.get()}if err := runtime.UnmarshalAs${format}(resp, &aux); err != nil {\n`;
1460
+ unmarshallerText += `${indent.push().get()}return ${zeroValue}, err\n`;
1461
+ unmarshallerText += `${indent.pop().get()}}\n`;
1462
+ unmarshallerText += `${indent.get()}result.${helpers.getResultFieldName(method)} = (*time.Time)(aux)\n`;
1268
1463
  return unmarshallerText;
1269
1464
  }
1270
1465
  else if (isArrayOfDateTime(type)) {
@@ -1275,52 +1470,52 @@ function generateResponseUnmarshaller(method, type, format, unmarshalTarget, imp
1275
1470
  elementPtr = '';
1276
1471
  }
1277
1472
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime');
1278
- unmarshallerText += `\tvar aux []${elementPtr}datetime.${timeInfo?.format}\n`;
1279
- unmarshallerText += `\tif err := runtime.UnmarshalAs${format}(resp, &aux); err != nil {\n`;
1280
- unmarshallerText += `\t\treturn ${zeroValue}, err\n`;
1281
- unmarshallerText += '\t}\n';
1282
- unmarshallerText += `\tcp := make([]${elementPtr}time.Time, len(aux))\n`;
1283
- unmarshallerText += '\tfor i := 0; i < len(aux); i++ {\n';
1284
- unmarshallerText += `\t\tcp[i] = (${elementPtr}time.Time)(aux[i])\n`;
1285
- unmarshallerText += '\t}\n';
1286
- unmarshallerText += `\tresult.${helpers.getResultFieldName(method)} = cp\n`;
1473
+ unmarshallerText += `${indent.get()}var aux []${elementPtr}datetime.${timeInfo?.format}\n`;
1474
+ unmarshallerText += `${indent.get()}if err := runtime.UnmarshalAs${format}(resp, &aux); err != nil {\n`;
1475
+ unmarshallerText += `${indent.push().get()}return ${zeroValue}, err\n`;
1476
+ unmarshallerText += `${indent.pop().get()}}\n`;
1477
+ unmarshallerText += `${indent.get()}cp := make([]${elementPtr}time.Time, len(aux))\n`;
1478
+ unmarshallerText += `${indent.get()}for i := 0; i < len(aux); i++ {\n`;
1479
+ unmarshallerText += `${indent.push().get()}cp[i] = (${elementPtr}time.Time)(aux[i])\n`;
1480
+ unmarshallerText += `${indent.pop().get()}}\n`;
1481
+ unmarshallerText += `${indent.get()}result.${helpers.getResultFieldName(method)} = cp\n`;
1287
1482
  return unmarshallerText;
1288
1483
  }
1289
1484
  else if (isMapOfDateTime(type)) {
1290
1485
  let timeType = isMapOfDateTime(type);
1291
1486
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/datetime');
1292
- unmarshallerText += `\taux := map[string]*datetime.${timeType}{}\n`;
1293
- unmarshallerText += `\tif err := runtime.UnmarshalAs${format}(resp, &aux); err != nil {\n`;
1294
- unmarshallerText += `\t\treturn ${zeroValue}, err\n`;
1295
- unmarshallerText += '\t}\n';
1296
- unmarshallerText += '\tcp := map[string]*time.Time{}\n';
1297
- unmarshallerText += '\tfor k, v := range aux {\n';
1298
- unmarshallerText += '\t\tcp[k] = (*time.Time)(v)\n';
1299
- unmarshallerText += '\t}\n';
1300
- unmarshallerText += `\tresult.${helpers.getResultFieldName(method)} = cp\n`;
1487
+ unmarshallerText += `${indent.get()}aux := map[string]*datetime.${timeType}{}\n`;
1488
+ unmarshallerText += `${indent.get()}if err := runtime.UnmarshalAs${format}(resp, &aux); err != nil {\n`;
1489
+ unmarshallerText += `${indent.push().get()}return ${zeroValue}, err\n`;
1490
+ unmarshallerText += `${indent.pop().get()}}\n`;
1491
+ unmarshallerText += `${indent.get()}cp := map[string]*time.Time{}\n`;
1492
+ unmarshallerText += `${indent.get()}for k, v := range aux {\n`;
1493
+ unmarshallerText += `${indent.push().get()}cp[k] = (*time.Time)(v)\n`;
1494
+ unmarshallerText += `${indent.pop().get()}}\n`;
1495
+ unmarshallerText += `${indent.get()}result.${helpers.getResultFieldName(method)} = cp\n`;
1301
1496
  return unmarshallerText;
1302
1497
  }
1303
1498
  if (format === 'JSON' || format === 'XML') {
1304
1499
  if (type.kind === 'rawJSON') {
1305
- unmarshallerText += '\tbody, err := runtime.Payload(resp)\n';
1306
- unmarshallerText += '\tif err != nil {\n';
1307
- unmarshallerText += `\t\treturn ${zeroValue}, err\n`;
1308
- unmarshallerText += '\t}\n';
1309
- unmarshallerText += `\t${unmarshalTarget} = body\n`;
1500
+ unmarshallerText += `${indent.get()}body, err := runtime.Payload(resp)\n`;
1501
+ unmarshallerText += `${indent.get()}if err != nil {\n`;
1502
+ unmarshallerText += `${indent.push().get()}return ${zeroValue}, err\n`;
1503
+ unmarshallerText += `${indent.pop().get()}}\n`;
1504
+ unmarshallerText += `${indent.get()}${unmarshalTarget} = body\n`;
1310
1505
  }
1311
1506
  else {
1312
- unmarshallerText += `\tif err := runtime.UnmarshalAs${getMediaFormat(type, format, `resp, &${unmarshalTarget}`)}; err != nil {\n`;
1313
- unmarshallerText += `\t\treturn ${zeroValue}, err\n`;
1314
- unmarshallerText += '\t}\n';
1507
+ unmarshallerText += `${indent.get()}if err := runtime.UnmarshalAs${getMediaFormat(type, format, `resp, &${unmarshalTarget}`)}; err != nil {\n`;
1508
+ unmarshallerText += `${indent.push().get()}return ${zeroValue}, err\n`;
1509
+ unmarshallerText += `${indent.pop().get()}}\n`;
1315
1510
  }
1316
1511
  }
1317
1512
  else if (format === 'Text') {
1318
- unmarshallerText += '\tbody, err := runtime.Payload(resp)\n';
1319
- unmarshallerText += '\tif err != nil {\n';
1320
- unmarshallerText += `\t\treturn ${zeroValue}, err\n`;
1321
- unmarshallerText += '\t}\n';
1322
- unmarshallerText += '\ttxt := string(body)\n';
1323
- unmarshallerText += `\t${unmarshalTarget} = &txt\n`;
1513
+ unmarshallerText += `${indent.get()}body, err := runtime.Payload(resp)\n`;
1514
+ unmarshallerText += `${indent.get()}if err != nil {\n`;
1515
+ unmarshallerText += `${indent.push().get()}return ${zeroValue}, err\n`;
1516
+ unmarshallerText += `${indent.pop().get()}}\n`;
1517
+ unmarshallerText += `${indent.get()}txt := string(body)\n`;
1518
+ unmarshallerText += `${indent.get()}${unmarshalTarget} = &txt\n`;
1324
1519
  }
1325
1520
  else {
1326
1521
  // the remaining formats should have been handled elsewhere
@@ -1328,7 +1523,7 @@ function generateResponseUnmarshaller(method, type, format, unmarshalTarget, imp
1328
1523
  }
1329
1524
  return unmarshallerText;
1330
1525
  }
1331
- function createProtocolResponse(method, imports) {
1526
+ function createProtocolResponse(method, imports, indent) {
1332
1527
  if (!needsResponseHandler(method)) {
1333
1528
  return '';
1334
1529
  }
@@ -1337,70 +1532,70 @@ function createProtocolResponse(method, imports) {
1337
1532
  text += `func ${getClientReceiverDefinition(method.receiver)} ${name}(resp *http.Response) (${generateReturnsInfo(method, 'handler').join(', ')}) {\n`;
1338
1533
  const addHeaders = function (headers) {
1339
1534
  for (const header of headers) {
1340
- text += formatHeaderResponseValue(method, header, imports, 'result', `${method.returns.name}{}`);
1535
+ text += formatHeaderResponseValue(method, header, 'result', `${method.returns.name}{}`, imports, indent);
1341
1536
  }
1342
1537
  };
1343
1538
  const result = method.returns.result;
1344
1539
  if (!result) {
1345
1540
  // only headers
1346
- text += `\tresult := ${method.returns.name}{}\n`;
1541
+ text += `${indent.get()}result := ${method.returns.name}{}\n`;
1347
1542
  addHeaders(method.returns.headers);
1348
1543
  }
1349
1544
  else {
1350
1545
  switch (result.kind) {
1351
1546
  case 'anyResult':
1352
1547
  imports.add('fmt');
1353
- text += `\tresult := ${method.returns.name}{}\n`;
1548
+ text += `${indent.get()}result := ${method.returns.name}{}\n`;
1354
1549
  addHeaders(method.returns.headers);
1355
- text += '\tswitch resp.StatusCode {\n';
1550
+ text += `${indent.get()}switch resp.StatusCode {\n`;
1356
1551
  for (const statusCode of method.httpStatusCodes) {
1357
- text += `\tcase ${helpers.formatStatusCodes([statusCode])}:\n`;
1552
+ text += `${indent.get()}case ${helpers.formatStatusCodes([statusCode])}:\n`;
1358
1553
  const resultType = result.httpStatusCodeType[statusCode];
1359
1554
  if (!resultType) {
1360
1555
  // the operation contains a mix of schemas and non-schema responses
1361
1556
  continue;
1362
1557
  }
1363
- text += `\tvar val ${go.getTypeDeclaration(resultType, method.receiver.type.pkg)}\n`;
1364
- text += generateResponseUnmarshaller(method, resultType, result.format, 'val', imports);
1365
- text += '\tresult.Value = val\n';
1558
+ text += `${indent.get()}var val ${go.getTypeDeclaration(resultType, method.receiver.type.pkg)}\n`;
1559
+ text += generateResponseUnmarshaller(method, resultType, result.format, 'val', imports, indent);
1560
+ text += `${indent.get()}result.Value = val\n`;
1366
1561
  }
1367
- text += '\tdefault:\n';
1368
- text += `\t\treturn ${getZeroReturnValue(method, 'handler')}, fmt.Errorf("unhandled HTTP status code %d", resp.StatusCode)\n`;
1369
- text += '\t}\n';
1562
+ text += `${indent.get()}default:\n`;
1563
+ text += `${indent.push().get()}return ${getZeroReturnValue(method, 'handler')}, fmt.Errorf("unhandled HTTP status code %d", resp.StatusCode)\n`;
1564
+ text += `${indent.pop().get()}}\n`;
1370
1565
  break;
1371
1566
  case 'binaryResult':
1372
- text += `\tresult := ${method.returns.name}{${result.fieldName}: resp.Body}\n`;
1567
+ text += `${indent.get()}result := ${method.returns.name}{${result.fieldName}: resp.Body}\n`;
1373
1568
  addHeaders(method.returns.headers);
1374
1569
  break;
1375
1570
  case 'headAsBooleanResult':
1376
- text += `\tresult := ${method.returns.name}{${result.fieldName}: resp.StatusCode >= 200 && resp.StatusCode < 300}\n`;
1571
+ text += `${indent.get()}result := ${method.returns.name}{${result.fieldName}: resp.StatusCode >= 200 && resp.StatusCode < 300}\n`;
1377
1572
  addHeaders(method.returns.headers);
1378
1573
  break;
1379
1574
  case 'modelResult':
1380
- text += `\tresult := ${method.returns.name}{}\n`;
1575
+ text += `${indent.get()}result := ${method.returns.name}{}\n`;
1381
1576
  addHeaders(method.returns.headers);
1382
- text += generateResponseUnmarshaller(method, result.modelType, result.format, `result.${helpers.getResultFieldName(method)}`, imports);
1577
+ text += generateResponseUnmarshaller(method, result.modelType, result.format, `result.${helpers.getResultFieldName(method)}`, imports, indent);
1383
1578
  break;
1384
1579
  case 'monomorphicResult':
1385
- text += `\tresult := ${method.returns.name}{}\n`;
1580
+ text += `${indent.get()}result := ${method.returns.name}{}\n`;
1386
1581
  addHeaders(method.returns.headers);
1387
1582
  let target = `result.${helpers.getResultFieldName(method)}`;
1388
1583
  // when unmarshalling a wrapped XML array, unmarshal into the response envelope
1389
1584
  if (result.format === 'XML' && result.monomorphicType.kind === 'slice') {
1390
1585
  target = 'result';
1391
1586
  }
1392
- text += generateResponseUnmarshaller(method, result.monomorphicType, result.format, target, imports);
1587
+ text += generateResponseUnmarshaller(method, result.monomorphicType, result.format, target, imports, indent);
1393
1588
  break;
1394
1589
  case 'polymorphicResult':
1395
- text += `\tresult := ${method.returns.name}{}\n`;
1590
+ text += `${indent.get()}result := ${method.returns.name}{}\n`;
1396
1591
  addHeaders(method.returns.headers);
1397
- text += generateResponseUnmarshaller(method, result.interface, result.format, 'result', imports);
1592
+ text += generateResponseUnmarshaller(method, result.interface, result.format, 'result', imports, indent);
1398
1593
  break;
1399
1594
  default:
1400
1595
  result;
1401
1596
  }
1402
1597
  }
1403
- text += '\treturn result, nil\n';
1598
+ text += `${indent.get()}return result, nil\n`;
1404
1599
  text += '}\n\n';
1405
1600
  return text;
1406
1601
  }
@@ -1500,7 +1695,7 @@ function generateReturnsInfo(method, apiType) {
1500
1695
  }
1501
1696
  return [returnType, 'error'];
1502
1697
  }
1503
- function generateLROBeginMethod(method, imports, options) {
1698
+ function generateLROBeginMethod(method, options, imports, indent) {
1504
1699
  const params = getAPIParametersSig(method, imports);
1505
1700
  const returns = generateReturnsInfo(method, 'api');
1506
1701
  imports.add('github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime');
@@ -1510,7 +1705,7 @@ function generateLROBeginMethod(method, imports, options) {
1510
1705
  text += genRespErrorDoc(method);
1511
1706
  text += genApiVersionDoc(method.apiVersions);
1512
1707
  }
1513
- const zeroResp = getZeroReturnValue(method, 'api');
1708
+ const zeroResp = getZeroReturnValue(method, 'lro');
1514
1709
  const methodParams = helpers.getMethodParameters(method);
1515
1710
  for (const param of methodParams) {
1516
1711
  text += helpers.formatCommentAsBulletItem(param.name, param.docs);
@@ -1522,16 +1717,17 @@ function generateLROBeginMethod(method, imports, options) {
1522
1717
  // for paged LROs, we construct a pager and pass it to the LRO ctor.
1523
1718
  pollerTypeParam = `[*runtime.Pager${pollerTypeParam}]`;
1524
1719
  pollerType = '&pager';
1525
- text += '\tpager := ';
1526
- text += emitPagerDefinition(method, imports, options);
1720
+ text += `${indent.get()}pager := `;
1721
+ text += emitPagerDefinition(method, options, imports, indent);
1527
1722
  }
1528
- text += '\tif options == nil || options.ResumeToken == "" {\n';
1723
+ text += `${indent.get()}if options == nil || options.ResumeToken == "" {\n`;
1724
+ indent.push();
1529
1725
  // creating the poller from response branch
1530
1726
  const opName = method.naming.internalMethod;
1531
- text += `\t\tresp, err := client.${opName}(${helpers.getCreateRequestParameters(method)})\n`;
1532
- text += '\t\tif err != nil {\n';
1533
- text += `\t\t\treturn ${zeroResp}, err\n`;
1534
- text += '\t\t}\n';
1727
+ text += `${indent.get()}resp, err := client.${opName}(${helpers.getCreateRequestParameters(method)})\n`;
1728
+ text += `${indent.get()}if err != nil {\n`;
1729
+ text += `${indent.push().get()}return ${zeroResp}, err\n`;
1730
+ text += `${indent.pop().get()}}\n`;
1535
1731
  let finalStateVia = '';
1536
1732
  // LRO operation might have a special configuration set in x-ms-long-running-operation-options
1537
1733
  // which indicates a specific url to perform the final Get operation on
@@ -1553,7 +1749,7 @@ function generateLROBeginMethod(method, imports, options) {
1553
1749
  throw new CodegenError('InternalError', `unhandled final-state-via value ${finalStateVia}`);
1554
1750
  }
1555
1751
  }
1556
- text += '\t\tpoller, err := runtime.NewPoller';
1752
+ text += `${indent.get()}poller, err := runtime.NewPoller`;
1557
1753
  if (finalStateVia === '' && pollerType === 'nil' && !options.injectSpans) {
1558
1754
  // the generic type param is redundant when it's also specified in the
1559
1755
  // options struct so we only include it when there's no options.
@@ -1566,25 +1762,29 @@ function generateLROBeginMethod(method, imports, options) {
1566
1762
  }
1567
1763
  else {
1568
1764
  // at least one option
1765
+ indent.push();
1569
1766
  text += `&runtime.NewPollerOptions${pollerTypeParam}{\n`;
1570
1767
  if (finalStateVia !== '') {
1571
- text += `\t\t\tFinalStateVia: ${finalStateVia},\n`;
1768
+ text += `${indent.get()}FinalStateVia: ${finalStateVia},\n`;
1572
1769
  }
1573
1770
  if (method.operationLocationResultPath) {
1574
- text += `\t\t\tOperationLocationResultPath: "${method.operationLocationResultPath}",\n`;
1771
+ text += `${indent.get()}OperationLocationResultPath: "${method.operationLocationResultPath}",\n`;
1575
1772
  }
1576
1773
  if (pollerType !== 'nil') {
1577
- text += `\t\t\tResponse: ${pollerType},\n`;
1774
+ text += `${indent.get()}Response: ${pollerType},\n`;
1578
1775
  }
1579
1776
  if (options.injectSpans) {
1580
- text += '\t\t\tTracer: client.internal.Tracer(),\n';
1777
+ text += `${indent.get()}Tracer: client.internal.Tracer(),\n`;
1581
1778
  }
1582
- text += '\t\t})\n';
1779
+ indent.pop();
1780
+ text += `${indent.get()}})\n`;
1583
1781
  }
1584
- text += '\t\treturn poller, err\n';
1585
- text += '\t} else {\n';
1782
+ text += `${indent.get()}return poller, err\n`;
1783
+ indent.pop();
1784
+ text += `${indent.get()}} else {\n`;
1785
+ indent.push();
1586
1786
  // creating the poller from resume token branch
1587
- text += '\t\treturn runtime.NewPollerFromResumeToken';
1787
+ text += `${indent.get()}return runtime.NewPollerFromResumeToken`;
1588
1788
  if (pollerType === 'nil' && !options.injectSpans) {
1589
1789
  text += pollerTypeParam;
1590
1790
  }
@@ -1593,16 +1793,19 @@ function generateLROBeginMethod(method, imports, options) {
1593
1793
  text += 'nil)\n';
1594
1794
  }
1595
1795
  else {
1796
+ indent.push();
1596
1797
  text += `&runtime.NewPollerFromResumeTokenOptions${pollerTypeParam}{\n`;
1597
1798
  if (pollerType !== 'nil') {
1598
- text += `\t\t\tResponse: ${pollerType},\n`;
1799
+ text += `${indent.get()}Response: ${pollerType},\n`;
1599
1800
  }
1600
1801
  if (options.injectSpans) {
1601
- text += '\t\t\tTracer: client.internal.Tracer(),\n';
1802
+ text += `${indent.get()}Tracer: client.internal.Tracer(),\n`;
1602
1803
  }
1603
- text += '\t\t})\n';
1804
+ indent.pop();
1805
+ text += `${indent.get()}})\n`;
1604
1806
  }
1605
- text += '\t}\n';
1807
+ indent.pop();
1808
+ text += `${indent.get()}}\n`;
1606
1809
  text += '}\n\n';
1607
1810
  return text;
1608
1811
  }