@typespec/compiler 0.60.0-dev.1 → 0.60.0-dev.11

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 (53) hide show
  1. package/dist/generated-defs/TypeSpec.d.ts +44 -0
  2. package/dist/generated-defs/TypeSpec.d.ts.map +1 -1
  3. package/dist/generated-defs/TypeSpec.ts-test.js +2 -45
  4. package/dist/generated-defs/TypeSpec.ts-test.js.map +1 -1
  5. package/dist/manifest.js +2 -2
  6. package/dist/src/config/config-loader.js +7 -7
  7. package/dist/src/config/config-loader.js.map +1 -1
  8. package/dist/src/core/binder.d.ts.map +1 -1
  9. package/dist/src/core/binder.js +58 -47
  10. package/dist/src/core/binder.js.map +1 -1
  11. package/dist/src/core/checker.d.ts.map +1 -1
  12. package/dist/src/core/checker.js +27 -578
  13. package/dist/src/core/checker.js.map +1 -1
  14. package/dist/src/core/diagnostics.d.ts.map +1 -1
  15. package/dist/src/core/diagnostics.js +2 -0
  16. package/dist/src/core/diagnostics.js.map +1 -1
  17. package/dist/src/core/linter.d.ts.map +1 -1
  18. package/dist/src/core/linter.js +1 -0
  19. package/dist/src/core/linter.js.map +1 -1
  20. package/dist/src/core/logger/console-sink.d.ts.map +1 -1
  21. package/dist/src/core/logger/console-sink.js +9 -1
  22. package/dist/src/core/logger/console-sink.js.map +1 -1
  23. package/dist/src/core/logger/support-hyperlinks.d.ts +5 -0
  24. package/dist/src/core/logger/support-hyperlinks.d.ts.map +1 -0
  25. package/dist/src/core/logger/support-hyperlinks.js +76 -0
  26. package/dist/src/core/logger/support-hyperlinks.js.map +1 -0
  27. package/dist/src/core/numeric.js +2 -0
  28. package/dist/src/core/numeric.js.map +1 -1
  29. package/dist/src/core/schema-validator.d.ts.map +1 -1
  30. package/dist/src/core/schema-validator.js +8 -18
  31. package/dist/src/core/schema-validator.js.map +1 -1
  32. package/dist/src/core/type-relation-checker.d.ts +32 -0
  33. package/dist/src/core/type-relation-checker.d.ts.map +1 -0
  34. package/dist/src/core/type-relation-checker.js +580 -0
  35. package/dist/src/core/type-relation-checker.js.map +1 -0
  36. package/dist/src/core/types.d.ts +20 -0
  37. package/dist/src/core/types.d.ts.map +1 -1
  38. package/dist/src/core/types.js.map +1 -1
  39. package/dist/src/index.js +2 -0
  40. package/dist/src/index.js.map +1 -1
  41. package/dist/src/lib/examples.d.ts.map +1 -1
  42. package/dist/src/lib/examples.js +2 -1
  43. package/dist/src/lib/examples.js.map +1 -1
  44. package/dist/src/lib/tsp-index.d.ts +3 -0
  45. package/dist/src/lib/tsp-index.d.ts.map +1 -0
  46. package/dist/src/lib/tsp-index.js +53 -0
  47. package/dist/src/lib/tsp-index.js.map +1 -0
  48. package/dist/src/server/serverlib.d.ts.map +1 -1
  49. package/dist/src/server/serverlib.js +23 -1
  50. package/dist/src/server/serverlib.js.map +1 -1
  51. package/lib/std/decorators.tsp +1 -1
  52. package/package.json +1 -1
  53. package/templates/scaffolding.json +4 -4
@@ -10,14 +10,13 @@ import { validateInheritanceDiscriminatedUnions } from "./helpers/discriminator-
10
10
  import { getLocationContext } from "./helpers/location-context.js";
11
11
  import { explainStringTemplateNotSerializable } from "./helpers/string-template-utils.js";
12
12
  import { getEntityName, getNamespaceFullName, getTypeName, } from "./helpers/type-name-utils.js";
13
- import { getMaxItems, getMaxLength, getMaxValueAsNumeric, getMaxValueExclusiveAsNumeric, getMinItems, getMinLength, getMinValueAsNumeric, getMinValueExclusiveAsNumeric, } from "./intrinsic-type-state.js";
14
13
  import { canNumericConstraintBeJsNumber, legacyMarshallTypeForJS, marshallTypeForJS, } from "./js-marshaller.js";
15
14
  import { createDiagnostic } from "./messages.js";
16
- import { numericRanges } from "./numeric-ranges.js";
17
15
  import { Numeric } from "./numeric.js";
18
16
  import { exprIsBareIdentifier, getFirstAncestor, getIdentifierContext, hasParseError, visitChildren, } from "./parser.js";
19
17
  import { createProjectionMembers } from "./projection-members.js";
20
- import { getFullyQualifiedSymbolName, getParentTemplateNode, isArrayModelType, isErrorType, isNeverType, isNullType, isTemplateInstance, isType, isUnknownType, isValue, isVoidType, } from "./type-utils.js";
18
+ import { createTypeRelationChecker } from "./type-relation-checker.js";
19
+ import { getFullyQualifiedSymbolName, getParentTemplateNode, isArrayModelType, isErrorType, isNullType, isTemplateInstance, isType, isValue, } from "./type-utils.js";
21
20
  import { IdentifierKind, SyntaxKind, } from "./types.js";
22
21
  /**
23
22
  * Maps type arguments to type instantiation.
@@ -122,14 +121,16 @@ export function createChecker(program) {
122
121
  createFunctionType,
123
122
  createLiteralType,
124
123
  finishType,
125
- isTypeAssignableTo,
126
124
  isStdType,
127
125
  getStdType,
128
126
  resolveTypeReference,
129
127
  getValueForNode,
130
128
  getTypeOrValueForNode,
131
129
  getValueExactType,
130
+ isTypeAssignableTo: undefined,
132
131
  };
132
+ const relation = createTypeRelationChecker(program, checker);
133
+ checker.isTypeAssignableTo = relation.isTypeAssignableTo;
133
134
  const projectionMembers = createProjectionMembers(checker);
134
135
  return checker;
135
136
  function reportCheckerDiagnostic(diagnostic) {
@@ -534,7 +535,8 @@ export function createChecker(program) {
534
535
  }
535
536
  function canTryLegacyCast(target, constraint) {
536
537
  return Boolean(constraint?.valueType &&
537
- !(constraint.type && ignoreDiagnostics(isTypeAssignableTo(target, constraint.type, target))));
538
+ !(constraint.type &&
539
+ ignoreDiagnostics(relation.isTypeAssignableTo(target, constraint.type, target))));
538
540
  }
539
541
  /**
540
542
  * Gets a type or value depending on the node and current constraint.
@@ -1298,6 +1300,7 @@ export function createChecker(program) {
1298
1300
  unionType.variants.set(variant.name, variant);
1299
1301
  }
1300
1302
  }
1303
+ linkMapper(unionType, mapper);
1301
1304
  return unionType;
1302
1305
  }
1303
1306
  /**
@@ -1352,15 +1355,16 @@ export function createChecker(program) {
1352
1355
  if (marshalling === "legacy") {
1353
1356
  for (const param of decorator.parameters) {
1354
1357
  if (param.type.valueType) {
1355
- if (ignoreDiagnostics(isTypeAssignableTo(nullType, param.type.valueType, param.type))) {
1358
+ if (ignoreDiagnostics(relation.isTypeAssignableTo(nullType, param.type.valueType, param.type))) {
1356
1359
  reportDeprecatedLegacyMarshalling(param, "null as a type");
1357
1360
  }
1358
1361
  else if (param.type.valueType.kind === "Enum" ||
1359
1362
  param.type.valueType.kind === "EnumMember" ||
1360
- (isReflectionType(param.type.valueType) && param.type.valueType.name === "EnumMember")) {
1363
+ (relation.isReflectionType(param.type.valueType) &&
1364
+ param.type.valueType.name === "EnumMember")) {
1361
1365
  reportDeprecatedLegacyMarshalling(param, "enum members");
1362
1366
  }
1363
- else if (ignoreDiagnostics(isTypeAssignableTo(param.type.valueType, getStdType("numeric"), param.type.valueType)) &&
1367
+ else if (ignoreDiagnostics(relation.isTypeAssignableTo(param.type.valueType, getStdType("numeric"), param.type.valueType)) &&
1364
1368
  !canNumericConstraintBeJsNumber(param.type.valueType)) {
1365
1369
  reportDeprecatedLegacyMarshalling(param, "a numeric type that is not representable as a JS Number");
1366
1370
  }
@@ -1606,7 +1610,8 @@ export function createChecker(program) {
1606
1610
  node.kind === SyntaxKind.IntersectionExpression) {
1607
1611
  let parent = node.parent;
1608
1612
  while (parent !== undefined) {
1609
- if (parent.kind === SyntaxKind.ModelStatement ||
1613
+ if (parent.kind === SyntaxKind.AliasStatement ||
1614
+ parent.kind === SyntaxKind.ModelStatement ||
1610
1615
  parent.kind === SyntaxKind.ScalarStatement ||
1611
1616
  parent.kind === SyntaxKind.OperationStatement ||
1612
1617
  parent.kind === SyntaxKind.EnumStatement ||
@@ -2884,6 +2889,7 @@ export function createChecker(program) {
2884
2889
  derivedModels: [],
2885
2890
  sourceModels: [],
2886
2891
  });
2892
+ linkMapper(type, mapper);
2887
2893
  checkModelProperties(node, properties, type, mapper);
2888
2894
  return finishType(type);
2889
2895
  }
@@ -2915,7 +2921,7 @@ export function createChecker(program) {
2915
2921
  ]);
2916
2922
  return;
2917
2923
  }
2918
- const [valid, diagnostics] = isTypeAssignableTo(property.type, indexer.value, diagnosticTarget);
2924
+ const [valid, diagnostics] = relation.isTypeAssignableTo(property.type, indexer.value, diagnosticTarget);
2919
2925
  if (!valid)
2920
2926
  reportCheckerDiagnostic(createDiagnostic({
2921
2927
  code: "incompatible-indexer",
@@ -3089,7 +3095,7 @@ export function createChecker(program) {
3089
3095
  }
3090
3096
  switch (type.kind) {
3091
3097
  case "Scalar":
3092
- if (ignoreDiagnostics(isTypeAssignableTo(literalType, type, literalType))) {
3098
+ if (ignoreDiagnostics(checker.isTypeAssignableTo(literalType, type, literalType))) {
3093
3099
  return type;
3094
3100
  }
3095
3101
  return undefined;
@@ -3330,13 +3336,13 @@ export function createChecker(program) {
3330
3336
  if (target.kind === "ScalarConstructor") {
3331
3337
  return createScalarValue(node, mapper, target);
3332
3338
  }
3333
- if (areScalarsRelated(target, getStdType("string"))) {
3339
+ if (relation.areScalarsRelated(target, getStdType("string"))) {
3334
3340
  return checkPrimitiveArg(node, target, "StringValue");
3335
3341
  }
3336
- else if (areScalarsRelated(target, getStdType("numeric"))) {
3342
+ else if (relation.areScalarsRelated(target, getStdType("numeric"))) {
3337
3343
  return checkPrimitiveArg(node, target, "NumericValue");
3338
3344
  }
3339
- else if (areScalarsRelated(target, getStdType("boolean"))) {
3345
+ else if (relation.areScalarsRelated(target, getStdType("boolean"))) {
3340
3346
  return checkPrimitiveArg(node, target, "BooleanValue");
3341
3347
  }
3342
3348
  else {
@@ -3416,7 +3422,7 @@ export function createChecker(program) {
3416
3422
  }
3417
3423
  const overriddenProp = getOverriddenProperty(newProp);
3418
3424
  if (overriddenProp) {
3419
- const [isAssignable, _] = isTypeAssignableTo(newProp.type, overriddenProp.type, newProp);
3425
+ const [isAssignable, _] = relation.isTypeAssignableTo(newProp.type, overriddenProp.type, newProp);
3420
3426
  const parentType = getTypeName(overriddenProp.type);
3421
3427
  const newPropType = getTypeName(newProp.type);
3422
3428
  let invalid = false;
@@ -3917,7 +3923,7 @@ export function createChecker(program) {
3917
3923
  if (defaultValue === null) {
3918
3924
  return null;
3919
3925
  }
3920
- const [related, diagnostics] = isValueOfType(defaultValue, type, defaultNode);
3926
+ const [related, diagnostics] = relation.isValueOfType(defaultValue, type, defaultNode);
3921
3927
  if (!related) {
3922
3928
  reportCheckerDiagnostics(diagnostics);
3923
3929
  return null;
@@ -4000,7 +4006,7 @@ export function createChecker(program) {
4000
4006
  }
4001
4007
  /** Check the decorator target is valid */
4002
4008
  function checkDecoratorTarget(targetType, declaration, decoratorNode) {
4003
- const [targetValid] = isTypeAssignableTo(targetType, declaration.target.type, decoratorNode);
4009
+ const [targetValid] = relation.isTypeAssignableTo(targetType, declaration.target.type, decoratorNode);
4004
4010
  if (!targetValid) {
4005
4011
  reportCheckerDiagnostic(createDiagnostic({
4006
4012
  code: "decorator-wrong-target",
@@ -4161,7 +4167,7 @@ export function createChecker(program) {
4161
4167
  return value;
4162
4168
  }
4163
4169
  function checkArgumentAssignable(argumentType, parameterType, diagnosticTarget) {
4164
- const [valid] = isTypeAssignableTo(argumentType, parameterType, diagnosticTarget);
4170
+ const [valid] = relation.isTypeAssignableTo(argumentType, parameterType, diagnosticTarget);
4165
4171
  if (!valid) {
4166
4172
  reportCheckerDiagnostic(createDiagnostic({
4167
4173
  code: "invalid-argument",
@@ -5596,7 +5602,7 @@ export function createChecker(program) {
5596
5602
  * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
5597
5603
  */
5598
5604
  function checkTypeOfValueMatchConstraint(source, constraint, diagnosticTarget) {
5599
- const [related, diagnostics] = isTypeAssignableTo(source, constraint.type, diagnosticTarget);
5605
+ const [related, diagnostics] = relation.isTypeAssignableTo(source, constraint.type, diagnosticTarget);
5600
5606
  if (!related) {
5601
5607
  if (constraint.kind === "argument") {
5602
5608
  reportCheckerDiagnostic(createDiagnostic({
@@ -5621,552 +5627,19 @@ export function createChecker(program) {
5621
5627
  * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
5622
5628
  */
5623
5629
  function checkTypeAssignable(source, target, diagnosticTarget) {
5624
- const [related, diagnostics] = isTypeAssignableTo(source, target, diagnosticTarget);
5630
+ const [related, diagnostics] = relation.isTypeAssignableTo(source, target, diagnosticTarget);
5625
5631
  if (!related) {
5626
5632
  reportCheckerDiagnostics(diagnostics);
5627
5633
  }
5628
5634
  return related;
5629
5635
  }
5630
5636
  function checkValueOfType(source, target, diagnosticTarget) {
5631
- const [related, diagnostics] = isValueOfType(source, target, diagnosticTarget);
5637
+ const [related, diagnostics] = relation.isValueOfType(source, target, diagnosticTarget);
5632
5638
  if (!related) {
5633
5639
  reportCheckerDiagnostics(diagnostics);
5634
5640
  }
5635
5641
  return related;
5636
5642
  }
5637
- /**
5638
- * Check if the source type can be assigned to the target type.
5639
- * @param source Source type
5640
- * @param target Target type
5641
- * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
5642
- */
5643
- function isTypeAssignableTo(source, target, diagnosticTarget) {
5644
- const [related, diagnostics] = isTypeAssignableToInternal(source, target, diagnosticTarget, new MultiKeyMap());
5645
- return [related === Related.true, diagnostics];
5646
- }
5647
- /**
5648
- * Check if the given Value type is of the given type.
5649
- * @param source Value
5650
- * @param target Target type
5651
- * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
5652
- */
5653
- function isValueOfType(source, target, diagnosticTarget) {
5654
- const [related, diagnostics] = isValueOfTypeInternal(source, target, diagnosticTarget, new MultiKeyMap());
5655
- return [related === Related.true, diagnostics];
5656
- }
5657
- function isTypeAssignableToInternal(source, target, diagnosticTarget, relationCache) {
5658
- const cached = relationCache.get([source, target]);
5659
- if (cached !== undefined) {
5660
- return [cached, []];
5661
- }
5662
- const [result, diagnostics] = isTypeAssignableToWorker(source, target, diagnosticTarget, new MultiKeyMap());
5663
- relationCache.set([source, target], result);
5664
- return [result, diagnostics];
5665
- }
5666
- function isTypeAssignableToWorker(source, target, diagnosticTarget, relationCache) {
5667
- // BACKCOMPAT: Allow certain type to be accepted as values
5668
- if ("kind" in source &&
5669
- "entityKind" in target &&
5670
- source.kind === "TemplateParameter" &&
5671
- source.constraint?.type &&
5672
- source.constraint.valueType === undefined &&
5673
- target.entityKind === "MixedParameterConstraint" &&
5674
- target.valueType) {
5675
- const [assignable] = isTypeAssignableToInternal(source.constraint.type, target.valueType, diagnosticTarget, relationCache);
5676
- if (assignable) {
5677
- const constraint = getEntityName(source.constraint);
5678
- reportDeprecated(program, `Template constrainted to '${constraint}' will not be assignable to '${getEntityName(target)}' in the future. Update the constraint to be 'valueof ${constraint}'`, diagnosticTarget);
5679
- return [Related.true, []];
5680
- }
5681
- }
5682
- if ("kind" in source && source.kind === "TemplateParameter") {
5683
- source = source.constraint ?? unknownType;
5684
- }
5685
- if (target.entityKind === "Indeterminate") {
5686
- target = target.type;
5687
- }
5688
- if (source === target)
5689
- return [Related.true, []];
5690
- if (isValue(target)) {
5691
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5692
- }
5693
- if (source.entityKind === "Indeterminate") {
5694
- return isIndeterminateEntityAssignableTo(source, target, diagnosticTarget, relationCache);
5695
- }
5696
- if (target.entityKind === "MixedParameterConstraint") {
5697
- return isAssignableToMixedParameterConstraint(source, target, diagnosticTarget, relationCache);
5698
- }
5699
- if (isValue(source) || (source.entityKind === "MixedParameterConstraint" && source.valueType)) {
5700
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5701
- }
5702
- if (source.entityKind === "MixedParameterConstraint") {
5703
- return isTypeAssignableToInternal(source.type, target, diagnosticTarget, relationCache);
5704
- }
5705
- const isSimpleTypeRelated = isSimpleTypeAssignableTo(source, target);
5706
- if (isSimpleTypeRelated === true) {
5707
- return [Related.true, []];
5708
- }
5709
- else if (isSimpleTypeRelated === false) {
5710
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5711
- }
5712
- if (source.kind === "Union") {
5713
- for (const variant of source.variants.values()) {
5714
- const [variantAssignable] = isTypeAssignableToInternal(variant.type, target, diagnosticTarget, relationCache);
5715
- if (!variantAssignable) {
5716
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5717
- }
5718
- }
5719
- return [Related.true, []];
5720
- }
5721
- if (target.kind === "Model" &&
5722
- source.kind === "Model" &&
5723
- target.name !== "object" &&
5724
- target.indexer === undefined &&
5725
- source.indexer &&
5726
- source.indexer.key.name === "integer") {
5727
- return [
5728
- Related.false,
5729
- [
5730
- createDiagnostic({
5731
- code: "missing-index",
5732
- format: {
5733
- indexType: getTypeName(source.indexer.key),
5734
- sourceType: getTypeName(target),
5735
- },
5736
- target: diagnosticTarget,
5737
- }),
5738
- ],
5739
- ];
5740
- }
5741
- else if (target.kind === "Model" &&
5742
- isArrayModelType(program, target) &&
5743
- source.kind === "Model") {
5744
- if (isArrayModelType(program, source)) {
5745
- return hasIndexAndIsAssignableTo(source, target, diagnosticTarget, relationCache);
5746
- }
5747
- else {
5748
- // For other models just fallback to unassignable
5749
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5750
- }
5751
- }
5752
- else if (target.kind === "Model" && source.kind === "Model") {
5753
- return isModelRelatedTo(source, target, diagnosticTarget, relationCache);
5754
- }
5755
- else if (target.kind === "Model" &&
5756
- isArrayModelType(program, target) &&
5757
- source.kind === "Tuple") {
5758
- return isTupleAssignableToArray(source, target, diagnosticTarget, relationCache);
5759
- }
5760
- else if (target.kind === "Tuple" && source.kind === "Tuple") {
5761
- return isTupleAssignableToTuple(source, target, diagnosticTarget, relationCache);
5762
- }
5763
- else if (target.kind === "Union") {
5764
- return isAssignableToUnion(source, target, diagnosticTarget, relationCache);
5765
- }
5766
- else if (target.kind === "Enum") {
5767
- return isAssignableToEnum(source, target, diagnosticTarget);
5768
- }
5769
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5770
- }
5771
- function isIndeterminateEntityAssignableTo(indeterminate, target, diagnosticTarget, relationCache) {
5772
- const [typeRelated, typeDiagnostics] = isTypeAssignableToInternal(indeterminate.type, target, diagnosticTarget, relationCache);
5773
- if (typeRelated) {
5774
- return [Related.true, []];
5775
- }
5776
- if (target.entityKind === "MixedParameterConstraint" && target.valueType) {
5777
- const [valueRelated] = isTypeAssignableToInternal(indeterminate.type, target.valueType, diagnosticTarget, relationCache);
5778
- if (valueRelated) {
5779
- return [Related.true, []];
5780
- }
5781
- }
5782
- return [Related.false, typeDiagnostics];
5783
- }
5784
- function isAssignableToValueType(source, target, diagnosticTarget, relationCache) {
5785
- if (!isValue(source)) {
5786
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5787
- }
5788
- return isValueOfTypeInternal(source, target, diagnosticTarget, relationCache);
5789
- }
5790
- function isAssignableToMixedParameterConstraint(source, target, diagnosticTarget, relationCache) {
5791
- if ("entityKind" in source && source.entityKind === "MixedParameterConstraint") {
5792
- if (source.type && target.type) {
5793
- const [variantAssignable, diagnostics] = isTypeAssignableToInternal(source.type, target.type, diagnosticTarget, relationCache);
5794
- if (variantAssignable === Related.false) {
5795
- return [Related.false, diagnostics];
5796
- }
5797
- return [Related.true, []];
5798
- }
5799
- if (source.valueType && target.valueType) {
5800
- const [variantAssignable, diagnostics] = isTypeAssignableToInternal(source.valueType, target.valueType, diagnosticTarget, relationCache);
5801
- if (variantAssignable === Related.false) {
5802
- return [Related.false, diagnostics];
5803
- }
5804
- return [Related.true, []];
5805
- }
5806
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5807
- }
5808
- if (target.type) {
5809
- const [related] = isTypeAssignableToInternal(source, target.type, diagnosticTarget, relationCache);
5810
- if (related) {
5811
- return [Related.true, []];
5812
- }
5813
- }
5814
- if (target.valueType) {
5815
- const [related] = isAssignableToValueType(source, target.valueType, diagnosticTarget, relationCache);
5816
- if (related) {
5817
- return [Related.true, []];
5818
- }
5819
- }
5820
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5821
- }
5822
- /** Check if the value is assignable to the given type. */
5823
- function isValueOfTypeInternal(source, target, diagnosticTarget, relationCache) {
5824
- return isTypeAssignableToInternal(source.type, target, diagnosticTarget, relationCache);
5825
- }
5826
- function isReflectionType(type) {
5827
- return (type.kind === "Model" &&
5828
- type.namespace?.name === "Reflection" &&
5829
- type.namespace?.namespace?.name === "TypeSpec");
5830
- }
5831
- function isRelatedToScalar(source, target) {
5832
- switch (source.kind) {
5833
- case "Number":
5834
- return isNumericLiteralRelatedTo(source, target);
5835
- case "String":
5836
- case "StringTemplate":
5837
- return isStringLiteralRelatedTo(source, target);
5838
- case "Boolean":
5839
- return areScalarsRelated(target, getStdType("boolean"));
5840
- case "Scalar":
5841
- return areScalarsRelated(source, target);
5842
- case "Union":
5843
- return undefined;
5844
- default:
5845
- return false;
5846
- }
5847
- }
5848
- function areScalarsRelated(source, target) {
5849
- let current = source;
5850
- while (current) {
5851
- if (current === target) {
5852
- return true;
5853
- }
5854
- current = current.baseScalar;
5855
- }
5856
- return false;
5857
- }
5858
- function isSimpleTypeAssignableTo(source, target) {
5859
- if (isNeverType(source))
5860
- return true;
5861
- if (isVoidType(target))
5862
- return false;
5863
- if (isUnknownType(target))
5864
- return true;
5865
- if (isReflectionType(target)) {
5866
- return source.kind === ReflectionNameToKind[target.name];
5867
- }
5868
- if (target.kind === "Scalar") {
5869
- return isRelatedToScalar(source, target);
5870
- }
5871
- if (source.kind === "Scalar" && target.kind === "Model") {
5872
- return false;
5873
- }
5874
- if (target.kind === "String") {
5875
- return ((source.kind === "String" && source.value === target.value) ||
5876
- (source.kind === "StringTemplate" && source.stringValue === target.value));
5877
- }
5878
- if (target.kind === "StringTemplate" && target.stringValue) {
5879
- return ((source.kind === "String" && source.value === target.stringValue) ||
5880
- (source.kind === "StringTemplate" && source.stringValue === target.stringValue));
5881
- }
5882
- if (target.kind === "Number") {
5883
- return source.kind === "Number" && target.value === source.value;
5884
- }
5885
- return undefined;
5886
- }
5887
- function isNumericLiteralRelatedTo(source, target) {
5888
- // First check that the source numeric literal is assignable to the target scalar
5889
- if (!isNumericAssignableToNumericScalar(source.numericValue, target)) {
5890
- return false;
5891
- }
5892
- const min = getMinValueAsNumeric(program, target);
5893
- const max = getMaxValueAsNumeric(program, target);
5894
- const minExclusive = getMinValueExclusiveAsNumeric(program, target);
5895
- const maxExclusive = getMaxValueExclusiveAsNumeric(program, target);
5896
- if (min && source.numericValue.lt(min)) {
5897
- return false;
5898
- }
5899
- if (minExclusive && source.numericValue.lte(minExclusive)) {
5900
- return false;
5901
- }
5902
- if (max && source.numericValue.gt(max)) {
5903
- return false;
5904
- }
5905
- if (maxExclusive && source.numericValue.gte(maxExclusive)) {
5906
- return false;
5907
- }
5908
- return true;
5909
- }
5910
- function isNumericAssignableToNumericScalar(source, target) {
5911
- // if the target does not derive from numeric, then it can't be assigned a numeric literal
5912
- if (!areScalarsRelated(target.projectionBase ?? target, getStdType("numeric"))) {
5913
- return false;
5914
- }
5915
- // With respect to literal assignability a custom numeric scalar is
5916
- // equivalent to its nearest TypeSpec.* base. Adjust target accordingly.
5917
- while (!target.namespace || !isTypeSpecNamespace(target.namespace)) {
5918
- compilerAssert(target.baseScalar, "Should not be possible to be derived from TypeSpec.numeric and not have a base when not in TypeSpec namespace.");
5919
- target = target.baseScalar;
5920
- }
5921
- if (target.name === "numeric")
5922
- return true;
5923
- if (target.name === "decimal")
5924
- return true;
5925
- if (target.name === "decimal128")
5926
- return true;
5927
- const isInt = source.isInteger;
5928
- if (target.name === "integer")
5929
- return isInt;
5930
- if (target.name === "float")
5931
- return true;
5932
- if (!(target.name in numericRanges))
5933
- return false;
5934
- const [low, high, options] = numericRanges[target.name];
5935
- return source.gte(low) && source.lte(high) && (!options.int || isInt);
5936
- }
5937
- function isStringLiteralRelatedTo(source, target) {
5938
- if (!areScalarsRelated(target.projectionBase ?? target, getStdType("string"))) {
5939
- return false;
5940
- }
5941
- if (source.kind === "StringTemplate") {
5942
- return true;
5943
- }
5944
- const len = source.value.length;
5945
- const min = getMinLength(program, target);
5946
- const max = getMaxLength(program, target);
5947
- if (min && len < min) {
5948
- return false;
5949
- }
5950
- if (max && len > max) {
5951
- return false;
5952
- }
5953
- return true;
5954
- }
5955
- function isModelRelatedTo(source, target, diagnosticTarget, relationCache) {
5956
- relationCache.set([source, target], Related.maybe);
5957
- const diagnostics = [];
5958
- const remainingProperties = new Map(source.properties);
5959
- for (const prop of walkPropertiesInherited(target)) {
5960
- const sourceProperty = getProperty(source, prop.name);
5961
- if (sourceProperty === undefined) {
5962
- if (!prop.optional) {
5963
- diagnostics.push(createDiagnostic({
5964
- code: "missing-property",
5965
- format: {
5966
- propertyName: prop.name,
5967
- sourceType: getTypeName(source),
5968
- targetType: getTypeName(target),
5969
- },
5970
- target: source,
5971
- }));
5972
- }
5973
- }
5974
- else {
5975
- remainingProperties.delete(prop.name);
5976
- if (sourceProperty.optional && !prop.optional) {
5977
- diagnostics.push(createDiagnostic({
5978
- code: "property-required",
5979
- format: {
5980
- propName: prop.name,
5981
- targetType: getTypeName(target),
5982
- },
5983
- target: diagnosticTarget,
5984
- }));
5985
- }
5986
- const [related, propDiagnostics] = isTypeAssignableToInternal(sourceProperty.type, prop.type, diagnosticTarget, relationCache);
5987
- if (!related) {
5988
- diagnostics.push(...propDiagnostics);
5989
- }
5990
- }
5991
- }
5992
- if (target.indexer) {
5993
- const [_, indexerDiagnostics] = arePropertiesAssignableToIndexer(remainingProperties, target.indexer.value, diagnosticTarget, relationCache);
5994
- diagnostics.push(...indexerDiagnostics);
5995
- // For anonymous models we don't need an indexer
5996
- if (source.name !== "" && target.indexer.key.name !== "integer") {
5997
- const [related, indexDiagnostics] = hasIndexAndIsAssignableTo(source, target, diagnosticTarget, relationCache);
5998
- if (!related) {
5999
- diagnostics.push(...indexDiagnostics);
6000
- }
6001
- }
6002
- }
6003
- else if (shouldCheckExcessProperties(source)) {
6004
- for (const [propName, prop] of remainingProperties) {
6005
- if (shouldCheckExcessProperty(prop)) {
6006
- diagnostics.push(createDiagnostic({
6007
- code: "unexpected-property",
6008
- format: {
6009
- propertyName: propName,
6010
- type: getEntityName(target),
6011
- },
6012
- target: prop,
6013
- }));
6014
- }
6015
- }
6016
- }
6017
- return [diagnostics.length === 0 ? Related.true : Related.false, diagnostics];
6018
- }
6019
- /** If we should check for excess properties on the given model. */
6020
- function shouldCheckExcessProperties(model) {
6021
- return model.node?.kind === SyntaxKind.ObjectLiteral;
6022
- }
6023
- /** If we should check for this specific property */
6024
- function shouldCheckExcessProperty(prop) {
6025
- return (prop.node?.kind === SyntaxKind.ObjectLiteralProperty && prop.node.parent === prop.model?.node);
6026
- }
6027
- function getProperty(model, name) {
6028
- return (model.properties.get(name) ??
6029
- (model.baseModel !== undefined ? getProperty(model.baseModel, name) : undefined));
6030
- }
6031
- function arePropertiesAssignableToIndexer(properties, indexerConstaint, diagnosticTarget, relationCache) {
6032
- for (const prop of properties.values()) {
6033
- const [related, diagnostics] = isTypeAssignableToInternal(prop.type, indexerConstaint, diagnosticTarget, relationCache);
6034
- if (!related) {
6035
- return [Related.false, diagnostics];
6036
- }
6037
- }
6038
- return [Related.true, []];
6039
- }
6040
- /** Check that the source model has an index, the index key match and the value of the source index is assignable to the target index. */
6041
- function hasIndexAndIsAssignableTo(source, target, diagnosticTarget, relationCache) {
6042
- if (source.indexer === undefined || source.indexer.key !== target.indexer.key) {
6043
- return [
6044
- Related.false,
6045
- [
6046
- createDiagnostic({
6047
- code: "missing-index",
6048
- format: {
6049
- indexType: getTypeName(target.indexer.key),
6050
- sourceType: getTypeName(source),
6051
- },
6052
- target: diagnosticTarget,
6053
- }),
6054
- ],
6055
- ];
6056
- }
6057
- return isTypeAssignableToInternal(source.indexer.value, target.indexer.value, diagnosticTarget, relationCache);
6058
- }
6059
- function isTupleAssignableToArray(source, target, diagnosticTarget, relationCache) {
6060
- const minItems = getMinItems(program, target);
6061
- const maxItems = getMaxItems(program, target);
6062
- if (minItems !== undefined && source.values.length < minItems) {
6063
- return [
6064
- Related.false,
6065
- [
6066
- createDiagnostic({
6067
- code: "unassignable",
6068
- messageId: "withDetails",
6069
- format: {
6070
- sourceType: getEntityName(source),
6071
- targetType: getTypeName(target),
6072
- details: `Source has ${source.values.length} element(s) but target requires ${minItems}.`,
6073
- },
6074
- target: diagnosticTarget,
6075
- }),
6076
- ],
6077
- ];
6078
- }
6079
- if (maxItems !== undefined && source.values.length > maxItems) {
6080
- return [
6081
- Related.false,
6082
- [
6083
- createDiagnostic({
6084
- code: "unassignable",
6085
- messageId: "withDetails",
6086
- format: {
6087
- sourceType: getEntityName(source),
6088
- targetType: getTypeName(target),
6089
- details: `Source has ${source.values.length} element(s) but target only allows ${maxItems}.`,
6090
- },
6091
- target: diagnosticTarget,
6092
- }),
6093
- ],
6094
- ];
6095
- }
6096
- for (const item of source.values) {
6097
- const [related, diagnostics] = isTypeAssignableToInternal(item, target.indexer.value, diagnosticTarget, relationCache);
6098
- if (!related) {
6099
- return [Related.false, diagnostics];
6100
- }
6101
- }
6102
- return [Related.true, []];
6103
- }
6104
- function isTupleAssignableToTuple(source, target, diagnosticTarget, relationCache) {
6105
- if (source.values.length !== target.values.length) {
6106
- return [
6107
- Related.false,
6108
- [
6109
- createDiagnostic({
6110
- code: "unassignable",
6111
- messageId: "withDetails",
6112
- format: {
6113
- sourceType: getEntityName(source),
6114
- targetType: getTypeName(target),
6115
- details: `Source has ${source.values.length} element(s) but target requires ${target.values.length}.`,
6116
- },
6117
- target: diagnosticTarget,
6118
- }),
6119
- ],
6120
- ];
6121
- }
6122
- for (const [index, sourceItem] of source.values.entries()) {
6123
- const targetItem = target.values[index];
6124
- const [related, diagnostics] = isTypeAssignableToInternal(sourceItem, targetItem, diagnosticTarget, relationCache);
6125
- if (!related) {
6126
- return [Related.false, diagnostics];
6127
- }
6128
- }
6129
- return [Related.true, []];
6130
- }
6131
- function isAssignableToUnion(source, target, diagnosticTarget, relationCache) {
6132
- if (source.kind === "UnionVariant" && source.union === target) {
6133
- return [Related.true, []];
6134
- }
6135
- for (const option of target.variants.values()) {
6136
- const [related] = isTypeAssignableToInternal(source, option.type, diagnosticTarget, relationCache);
6137
- if (related) {
6138
- return [Related.true, []];
6139
- }
6140
- }
6141
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
6142
- }
6143
- function isAssignableToEnum(source, target, diagnosticTarget) {
6144
- switch (source.kind) {
6145
- case "Enum":
6146
- if (source === target) {
6147
- return [Related.true, []];
6148
- }
6149
- else {
6150
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
6151
- }
6152
- case "EnumMember":
6153
- if (source.enum === target) {
6154
- return [Related.true, []];
6155
- }
6156
- else {
6157
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
6158
- }
6159
- default:
6160
- return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
6161
- }
6162
- }
6163
- function createUnassignableDiagnostic(source, target, diagnosticTarget) {
6164
- return createDiagnostic({
6165
- code: "unassignable",
6166
- format: { targetType: getEntityName(target), value: getEntityName(source) },
6167
- target: diagnosticTarget,
6168
- });
6169
- }
6170
5643
  function isStdType(type, stdType) {
6171
5644
  type = type.projectionBase ?? type;
6172
5645
  if ((type.kind !== "Model" && type.kind !== "Scalar") ||
@@ -6562,24 +6035,6 @@ function createDecoratorContext(program, decApp) {
6562
6035
  function isTemplatedNode(node) {
6563
6036
  return "templateParameters" in node && node.templateParameters.length > 0;
6564
6037
  }
6565
- /**
6566
- * Mapping from the reflection models to Type["kind"] value
6567
- */
6568
- const ReflectionNameToKind = {
6569
- Enum: "Enum",
6570
- EnumMember: "EnumMember",
6571
- Interface: "Interface",
6572
- Model: "Model",
6573
- ModelProperty: "ModelProperty",
6574
- Namespace: "Namespace",
6575
- Operation: "Operation",
6576
- Scalar: "Scalar",
6577
- TemplateParameter: "TemplateParameter",
6578
- Tuple: "Tuple",
6579
- Union: "Union",
6580
- UnionVariant: "UnionVariant",
6581
- };
6582
- const _assertReflectionNameToKind = ReflectionNameToKind;
6583
6038
  var ResolutionKind;
6584
6039
  (function (ResolutionKind) {
6585
6040
  ResolutionKind[ResolutionKind["Value"] = 0] = "Value";
@@ -6611,12 +6066,6 @@ class PendingResolutions {
6611
6066
  }
6612
6067
  }
6613
6068
  }
6614
- var Related;
6615
- (function (Related) {
6616
- Related[Related["false"] = 0] = "false";
6617
- Related[Related["true"] = 1] = "true";
6618
- Related[Related["maybe"] = 2] = "maybe";
6619
- })(Related || (Related = {}));
6620
6069
  const defaultSymbolResolutionOptions = {
6621
6070
  resolveDecorators: false,
6622
6071
  checkTemplateTypes: true,