@azure-tools/typespec-rust 0.38.0 → 0.39.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.
@@ -222,7 +222,6 @@ export class Adapter {
222
222
  };
223
223
  terminalErrorModelNames = getTerminalErrorModelNames(this.ctx.sdkPackage.clients);
224
224
  }
225
- const processedTypes = new Set();
226
225
  for (const model of this.ctx.sdkPackage.models) {
227
226
  if ((model.usage & (tcgc.UsageFlags.Input | tcgc.UsageFlags.Output | tcgc.UsageFlags.Spread | tcgc.UsageFlags.Exception)) === 0) {
228
227
  // skip types without input and output usage. this will include core
@@ -236,15 +235,7 @@ export class Adapter {
236
235
  continue;
237
236
  }
238
237
  needsCoreAndSerde = true;
239
- // TODO: workaround for https://github.com/Azure/typespec-azure/issues/3614
240
- if (processedTypes.has(model.name)) {
241
- continue;
242
- }
243
- else {
244
- processedTypes.add(model.name);
245
- }
246
- // END workaround
247
- if (model.discriminatedSubtypes) {
238
+ if (isPolymorphicRoot(model)) {
248
239
  const rustUnion = this.getDiscriminatedUnion(model);
249
240
  this.adaptNamespace(model.namespace).unions.push(rustUnion);
250
241
  // we don't want to add the base type to the array
@@ -426,7 +417,7 @@ export class Adapter {
426
417
  // aggregate the properties from the provided type and its parent types
427
418
  const allProps = new Array();
428
419
  for (const prop of model.properties) {
429
- if (prop.discriminator && !model.discriminatedSubtypes) {
420
+ if (prop.discriminator && !isPolymorphicRoot(model)) {
430
421
  rustModel.flags |= rust.ModelFlags.PolymorphicSubtype;
431
422
  }
432
423
  allProps.push(prop);
@@ -492,7 +483,7 @@ export class Adapter {
492
483
  * @returns a Rust union
493
484
  */
494
485
  getDiscriminatedUnion(src) {
495
- var _a, _b, _c, _d, _e, _f, _g, _h;
486
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
496
487
  if (src.name.length === 0) {
497
488
  throw new AdapterError('InternalError', 'unnamed union', (_a = src.__raw) === null || _a === void 0 ? void 0 : _a.node);
498
489
  }
@@ -504,7 +495,7 @@ export class Adapter {
504
495
  }
505
496
  switch (src.kind) {
506
497
  case 'model': {
507
- if (!src.discriminatedSubtypes) {
498
+ if (!isPolymorphicRoot(src)) {
508
499
  // we should have verified this earlier.
509
500
  // having this check means the compiler won't bark
510
501
  // at us when accessing src.discriminatedSubtypes
@@ -553,9 +544,10 @@ export class Adapter {
553
544
  }
554
545
  rustUnion.unionKind = new rust.DiscriminatedUnionBase(baseModel);
555
546
  }
556
- for (const subType of Object.values(src.discriminatedSubtypes)) {
547
+ // we need to handle the case where src is a root with no child types
548
+ for (const subType of Object.values((_e = src.discriminatedSubtypes) !== null && _e !== void 0 ? _e : {})) {
557
549
  if (!subType.discriminatorValue) {
558
- throw new AdapterError('InternalError', `model ${subType.name} has no discriminator value`, (_e = subType.__raw) === null || _e === void 0 ? void 0 : _e.node);
550
+ throw new AdapterError('InternalError', `model ${subType.name} has no discriminator value`, (_f = subType.__raw) === null || _f === void 0 ? void 0 : _f.node);
559
551
  }
560
552
  const unionMemberType = subType.discriminatedSubtypes ? this.getDiscriminatedUnion(subType) : this.getModel(subType);
561
553
  const rustUnionMember = new rust.DiscriminatedUnionMember(unionMemberType, subType.discriminatorValue);
@@ -568,7 +560,7 @@ export class Adapter {
568
560
  // we should have verified this earlier.
569
561
  // having this check means the compiler won't bark
570
562
  // at us when accessing src.discriminatedOptions
571
- throw new AdapterError('InternalError', 'getDiscriminatedUnion called for non-discriminated union', (_f = src.__raw) === null || _f === void 0 ? void 0 : _f.node);
563
+ throw new AdapterError('InternalError', 'getDiscriminatedUnion called for non-discriminated union', (_g = src.__raw) === null || _g === void 0 ? void 0 : _g.node);
572
564
  }
573
565
  rustUnion = new rust.DiscriminatedUnion(unionName, adaptAccessFlags(src.access), src.discriminatedOptions.discriminatorPropertyName, this.adaptNamespace(src.namespace));
574
566
  if (src.discriminatedOptions.envelopePropertyName) {
@@ -591,12 +583,12 @@ export class Adapter {
591
583
  // END WORKAROUND
592
584
  for (const unionMember of src.variantTypes) {
593
585
  if (unionMember.kind !== 'model') {
594
- throw new AdapterError('UnsupportedTsp', `non-model union member kind ${unionMember.kind}`, (_g = unionMember.__raw) === null || _g === void 0 ? void 0 : _g.node);
586
+ throw new AdapterError('UnsupportedTsp', `non-model union member kind ${unionMember.kind}`, (_h = unionMember.__raw) === null || _h === void 0 ? void 0 : _h.node);
595
587
  }
596
588
  // TODO: use unionMember.discriminatorValue
597
589
  const discriminatorValue = discriminatorValues.get(unionMember.name);
598
590
  if (!discriminatorValue) {
599
- throw new AdapterError('InternalError', `didn't find discriminant value for type ${unionMember.name}`, (_h = unionMember.__raw) === null || _h === void 0 ? void 0 : _h.node);
591
+ throw new AdapterError('InternalError', `didn't find discriminant value for type ${unionMember.name}`, (_j = unionMember.__raw) === null || _j === void 0 ? void 0 : _j.node);
600
592
  }
601
593
  const unionMemberType = this.getModel(unionMember);
602
594
  const rustUnionMember = new rust.DiscriminatedUnionMember(unionMemberType, discriminatorValue);
@@ -854,6 +846,9 @@ export class Adapter {
854
846
  }
855
847
  modelField.docs.description += `Operational visibility: ${visibilityStr}`;
856
848
  }
849
+ if (property.visibility && property.visibility.length === 1 && property.visibility[0] === http.Visibility.Read) {
850
+ modelField.flags |= rust.ModelFieldFlags.ReadOnly;
851
+ }
857
852
  // if this is a literal, add a doc comment explaining its behavior
858
853
  const unwrappedType = utils.unwrapOption(fieldType);
859
854
  if (unwrappedType.kind === 'enumValue' || unwrappedType.kind === 'literal') {
@@ -960,6 +955,11 @@ export class Adapter {
960
955
  }
961
956
  case 'constant':
962
957
  return this.getLiteral(type);
958
+ // Per https://typespec.io/docs/language-basics/built-in-types/:
959
+ // "Parent type for all numeric types" - decimal fits the best.
960
+ // No Azure spec, no Spector test uses this type, we only need it here for spector/tcgc/alternate-type test,
961
+ // but only until https://github.com/Azure/typespec-azure/issues/3965 is fixed.
962
+ case 'numeric':
963
963
  case 'decimal':
964
964
  case 'decimal128': {
965
965
  const keyName = 'decimal' + (type.encode ? `-${type.encode}` : '');
@@ -1008,7 +1008,7 @@ export class Adapter {
1008
1008
  if (type.external) {
1009
1009
  return this.getExternalType(type.external);
1010
1010
  }
1011
- else if (type.discriminatedSubtypes) {
1011
+ else if (isPolymorphicRoot(type)) {
1012
1012
  return this.getDiscriminatedUnion(type);
1013
1013
  }
1014
1014
  else if (tcgc.isAzureCoreModel(type)) {
@@ -2441,7 +2441,7 @@ export class Adapter {
2441
2441
  * @returns a Rust method parameter
2442
2442
  */
2443
2443
  adaptMethodParameter(opParam, methodParam, lifetime) {
2444
- var _a, _b, _c, _d, _e, _f, _g, _h;
2444
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
2445
2445
  /**
2446
2446
  * used to create keys for this.clientMethodParams
2447
2447
  * @param param the param for which to create a key
@@ -2570,6 +2570,12 @@ export class Adapter {
2570
2570
  throw new AdapterError('InternalError', `unexpected kind ${paramType.kind} for scalar path ${opParam.serializedName}`, (_g = opParam.__raw) === null || _g === void 0 ? void 0 : _g.node);
2571
2571
  }
2572
2572
  adaptedParam = new rust.PathScalarParameter(paramName, opParam.serializedName, paramLoc, paramOptional, paramType, opParam.allowReserved, style);
2573
+ const allowEmpty = ((_h = opParam.decorators.find(d => d.name === 'Azure.ClientGenerator.Core.@clientOption'
2574
+ && d.arguments['name'] === 'allowEmpty'
2575
+ && d.arguments['scope'] === 'rust')) === null || _h === void 0 ? void 0 : _h.arguments['value']) === true;
2576
+ if (allowEmpty) {
2577
+ adaptedParam.minLength = 0;
2578
+ }
2573
2579
  }
2574
2580
  }
2575
2581
  break;
@@ -2593,7 +2599,7 @@ export class Adapter {
2593
2599
  case 'model':
2594
2600
  case 'slice':
2595
2601
  case 'str':
2596
- throw new AdapterError('InternalError', `unexpected kind ${paramType.kind} for scalar query ${opParam.serializedName}`, (_h = opParam.__raw) === null || _h === void 0 ? void 0 : _h.node);
2602
+ throw new AdapterError('InternalError', `unexpected kind ${paramType.kind} for scalar query ${opParam.serializedName}`, (_j = opParam.__raw) === null || _j === void 0 ? void 0 : _j.node);
2597
2603
  }
2598
2604
  // TODO: hard-coded encoding setting, https://github.com/Azure/typespec-azure/issues/1314
2599
2605
  adaptedParam = new rust.QueryScalarParameter(paramName, opParam.serializedName, paramLoc, paramOptional, paramType, true);
@@ -3009,4 +3015,23 @@ function typeToRefType(type) {
3009
3015
  throw new AdapterError('InternalError', `cannot convert ${type.kind} to a ref type`);
3010
3016
  }
3011
3017
  }
3018
+ /**
3019
+ * returns true if model is a polymorphic root type.
3020
+ *
3021
+ * @param model the model to inspect
3022
+ * @returns true if the model is a polymorphic root
3023
+ */
3024
+ function isPolymorphicRoot(model) {
3025
+ if (model.discriminatedSubtypes) {
3026
+ // when there are sub-types we know for sure it's a polymorphic root
3027
+ return true;
3028
+ }
3029
+ else if (model.discriminatorProperty && !model.discriminatorValue) {
3030
+ // we can land here if it's a root but has no child types
3031
+ return true;
3032
+ }
3033
+ else {
3034
+ return false;
3035
+ }
3036
+ }
3012
3037
  //# sourceMappingURL=adapter.js.map