@azure-tools/typespec-rust 0.36.0 → 0.37.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 (76) hide show
  1. package/dist/src/codegen/clients.d.ts +4 -4
  2. package/dist/src/codegen/clients.d.ts.map +1 -1
  3. package/dist/src/codegen/clients.js +167 -67
  4. package/dist/src/codegen/clients.js.map +1 -1
  5. package/dist/src/codegen/codeGenerator.d.ts +6 -0
  6. package/dist/src/codegen/codeGenerator.d.ts.map +1 -1
  7. package/dist/src/codegen/codeGenerator.js +112 -32
  8. package/dist/src/codegen/codeGenerator.js.map +1 -1
  9. package/dist/src/codegen/context.d.ts +10 -0
  10. package/dist/src/codegen/context.d.ts.map +1 -1
  11. package/dist/src/codegen/context.js +57 -15
  12. package/dist/src/codegen/context.js.map +1 -1
  13. package/dist/src/codegen/docTests.d.ts +1 -2
  14. package/dist/src/codegen/docTests.d.ts.map +1 -1
  15. package/dist/src/codegen/docTests.js +13 -3
  16. package/dist/src/codegen/docTests.js.map +1 -1
  17. package/dist/src/codegen/enums.d.ts +4 -4
  18. package/dist/src/codegen/enums.d.ts.map +1 -1
  19. package/dist/src/codegen/enums.js +21 -21
  20. package/dist/src/codegen/enums.js.map +1 -1
  21. package/dist/src/codegen/headerTraits.d.ts +2 -2
  22. package/dist/src/codegen/headerTraits.d.ts.map +1 -1
  23. package/dist/src/codegen/headerTraits.js +17 -9
  24. package/dist/src/codegen/headerTraits.js.map +1 -1
  25. package/dist/src/codegen/helpers.d.ts +12 -3
  26. package/dist/src/codegen/helpers.d.ts.map +1 -1
  27. package/dist/src/codegen/helpers.js +19 -13
  28. package/dist/src/codegen/helpers.js.map +1 -1
  29. package/dist/src/codegen/lib.d.ts +3 -1
  30. package/dist/src/codegen/lib.d.ts.map +1 -1
  31. package/dist/src/codegen/lib.js +5 -1
  32. package/dist/src/codegen/lib.js.map +1 -1
  33. package/dist/src/codegen/mod.d.ts +9 -2
  34. package/dist/src/codegen/mod.d.ts.map +1 -1
  35. package/dist/src/codegen/mod.js +25 -9
  36. package/dist/src/codegen/mod.js.map +1 -1
  37. package/dist/src/codegen/models.d.ts +4 -4
  38. package/dist/src/codegen/models.d.ts.map +1 -1
  39. package/dist/src/codegen/models.js +76 -30
  40. package/dist/src/codegen/models.js.map +1 -1
  41. package/dist/src/codegen/unions.d.ts +4 -4
  42. package/dist/src/codegen/unions.d.ts.map +1 -1
  43. package/dist/src/codegen/unions.js +71 -45
  44. package/dist/src/codegen/unions.js.map +1 -1
  45. package/dist/src/codegen/use.d.ts +4 -2
  46. package/dist/src/codegen/use.d.ts.map +1 -1
  47. package/dist/src/codegen/use.js +22 -26
  48. package/dist/src/codegen/use.js.map +1 -1
  49. package/dist/src/codemodel/client.d.ts +30 -15
  50. package/dist/src/codemodel/client.d.ts.map +1 -1
  51. package/dist/src/codemodel/client.js +11 -7
  52. package/dist/src/codemodel/client.js.map +1 -1
  53. package/dist/src/codemodel/crate.d.ts +42 -12
  54. package/dist/src/codemodel/crate.d.ts.map +1 -1
  55. package/dist/src/codemodel/crate.js +21 -46
  56. package/dist/src/codemodel/crate.js.map +1 -1
  57. package/dist/src/codemodel/types.d.ts +60 -34
  58. package/dist/src/codemodel/types.d.ts.map +1 -1
  59. package/dist/src/codemodel/types.js +26 -10
  60. package/dist/src/codemodel/types.js.map +1 -1
  61. package/dist/src/emitter.d.ts.map +1 -1
  62. package/dist/src/emitter.js +40 -12
  63. package/dist/src/emitter.js.map +1 -1
  64. package/dist/src/lib.d.ts +2 -0
  65. package/dist/src/lib.d.ts.map +1 -1
  66. package/dist/src/lib.js +6 -0
  67. package/dist/src/lib.js.map +1 -1
  68. package/dist/src/tcgcadapter/adapter.d.ts +75 -13
  69. package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
  70. package/dist/src/tcgcadapter/adapter.js +655 -173
  71. package/dist/src/tcgcadapter/adapter.js.map +1 -1
  72. package/dist/src/utils/utils.d.ts +7 -4
  73. package/dist/src/utils/utils.d.ts.map +1 -1
  74. package/dist/src/utils/utils.js +25 -23
  75. package/dist/src/utils/utils.js.map +1 -1
  76. package/package.json +17 -17
@@ -5,13 +5,13 @@ export interface ClientModules {
5
5
  /** the list of client modules */
6
6
  modules: Array<helpers.Module>;
7
7
  /** the client method options module */
8
- options: helpers.Module;
8
+ options?: helpers.Module;
9
9
  }
10
10
  /**
11
11
  * emits the content for all client files
12
12
  *
13
- * @param crate the crate for which to emit clients
14
- * @returns client content or undefined if the crate contains no clients
13
+ * @param module the module for which to emit clients
14
+ * @returns client content or undefined if the module contains no clients
15
15
  */
16
- export declare function emitClients(crate: rust.Crate): ClientModules | undefined;
16
+ export declare function emitClients(module: rust.ModuleContainer): ClientModules | undefined;
17
17
  //# sourceMappingURL=clients.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAG9C,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/B,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,aAAa,GAAG,SAAS,CA+RxE"}
1
+ {"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAG9C,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/B,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,GAAG,aAAa,GAAG,SAAS,CA6TnF"}
@@ -13,11 +13,11 @@ import * as utils from '../utils/utils.js';
13
13
  /**
14
14
  * emits the content for all client files
15
15
  *
16
- * @param crate the crate for which to emit clients
17
- * @returns client content or undefined if the crate contains no clients
16
+ * @param module the module for which to emit clients
17
+ * @returns client content or undefined if the module contains no clients
18
18
  */
19
- export function emitClients(crate) {
20
- if (crate.clients.length === 0) {
19
+ export function emitClients(module) {
20
+ if (module.clients.length === 0) {
21
21
  return undefined;
22
22
  }
23
23
  // returns true if the client options type needs to explicitly implement Default
@@ -34,8 +34,8 @@ export function emitClients(crate) {
34
34
  };
35
35
  const clientModules = new Array();
36
36
  // emit the clients, one file per client
37
- for (const client of crate.clients) {
38
- const use = new Use('clients');
37
+ for (const client of module.clients) {
38
+ const use = new Use(module, 'clients');
39
39
  const indent = new helpers.indentation();
40
40
  let body = helpers.formatDocComment(client.docs);
41
41
  use.add('azure_core', 'tracing');
@@ -163,6 +163,7 @@ export function emitClients(crate) {
163
163
  body += `${indent.get()}pub fn endpoint(&self) -> &Url {\n`;
164
164
  body += `${indent.push().get()}&self.${client.endpoint.name}\n`;
165
165
  body += `${indent.pop().get()}}\n\n`;
166
+ const crate = helpers.getCrate(module);
166
167
  for (let i = 0; i < client.methods.length; ++i) {
167
168
  const method = client.methods[i];
168
169
  const returnType = helpers.getTypeDeclaration(method.returns);
@@ -231,6 +232,24 @@ export function emitClients(crate) {
231
232
  }
232
233
  }
233
234
  body += '}\n\n'; // end client impl
235
+ // emit pub(crate) const declarations for fields with default value constants
236
+ if (client.constructable) {
237
+ const isSuppressed = client.constructable.suppressed === 'yes';
238
+ for (const field of client.constructable.options.type.fields) {
239
+ if (field.defaultValueConstant) {
240
+ if (isSuppressed) {
241
+ // When the client options type is suppressed, avoid emitting an intra-doc link
242
+ // to a type that does not exist in the generated code.
243
+ body += `/// Default value for \`${client.constructable.options.type.name}::${field.name}\`.\n`;
244
+ }
245
+ else {
246
+ body += `/// Default value for [\`${client.constructable.options.type.name}::${field.name}\`].\n`;
247
+ }
248
+ body += `#[allow(dead_code)]\n`;
249
+ body += `pub(crate) const ${field.defaultValueConstant.name}: &str = "${field.defaultValueConstant.value}";\n\n`;
250
+ }
251
+ }
252
+ }
234
253
  // only implement Default when there's more than one field.
235
254
  // for the single-case field we just derive Default.
236
255
  if (client.constructable && clientOptionsImplDefault(client.constructable)) {
@@ -256,7 +275,16 @@ export function emitClients(crate) {
256
275
  // add using for method_options as required
257
276
  for (const method of client.methods) {
258
277
  if (method.kind !== 'clientaccessor') {
259
- use.add('crate::generated::models', method.options.type.name);
278
+ // client method options types are always in the same module as their client method
279
+ use.add(`${utils.buildImportPath(client.module, client.module)}::models`, method.options.type.type.name);
280
+ // add imports for parameter group types
281
+ const seenGroups = new Set();
282
+ for (const param of method.params) {
283
+ if (param.group && !seenGroups.has(param.group.type.name)) {
284
+ seenGroups.add(param.group.type.name);
285
+ use.add(`${utils.buildImportPath(client.module, client.module)}::models`, param.group.type.name);
286
+ }
287
+ }
260
288
  }
261
289
  }
262
290
  let content = helpers.contentPreamble();
@@ -271,64 +299,102 @@ export function emitClients(crate) {
271
299
  }
272
300
  return {
273
301
  modules: clientModules,
274
- options: getMethodOptions(crate),
302
+ options: getMethodOptions(module),
275
303
  };
276
304
  }
277
- function getMethodOptions(crate) {
278
- const use = new Use('modelsOther');
305
+ function getMethodOptions(module) {
306
+ const use = new Use(module, 'modelsOther');
279
307
  const indent = new helpers.indentation();
280
308
  const visTracker = new helpers.VisibilityTracker();
281
- let body = '';
282
- for (const client of crate.clients) {
283
- for (let i = 0; i < client.methods.length; ++i) {
284
- const method = client.methods[i];
309
+ // collect all struct blocks so they can be sorted by name
310
+ const structBlocks = [];
311
+ for (const client of module.clients) {
312
+ for (const method of client.methods) {
285
313
  if (method.kind === 'clientaccessor') {
286
314
  continue;
287
315
  }
288
- body += helpers.formatDocComment(method.options.type.docs);
316
+ // method options struct
317
+ let block = '';
318
+ const optionsStruct = method.options.type.type;
319
+ block += helpers.formatDocComment(optionsStruct.docs);
289
320
  use.add('azure_core::fmt', 'SafeDebug');
290
- body += '#[derive(Clone, Default, SafeDebug)]\n';
291
- body += `${helpers.emitVisibility(method.options.type.visibility)}struct ${helpers.getTypeDeclaration(method.options.type)} {\n`;
292
- visTracker.update(method.options.type.visibility);
293
- for (let i = 0; i < method.options.type.fields.length; ++i) {
294
- const field = method.options.type.fields[i];
321
+ block += '#[derive(Clone, Default, SafeDebug)]\n';
322
+ block += `${helpers.emitVisibility(optionsStruct.visibility)}struct ${helpers.getTypeDeclaration(optionsStruct)} {\n`;
323
+ visTracker.update(optionsStruct.visibility);
324
+ for (let i = 0; i < optionsStruct.fields.length; ++i) {
325
+ const field = optionsStruct.fields[i];
295
326
  use.addForType(field.type);
296
327
  const fieldDocs = helpers.formatDocComment(field.docs);
297
328
  if (fieldDocs.length > 0) {
298
- body += `${indent.get()}${fieldDocs}`;
329
+ block += `${indent.get()}${fieldDocs}`;
299
330
  }
300
- body += `${indent.get()}${helpers.emitVisibility(method.visibility)}${field.name}: ${helpers.getTypeDeclaration(field.type)},\n`;
301
- if (i + 1 < method.options.type.fields.length) {
302
- body += '\n';
331
+ block += `${indent.get()}${helpers.emitVisibility(method.visibility)}${field.name}: ${helpers.getTypeDeclaration(field.type)},\n`;
332
+ if (i + 1 < optionsStruct.fields.length) {
333
+ block += '\n';
303
334
  }
304
335
  }
305
- body += '}\n\n'; // end options
336
+ block += '}\n';
306
337
  if (method.kind === 'pageable' || method.kind === 'lro') {
307
- body += `impl ${helpers.getTypeDeclaration(method.options.type, 'anonymous')} {\n`;
308
- const wrappedTypeName = helpers.wrapInBackTicks(helpers.getTypeDeclaration(method.options.type, 'omit'));
309
- body += `${indent.get()}/// Transforms this [${wrappedTypeName}] into a new ${wrappedTypeName} that owns the underlying data, cloning it if necessary.\n`;
310
- body += `${indent.get()}pub fn into_owned(self) -> ${method.options.type.name}<'static> {\n`;
311
- body += `${indent.push().get()}${method.options.type.name} {\n`;
338
+ block += '\n';
339
+ block += `impl ${helpers.getTypeDeclaration(optionsStruct, 'anonymous')} {\n`;
340
+ const wrappedTypeName = helpers.wrapInBackTicks(helpers.getTypeDeclaration(optionsStruct, 'omit'));
341
+ block += `${indent.get()}/// Transforms this [${wrappedTypeName}] into a new ${wrappedTypeName} that owns the underlying data, cloning it if necessary.\n`;
342
+ block += `${indent.get()}pub fn into_owned(self) -> ${optionsStruct.name}<'static> {\n`;
343
+ block += `${indent.push().get()}${optionsStruct.name} {\n`;
312
344
  indent.push();
313
- for (const field of method.options.type.fields) {
345
+ for (const field of optionsStruct.fields) {
314
346
  if (field.type.kind === 'clientMethodOptions' || field.type.kind === 'pagerOptions' || field.type.kind === 'pollerOptions') {
315
- body += `${indent.get()}${field.name}: ${field.type.name} {\n`;
316
- body += `${indent.push().get()}context: self.${field.name}.context.into_owned(),\n`;
317
- body += `${indent.get()}..self.${field.name}\n`;
318
- body += `${indent.pop().get()}},\n`;
347
+ block += `${indent.get()}${field.name}: ${field.type.name} {\n`;
348
+ block += `${indent.push().get()}context: self.${field.name}.context.into_owned(),\n`;
349
+ block += `${indent.get()}..self.${field.name}\n`;
350
+ block += `${indent.pop().get()}},\n`;
319
351
  continue;
320
352
  }
321
- body += `${indent.get()}${field.name}: self.${field.name},\n`;
353
+ block += `${indent.get()}${field.name}: self.${field.name},\n`;
322
354
  }
323
- body += `${indent.pop().get()}}\n`;
324
- body += `${indent.pop().get()}}\n`;
325
- body += '}\n';
355
+ block += `${indent.pop().get()}}\n`;
356
+ block += `${indent.pop().get()}}\n`;
357
+ block += '}\n';
326
358
  }
327
- if (i + 1 < client.methods.length) {
328
- body += '\n';
359
+ structBlocks.push({ name: optionsStruct.name, body: block });
360
+ // parameter group structs
361
+ const seenGroups = new Set();
362
+ for (const param of method.params) {
363
+ if (param.group) {
364
+ seenGroups.add(param.group);
365
+ }
366
+ }
367
+ for (const group of seenGroups) {
368
+ const groupParams = method.params.filter(p => p.group === group);
369
+ let groupBlock = '';
370
+ groupBlock += helpers.formatDocComment(group.type.docs);
371
+ use.add('azure_core::fmt', 'SafeDebug');
372
+ groupBlock += '#[derive(Clone, SafeDebug)]\n';
373
+ groupBlock += `${helpers.emitVisibility(group.type.visibility)}struct ${group.type.name}${group.type.lifetime ? `<${group.type.lifetime.name}>` : ''} {\n`;
374
+ visTracker.update(group.type.visibility);
375
+ for (let i = 0; i < groupParams.length; i++) {
376
+ const field = groupParams[i];
377
+ use.addForType(field.type);
378
+ const fieldDocs = helpers.formatDocComment(field.docs);
379
+ if (fieldDocs.length > 0) {
380
+ if (i > 0) {
381
+ groupBlock += '\n';
382
+ }
383
+ groupBlock += `${indent.get()}${fieldDocs}`;
384
+ }
385
+ groupBlock += `${indent.get()}${helpers.emitVisibility(group.type.visibility)}${field.name}: ${helpers.getTypeDeclaration(field.type)},\n`;
386
+ }
387
+ groupBlock += '}\n';
388
+ structBlocks.push({ name: group.type.name, body: groupBlock });
329
389
  }
330
390
  }
331
391
  }
392
+ structBlocks.sort((a, b) => helpers.sortAscending(a.name, b.name));
393
+ const body = structBlocks.map((b) => b.body).join('\n');
394
+ if (body === '') {
395
+ // client is top-level only, no methods just accessors
396
+ return undefined;
397
+ }
332
398
  let content = helpers.contentPreamble();
333
399
  content += use.text();
334
400
  content += body;
@@ -351,7 +417,17 @@ function getParamsBlockDocComment(indent, callable) {
351
417
  return `* ${helpers.wrapInBackTicks(paramName)} - `;
352
418
  };
353
419
  let paramsContent = '';
420
+ const documentedGroups = new Set();
354
421
  for (const param of callable.params) {
422
+ if ('group' in param && param.group) {
423
+ // required parameter group appears as a single param in the method sig
424
+ const group = param.group;
425
+ if (!documentedGroups.has(group.name)) {
426
+ documentedGroups.add(group.name);
427
+ paramsContent += helpers.formatDocComment(group.docs, false, formatParamBullet(group.name), indent);
428
+ }
429
+ continue;
430
+ }
355
431
  let optional = false;
356
432
  if ('optional' in param) {
357
433
  optional = param.optional;
@@ -426,7 +502,17 @@ function getMethodParamsCountAndSig(method, use) {
426
502
  }
427
503
  }
428
504
  else {
505
+ const emittedGroups = new Set();
429
506
  for (const param of method.params) {
507
+ if (param.group) {
508
+ if (!emittedGroups.has(param.group.name)) {
509
+ emittedGroups.add(param.group.name);
510
+ // required parameter group appears as a single struct parameter in the method signature
511
+ paramsSig.push(`${param.group.name}: ${helpers.getTypeDeclaration(param.group.type, 'anonymous')}`);
512
+ ++count;
513
+ }
514
+ continue;
515
+ }
430
516
  const paramType = helpers.unwrapType(param.type);
431
517
  if (paramType.kind === 'literal') {
432
518
  // literal params are embedded directly in the code (e.g. accept header param)
@@ -444,7 +530,7 @@ function getMethodParamsCountAndSig(method, use) {
444
530
  ++count;
445
531
  }
446
532
  }
447
- paramsSig.push(`options: ${helpers.getTypeDeclaration(method.options, 'anonymous')}`);
533
+ paramsSig.push(`${method.options.name}: ${helpers.getTypeDeclaration(method.options.type, 'anonymous')}`);
448
534
  ++count;
449
535
  }
450
536
  return { count: count, sig: paramsSig.join(', ') };
@@ -453,11 +539,11 @@ function getMethodParamsCountAndSig(method, use) {
453
539
  * returns documentation for header trait access if the method has response headers.
454
540
  *
455
541
  * @param indent the current indentation level
456
- * @param crate the crate to which method belongs
542
+ * @param module the module to which method belongs
457
543
  * @param method the method for which to generate header trait documentation
458
544
  * @returns the header trait documentation or empty string if not applicable
459
545
  */
460
- function getHeaderTraitDocComment(indent, crate, method) {
546
+ function getHeaderTraitDocComment(indent, module, method) {
461
547
  if (!method.responseHeaders) {
462
548
  return '';
463
549
  }
@@ -479,15 +565,15 @@ function getHeaderTraitDocComment(indent, crate, method) {
479
565
  headerDocs += `${indent.get()}/// The returned [${helpers.wrapInBackTicks(returnType)}](azure_core::http::${returnType}) implements the [${helpers.wrapInBackTicks(traitName)}] trait, which provides\n`;
480
566
  headerDocs += `${indent.get()}/// access to response headers. For example:\n`;
481
567
  headerDocs += `${indent.get()}///\n`;
482
- headerDocs += emitHeaderTraitDocExample(crate.name, method.responseHeaders, indent);
568
+ headerDocs += emitHeaderTraitDocExample(method.responseHeaders, indent);
483
569
  headerDocs += `${indent.get()}///\n`;
484
570
  headerDocs += `${indent.get()}/// ### Available headers\n`;
485
571
  // List all available headers
486
572
  for (const header of method.responseHeaders.headers) {
487
- headerDocs += `${indent.get()}/// * [${helpers.wrapInBackTicks(header.name)}()](crate::generated::models::${traitName}::${header.name}) - ${header.header}\n`;
573
+ headerDocs += `${indent.get()}/// * [${helpers.wrapInBackTicks(header.name)}()](${utils.buildImportPath(module, module)}::models::${traitName}::${header.name}) - ${header.header}\n`;
488
574
  }
489
575
  headerDocs += `${indent.get()}///\n`;
490
- headerDocs += `${indent.get()}/// [${helpers.wrapInBackTicks(traitName)}]: crate::generated::models::${traitName}\n`;
576
+ headerDocs += `${indent.get()}/// [${helpers.wrapInBackTicks(traitName)}]: ${utils.buildImportPath(module, module)}::models::${traitName}\n`;
491
577
  return headerDocs;
492
578
  }
493
579
  /**
@@ -683,8 +769,8 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
683
769
  throw new CodegenError('InternalError', 'too many HTTP path chunks');
684
770
  }
685
771
  let body = '';
686
- // if path is just "/" no need to set it again, we're already there
687
- if (pathChunks[0] !== '/') {
772
+ // if path is just "/" or empty, no need to set it again, we're already there
773
+ if (pathChunks[0] !== '/' && pathChunks[0] !== '') {
688
774
  use.add('azure_core::http', 'UrlExt');
689
775
  let path = `"${pathChunks[0]}"`;
690
776
  if (paramGroups.path.length === 0) {
@@ -704,8 +790,9 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
704
790
  let wrapSortedVec = (s) => s;
705
791
  let paramExpression;
706
792
  if (pathParam.kind === 'pathHashMap') {
793
+ const pathParamRef = qualifiedParamName(pathParam);
707
794
  wrapSortedVec = (s) => `${indent.get()}{`
708
- + `${indent.push().get()}let mut ${pathParam.name}_vec = ${pathParam.name}.iter().collect::<Vec<_>>();\n`
795
+ + `${indent.push().get()}let mut ${pathParam.name}_vec = ${pathParamRef}.iter().collect::<Vec<_>>();\n`
709
796
  + `${indent.get()}${pathParam.name}_vec.sort_by_key(|p| p.0);\n`
710
797
  + `${s}`
711
798
  + `${indent.pop().get()}}`;
@@ -738,16 +825,17 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
738
825
  }
739
826
  }
740
827
  else if (pathParam.kind === 'pathCollection') {
741
- paramExpression = `&${pathParam.name}.join(",")`;
828
+ const pathParamRef = qualifiedParamName(pathParam);
829
+ paramExpression = `&${pathParamRef}.join(",")`;
742
830
  switch (pathParam.style) {
743
831
  case 'path':
744
- paramExpression = `&format!("/{}", ${pathParam.name}.join("${pathParam.explode ? '/' : ','}"))`;
832
+ paramExpression = `&format!("/{}", ${pathParamRef}.join("${pathParam.explode ? '/' : ','}"))`;
745
833
  break;
746
834
  case 'label':
747
- paramExpression = `&format!(".{}", ${pathParam.name}.join("${pathParam.explode ? '.' : ','}"))`;
835
+ paramExpression = `&format!(".{}", ${pathParamRef}.join("${pathParam.explode ? '.' : ','}"))`;
748
836
  break;
749
837
  case 'matrix':
750
- paramExpression = `&format!(";${pathParam.name}={}", ${pathParam.name}.join(`
838
+ paramExpression = `&format!(";${pathParam.name}={}", ${pathParamRef}.join(`
751
839
  + `"${pathParam.explode ? `;${pathParam.name}=` : ','}"))`;
752
840
  break;
753
841
  }
@@ -822,8 +910,9 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
822
910
  for (const queryParam of paramGroups.query) {
823
911
  if (queryParam.kind === 'queryCollection' && queryParam.format === 'multi') {
824
912
  body += getParamValueHelper(indent, queryParam, () => {
913
+ const queryParamRef = qualifiedParamName(queryParam);
825
914
  const valueVar = queryParam.name[0];
826
- let text = `${indent.get()}for ${valueVar} in ${queryParam.name}.iter() {\n`;
915
+ let text = `${indent.get()}for ${valueVar} in ${queryParamRef}.iter() {\n`;
827
916
  // if queryParam is a &[&str] then we'll need to deref the iterator
828
917
  const deref = utils.asTypeOf(queryParam.type, 'str', 'ref', 'slice', 'ref') ? '*' : '';
829
918
  text += `${indent.push().get()}query_builder.append_pair("${queryParam.key}", ${deref}${getHeaderPathQueryParamValue(use, queryParam, !queryParam.optional, false, valueVar)});\n`;
@@ -833,8 +922,9 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
833
922
  }
834
923
  else if (queryParam.kind === 'queryHashMap') {
835
924
  body += getParamValueHelper(indent, queryParam, () => {
925
+ const queryParamRef = qualifiedParamName(queryParam);
836
926
  let text = `${indent.get()}{\n`;
837
- text += `${indent.push().get()}let mut ${queryParam.name}_vec = ${queryParam.name}.iter().collect::<Vec<_>>();\n`;
927
+ text += `${indent.push().get()}let mut ${queryParam.name}_vec = ${queryParamRef}.iter().collect::<Vec<_>>();\n`;
838
928
  text += `${indent.get()}${queryParam.name}_vec.sort_by_key(|p| p.0);\n`;
839
929
  if (queryParam.explode) {
840
930
  text += `${indent.get()}for (k, v) in ${queryParam.name}_vec.iter() {\n`;
@@ -903,7 +993,8 @@ function applyHeaderParams(indent, use, method, paramGroups, inClosure, requestV
903
993
  }
904
994
  body += getParamValueHelper(indent, headerParam, () => {
905
995
  if (headerParam.kind === 'headerHashMap') {
906
- let setter = `for (k, v) in ${headerParam.name} {\n`;
996
+ const headerParamRef = qualifiedParamName(headerParam);
997
+ let setter = `for (k, v) in ${headerParamRef} {\n`;
907
998
  setter += `${indent.push().get()}${requestVarName}.insert_header(format!("${headerParam.header}-{k}"), v);\n`;
908
999
  setter += `${indent.pop().get()}}\n`;
909
1000
  return setter;
@@ -961,15 +1052,15 @@ function constructRequest(indent, use, method, paramGroups, inClosure, urlVarNam
961
1052
  const requestContentType = paramGroups.partialBody[0].type;
962
1053
  use.addForType(requestContentType);
963
1054
  if (inClosure) {
964
- body += `${indent.get()}let body: Result<${helpers.getTypeDeclaration(requestContentType)}> = ${requestContentType.content.type.name} {\n`;
1055
+ body += `${indent.get()}let body: Result<${helpers.getTypeDeclaration(requestContentType)}> = ${requestContentType.content.name} {\n`;
965
1056
  }
966
1057
  else {
967
- body += `${indent.get()}let body: ${helpers.getTypeDeclaration(requestContentType)} = ${requestContentType.content.type.name} {\n`;
1058
+ body += `${indent.get()}let body: ${helpers.getTypeDeclaration(requestContentType)} = ${requestContentType.content.name} {\n`;
968
1059
  }
969
1060
  indent.push();
970
1061
  for (const partialBodyParam of paramGroups.partialBody) {
971
- if (partialBodyParam.type.content.type !== requestContentType.content.type) {
972
- throw new CodegenError('InternalError', `spread param ${partialBodyParam.name} has conflicting model type ${partialBodyParam.type.content.type.name}, expected model type ${requestContentType.content.type.name}`);
1062
+ if (partialBodyParam.type.content !== requestContentType.content) {
1063
+ throw new CodegenError('InternalError', `spread param ${partialBodyParam.name} has conflicting model type ${partialBodyParam.type.content.name}, expected model type ${requestContentType.content.name}`);
973
1064
  }
974
1065
  if (partialBodyParam.optional) {
975
1066
  body += `${indent.get()}${partialBodyParam.name}: options.${partialBodyParam.name}${inClosure ? '.clone()' : ''},\n`;
@@ -979,7 +1070,7 @@ function constructRequest(indent, use, method, paramGroups, inClosure, urlVarNam
979
1070
  if (inClosure) {
980
1071
  initializer = initializer + '.clone()';
981
1072
  }
982
- if (requestContentType.content.type.visibility === 'pub') {
1073
+ if (requestContentType.content.visibility === 'pub') {
983
1074
  // spread param maps to a non-internal model, so it must be wrapped in Some()
984
1075
  initializer = `Some(${initializer})`;
985
1076
  }
@@ -1062,8 +1153,9 @@ function emitEmptyPathParamCheck(indent, param) {
1062
1153
  // no length to check so bail
1063
1154
  return '';
1064
1155
  }
1156
+ const paramRef = qualifiedParamName(param);
1065
1157
  return helpers.buildIfBlock(indent, {
1066
- condition: `${param.name}${toString}.is_empty()`,
1158
+ condition: `${paramRef}${toString}.is_empty()`,
1067
1159
  body: (indent) => `${indent.get()}return Err(azure_core::Error::with_message(azure_core::error::ErrorKind::Other, "parameter ${param.name} cannot be empty"));\n`,
1068
1160
  });
1069
1161
  }
@@ -1647,6 +1739,9 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
1647
1739
  else if (overrideParamName) {
1648
1740
  paramName = overrideParamName;
1649
1741
  }
1742
+ else if (param.group) {
1743
+ paramName = qualifiedParamName(param);
1744
+ }
1650
1745
  const encodeBytes = function (type, param) {
1651
1746
  const encoding = helpers.getBytesEncodingMethod(type.encoding, 'encode', use);
1652
1747
  if (param) {
@@ -1675,6 +1770,7 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
1675
1770
  // contains the result from calculating if the
1676
1771
  // param requires borrowing.
1677
1772
  let mustBorrow = !helpers.isQueryParameter(param);
1773
+ const isGrouped = !!param.group;
1678
1774
  const paramType = helpers.unwrapType(param.type);
1679
1775
  // we want multi to hit the else case so the necessary conversions etc can happen
1680
1776
  if ((param.kind === 'headerCollection' || param.kind === 'queryCollection') && param.format !== 'multi') {
@@ -1701,8 +1797,8 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
1701
1797
  switch (paramType.kind) {
1702
1798
  case 'String':
1703
1799
  paramValue = paramName;
1704
- // if the param is on the client, then we must borrow
1705
- mustBorrow = param.location === 'client' && fromSelf;
1800
+ // if the param is on the client or in a group struct, then we must borrow
1801
+ mustBorrow = isGrouped || (param.location === 'client' && fromSelf);
1706
1802
  break;
1707
1803
  case 'str':
1708
1804
  paramValue = paramName;
@@ -1746,8 +1842,8 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
1746
1842
  case 'headerHashMap':
1747
1843
  case 'headerScalar':
1748
1844
  // for non-copyable params (e.g. String), we need to borrow them if they're on the
1749
- // client or we're in a closure and the param is required (header params are always owned)
1750
- mustBorrow = nonCopyableType(param.type) && (param.location === 'client' || (!fromSelf && !param.optional));
1845
+ // client, in a group struct, or we're in a closure and the param is required (header params are always owned)
1846
+ mustBorrow = nonCopyableType(param.type) && (isGrouped || param.location === 'client' || (!fromSelf && !param.optional));
1751
1847
  break;
1752
1848
  }
1753
1849
  return `${mustBorrow && !neverBorrow ? '&' : ''}${paramValue}`;
@@ -1823,4 +1919,8 @@ function isEnumString(type) {
1823
1919
  const unwrapped = helpers.unwrapType(type);
1824
1920
  return unwrapped.kind === 'enum' && unwrapped.type === 'String';
1825
1921
  }
1922
+ /** returns the qualified name for a param, prefixing with the group name when the param belongs to a parameter group */
1923
+ function qualifiedParamName(param) {
1924
+ return param.group ? `${param.group.name}.${param.name}` : param.name;
1925
+ }
1826
1926
  //# sourceMappingURL=clients.js.map