@typespec/compiler 0.57.0-dev.0 → 0.57.0-dev.5

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 (194) hide show
  1. package/dist/generated-defs/TypeSpec.d.ts +9 -9
  2. package/dist/generated-defs/TypeSpec.d.ts.map +1 -1
  3. package/dist/manifest.js +2 -2
  4. package/dist/src/config/types.d.ts +2 -2
  5. package/dist/src/config/types.d.ts.map +1 -1
  6. package/dist/src/core/binder.d.ts +1 -1
  7. package/dist/src/core/binder.d.ts.map +1 -1
  8. package/dist/src/core/binder.js +16 -3
  9. package/dist/src/core/binder.js.map +1 -1
  10. package/dist/src/core/checker.d.ts +11 -9
  11. package/dist/src/core/checker.d.ts.map +1 -1
  12. package/dist/src/core/checker.js +1577 -241
  13. package/dist/src/core/checker.js.map +1 -1
  14. package/dist/src/core/compiler-code-fixes/model-to-object-literal.codefix.d.ts +6 -0
  15. package/dist/src/core/compiler-code-fixes/model-to-object-literal.codefix.d.ts.map +1 -0
  16. package/dist/src/core/compiler-code-fixes/model-to-object-literal.codefix.js +15 -0
  17. package/dist/src/core/compiler-code-fixes/model-to-object-literal.codefix.js.map +1 -0
  18. package/dist/src/core/compiler-code-fixes/tuple-to-array-value.codefix.d.ts +6 -0
  19. package/dist/src/core/compiler-code-fixes/tuple-to-array-value.codefix.d.ts.map +1 -0
  20. package/dist/src/core/compiler-code-fixes/tuple-to-array-value.codefix.js +15 -0
  21. package/dist/src/core/compiler-code-fixes/tuple-to-array-value.codefix.js.map +1 -0
  22. package/dist/src/core/decorator-utils.d.ts +5 -1
  23. package/dist/src/core/decorator-utils.d.ts.map +1 -1
  24. package/dist/src/core/decorator-utils.js +11 -1
  25. package/dist/src/core/decorator-utils.js.map +1 -1
  26. package/dist/src/core/deprecation.d.ts +1 -1
  27. package/dist/src/core/deprecation.d.ts.map +1 -1
  28. package/dist/src/core/diagnostic-creator.d.ts.map +1 -1
  29. package/dist/src/core/diagnostic-creator.js +1 -2
  30. package/dist/src/core/diagnostic-creator.js.map +1 -1
  31. package/dist/src/core/diagnostics.js +3 -3
  32. package/dist/src/core/diagnostics.js.map +1 -1
  33. package/dist/src/core/emitter-utils.d.ts +1 -1
  34. package/dist/src/core/emitter-utils.d.ts.map +1 -1
  35. package/dist/src/core/helpers/discriminator-utils.d.ts +2 -2
  36. package/dist/src/core/helpers/discriminator-utils.d.ts.map +1 -1
  37. package/dist/src/core/helpers/discriminator-utils.js +1 -1
  38. package/dist/src/core/helpers/discriminator-utils.js.map +1 -1
  39. package/dist/src/core/helpers/index.d.ts +1 -1
  40. package/dist/src/core/helpers/index.d.ts.map +1 -1
  41. package/dist/src/core/helpers/index.js +3 -1
  42. package/dist/src/core/helpers/index.js.map +1 -1
  43. package/dist/src/core/helpers/location-context.d.ts +2 -2
  44. package/dist/src/core/helpers/location-context.d.ts.map +1 -1
  45. package/dist/src/core/helpers/projected-names-utils.d.ts +2 -2
  46. package/dist/src/core/helpers/projected-names-utils.d.ts.map +1 -1
  47. package/dist/src/core/helpers/projected-names-utils.js.map +1 -1
  48. package/dist/src/core/helpers/string-template-utils.d.ts +6 -6
  49. package/dist/src/core/helpers/string-template-utils.d.ts.map +1 -1
  50. package/dist/src/core/helpers/string-template-utils.js +20 -33
  51. package/dist/src/core/helpers/string-template-utils.js.map +1 -1
  52. package/dist/src/core/helpers/type-name-utils.d.ts +3 -2
  53. package/dist/src/core/helpers/type-name-utils.d.ts.map +1 -1
  54. package/dist/src/core/helpers/type-name-utils.js +57 -8
  55. package/dist/src/core/helpers/type-name-utils.js.map +1 -1
  56. package/dist/src/core/index.d.ts +4 -1
  57. package/dist/src/core/index.d.ts.map +1 -1
  58. package/dist/src/core/index.js +4 -1
  59. package/dist/src/core/index.js.map +1 -1
  60. package/dist/src/core/intrinsic-type-state.d.ts +63 -0
  61. package/dist/src/core/intrinsic-type-state.d.ts.map +1 -0
  62. package/dist/src/core/intrinsic-type-state.js +160 -0
  63. package/dist/src/core/intrinsic-type-state.js.map +1 -0
  64. package/dist/src/core/js-marshaller.d.ts +13 -0
  65. package/dist/src/core/js-marshaller.d.ts.map +1 -0
  66. package/dist/src/core/js-marshaller.js +79 -0
  67. package/dist/src/core/js-marshaller.js.map +1 -0
  68. package/dist/src/core/library.d.ts +2 -1
  69. package/dist/src/core/library.d.ts.map +1 -1
  70. package/dist/src/core/library.js +3 -0
  71. package/dist/src/core/library.js.map +1 -1
  72. package/dist/src/core/linter.d.ts +1 -1
  73. package/dist/src/core/linter.d.ts.map +1 -1
  74. package/dist/src/core/linter.js +1 -1
  75. package/dist/src/core/linter.js.map +1 -1
  76. package/dist/src/core/messages.d.ts +235 -2
  77. package/dist/src/core/messages.d.ts.map +1 -1
  78. package/dist/src/core/messages.js +74 -1
  79. package/dist/src/core/messages.js.map +1 -1
  80. package/dist/src/core/numeric-ranges.d.ts +51 -0
  81. package/dist/src/core/numeric-ranges.d.ts.map +1 -0
  82. package/dist/src/core/numeric-ranges.js +30 -0
  83. package/dist/src/core/numeric-ranges.js.map +1 -0
  84. package/dist/src/core/parser.d.ts.map +1 -1
  85. package/dist/src/core/parser.js +232 -5
  86. package/dist/src/core/parser.js.map +1 -1
  87. package/dist/src/core/program.d.ts +2 -45
  88. package/dist/src/core/program.d.ts.map +1 -1
  89. package/dist/src/core/program.js +3 -127
  90. package/dist/src/core/program.js.map +1 -1
  91. package/dist/src/core/projected-program.d.ts +3 -0
  92. package/dist/src/core/projected-program.d.ts.map +1 -0
  93. package/dist/src/core/projected-program.js +4 -0
  94. package/dist/src/core/projected-program.js.map +1 -0
  95. package/dist/src/core/projection-members.d.ts +2 -2
  96. package/dist/src/core/projection-members.d.ts.map +1 -1
  97. package/dist/src/core/projector.d.ts +2 -2
  98. package/dist/src/core/projector.d.ts.map +1 -1
  99. package/dist/src/core/projector.js +12 -3
  100. package/dist/src/core/projector.js.map +1 -1
  101. package/dist/src/core/scanner.d.ts +42 -37
  102. package/dist/src/core/scanner.d.ts.map +1 -1
  103. package/dist/src/core/scanner.js +67 -46
  104. package/dist/src/core/scanner.js.map +1 -1
  105. package/dist/src/core/semantic-walker.d.ts +1 -1
  106. package/dist/src/core/semantic-walker.d.ts.map +1 -1
  107. package/dist/src/core/semantic-walker.js +12 -0
  108. package/dist/src/core/semantic-walker.js.map +1 -1
  109. package/dist/src/core/state-accessors.d.ts +46 -0
  110. package/dist/src/core/state-accessors.d.ts.map +1 -0
  111. package/dist/src/core/state-accessors.js +123 -0
  112. package/dist/src/core/state-accessors.js.map +1 -0
  113. package/dist/src/core/type-utils.d.ts +18 -7
  114. package/dist/src/core/type-utils.d.ts.map +1 -1
  115. package/dist/src/core/type-utils.js +24 -5
  116. package/dist/src/core/type-utils.js.map +1 -1
  117. package/dist/src/core/types.d.ts +224 -45
  118. package/dist/src/core/types.d.ts.map +1 -1
  119. package/dist/src/core/types.js +8 -0
  120. package/dist/src/core/types.js.map +1 -1
  121. package/dist/src/emitter-framework/asset-emitter.d.ts +1 -1
  122. package/dist/src/emitter-framework/asset-emitter.d.ts.map +1 -1
  123. package/dist/src/emitter-framework/asset-emitter.js +4 -1
  124. package/dist/src/emitter-framework/asset-emitter.js.map +1 -1
  125. package/dist/src/emitter-framework/ref-scope.d.ts +1 -1
  126. package/dist/src/emitter-framework/ref-scope.d.ts.map +1 -1
  127. package/dist/src/emitter-framework/reference-cycle.d.ts +2 -2
  128. package/dist/src/emitter-framework/reference-cycle.d.ts.map +1 -1
  129. package/dist/src/emitter-framework/reference-cycle.js +1 -1
  130. package/dist/src/emitter-framework/reference-cycle.js.map +1 -1
  131. package/dist/src/emitter-framework/type-emitter.d.ts +2 -1
  132. package/dist/src/emitter-framework/type-emitter.d.ts.map +1 -1
  133. package/dist/src/emitter-framework/type-emitter.js +10 -2
  134. package/dist/src/emitter-framework/type-emitter.js.map +1 -1
  135. package/dist/src/emitter-framework/types.d.ts +2 -2
  136. package/dist/src/emitter-framework/types.d.ts.map +1 -1
  137. package/dist/src/formatter/print/comment-handler.d.ts.map +1 -1
  138. package/dist/src/formatter/print/comment-handler.js +22 -0
  139. package/dist/src/formatter/print/comment-handler.js.map +1 -1
  140. package/dist/src/formatter/print/printer.d.ts +11 -5
  141. package/dist/src/formatter/print/printer.d.ts.map +1 -1
  142. package/dist/src/formatter/print/printer.js +95 -4
  143. package/dist/src/formatter/print/printer.js.map +1 -1
  144. package/dist/src/init/file-templating.d.ts +2 -2
  145. package/dist/src/init/file-templating.d.ts.map +1 -1
  146. package/dist/src/lib/decorators.d.ts +3 -55
  147. package/dist/src/lib/decorators.d.ts.map +1 -1
  148. package/dist/src/lib/decorators.js +30 -124
  149. package/dist/src/lib/decorators.js.map +1 -1
  150. package/dist/src/lib/encoded-names.d.ts +2 -2
  151. package/dist/src/lib/encoded-names.d.ts.map +1 -1
  152. package/dist/src/lib/intrinsic-decorators.d.ts +2 -2
  153. package/dist/src/lib/intrinsic-decorators.d.ts.map +1 -1
  154. package/dist/src/lib/intrinsic-decorators.js +7 -0
  155. package/dist/src/lib/intrinsic-decorators.js.map +1 -1
  156. package/dist/src/lib/service.d.ts +1 -1
  157. package/dist/src/lib/service.d.ts.map +1 -1
  158. package/dist/src/server/classify.d.ts.map +1 -1
  159. package/dist/src/server/classify.js +10 -0
  160. package/dist/src/server/classify.js.map +1 -1
  161. package/dist/src/server/completion.d.ts.map +1 -1
  162. package/dist/src/server/completion.js +6 -0
  163. package/dist/src/server/completion.js.map +1 -1
  164. package/dist/src/server/serverlib.js +2 -2
  165. package/dist/src/server/serverlib.js.map +1 -1
  166. package/dist/src/server/tmlanguage.d.ts +1 -1
  167. package/dist/src/server/tmlanguage.d.ts.map +1 -1
  168. package/dist/src/server/tmlanguage.js +147 -20
  169. package/dist/src/server/tmlanguage.js.map +1 -1
  170. package/dist/src/server/type-details.js +1 -2
  171. package/dist/src/server/type-details.js.map +1 -1
  172. package/dist/src/server/type-signature.js +15 -6
  173. package/dist/src/server/type-signature.js.map +1 -1
  174. package/dist/src/server/types.d.ts +1 -1
  175. package/dist/src/server/types.d.ts.map +1 -1
  176. package/dist/src/testing/expect.js +1 -1
  177. package/dist/src/testing/expect.js.map +1 -1
  178. package/dist/src/testing/rule-tester.d.ts.map +1 -1
  179. package/dist/src/testing/rule-tester.js +1 -2
  180. package/dist/src/testing/rule-tester.js.map +1 -1
  181. package/dist/src/testing/test-host.d.ts +1 -2
  182. package/dist/src/testing/test-host.d.ts.map +1 -1
  183. package/dist/src/testing/test-host.js +1 -8
  184. package/dist/src/testing/test-host.js.map +1 -1
  185. package/dist/src/testing/test-server-host.d.ts.map +1 -1
  186. package/dist/src/testing/test-server-host.js +2 -1
  187. package/dist/src/testing/test-server-host.js.map +1 -1
  188. package/dist/src/testing/test-utils.d.ts +1 -0
  189. package/dist/src/testing/test-utils.d.ts.map +1 -1
  190. package/dist/src/testing/test-utils.js +7 -0
  191. package/dist/src/testing/test-utils.js.map +1 -1
  192. package/dist/typespec.tmLanguage +408 -17
  193. package/lib/intrinsics.tsp +55 -5
  194. package/package.json +1 -1
@@ -1,17 +1,23 @@
1
- import { $docFromComment, isArrayModelType } from "../lib/decorators.js";
2
- import { getIndexer } from "../lib/intrinsic-decorators.js";
1
+ import { $docFromComment, getIndexer } from "../lib/intrinsic-decorators.js";
3
2
  import { MultiKeyMap, createRekeyableMap, isArray, mutate } from "../utils/misc.js";
4
3
  import { createSymbol, createSymbolTable } from "./binder.js";
5
4
  import { createChangeIdentifierCodeFix } from "./compiler-code-fixes/change-identifier.codefix.js";
5
+ import { createModelToObjectValueCodeFix } from "./compiler-code-fixes/model-to-object-literal.codefix.js";
6
+ import { createTupleToArrayValueCodeFix } from "./compiler-code-fixes/tuple-to-array-value.codefix.js";
6
7
  import { getDeprecationDetails, markDeprecated } from "./deprecation.js";
7
- import { ProjectionError, compilerAssert, reportDeprecated } from "./diagnostics.js";
8
+ import { ProjectionError, compilerAssert, ignoreDiagnostics, reportDeprecated, } from "./diagnostics.js";
8
9
  import { validateInheritanceDiscriminatedUnions } from "./helpers/discriminator-utils.js";
9
- import { getNamespaceFullName, getTypeName, stringTemplateToString, } from "./helpers/index.js";
10
- import { isStringTemplateSerializable } from "./helpers/string-template-utils.js";
10
+ import { getLocationContext } from "./helpers/location-context.js";
11
+ import { explainStringTemplateNotSerializable } from "./helpers/string-template-utils.js";
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
+ import { canNumericConstraintBeJsNumber, legacyMarshallTypeForJS, marshallTypeForJS, } from "./js-marshaller.js";
11
15
  import { createDiagnostic } from "./messages.js";
16
+ import { numericRanges } from "./numeric-ranges.js";
17
+ import { Numeric } from "./numeric.js";
12
18
  import { exprIsBareIdentifier, getIdentifierContext, hasParseError, visitChildren, } from "./parser.js";
13
19
  import { createProjectionMembers } from "./projection-members.js";
14
- import { getFullyQualifiedSymbolName, getParentTemplateNode, isNeverType, isTemplateInstance, isUnknownType, isVoidType, } from "./type-utils.js";
20
+ import { getFullyQualifiedSymbolName, getParentTemplateNode, isArrayModelType, isErrorType, isNeverType, isNullType, isTemplateInstance, isType, isUnknownType, isValue, isVoidType, } from "./type-utils.js";
15
21
  import { IdentifierKind, SyntaxKind, } from "./types.js";
16
22
  /**
17
23
  * Maps type arguments to type instantiation.
@@ -105,6 +111,7 @@ export function createChecker(program) {
105
111
  project,
106
112
  neverType,
107
113
  errorType,
114
+ nullType,
108
115
  anyType: unknownType,
109
116
  voidType,
110
117
  typePrototype,
@@ -117,6 +124,8 @@ export function createChecker(program) {
117
124
  isStdType,
118
125
  getStdType,
119
126
  resolveTypeReference,
127
+ getValueForNode,
128
+ getTypeOrValueForNode,
120
129
  };
121
130
  const projectionMembers = createProjectionMembers(checker);
122
131
  return checker;
@@ -207,13 +216,13 @@ export function createChecker(program) {
207
216
  if (ref.flags & 4096 /* SymbolFlags.Namespace */) {
208
217
  const links = getSymbolLinks(getMergedSymbol(ref));
209
218
  const type = links.type;
210
- const decApp = checkDecorator(type, decNode, undefined);
219
+ const decApp = checkDecoratorApplication(type, decNode, undefined);
211
220
  if (decApp) {
212
221
  type.decorators.push(decApp);
213
222
  applyDecoratorToType(program, decApp, type);
214
223
  }
215
224
  }
216
- else if (args.length > 0 || ref.flags & 16777216 /* SymbolFlags.LateBound */) {
225
+ else if (args.length > 0 || ref.flags & 67108864 /* SymbolFlags.LateBound */) {
217
226
  reportCheckerDiagnostic(createDiagnostic({
218
227
  code: "augment-decorator-target",
219
228
  messageId: "noInstance",
@@ -313,9 +322,259 @@ export function createChecker(program) {
313
322
  return checkOperation(node, mapper, containerType);
314
323
  case SyntaxKind.UnionVariant:
315
324
  return checkUnionVariant(node, mapper);
325
+ case SyntaxKind.ScalarConstructor:
326
+ return checkScalarConstructor(node, mapper, containerType);
316
327
  }
317
328
  }
318
329
  function getTypeForNode(node, mapper) {
330
+ const entity = checkNode(node, mapper);
331
+ if (entity === null) {
332
+ return errorType;
333
+ }
334
+ if (entity.entityKind === "Indeterminate") {
335
+ return entity.type;
336
+ }
337
+ if (isValue(entity)) {
338
+ reportCheckerDiagnostic(createDiagnostic({
339
+ code: "value-in-type",
340
+ target: node,
341
+ }));
342
+ return errorType;
343
+ }
344
+ if (entity.kind === "TemplateParameter") {
345
+ if (entity.constraint?.valueType) {
346
+ // means this template constraint will accept values
347
+ reportCheckerDiagnostic(createDiagnostic({
348
+ code: "value-in-type",
349
+ messageId: "referenceTemplate",
350
+ target: node,
351
+ }));
352
+ }
353
+ }
354
+ return entity;
355
+ }
356
+ function getValueForNode(node, mapper, constraint, options = {}) {
357
+ const initial = checkNode(node, mapper, constraint);
358
+ if (initial === null) {
359
+ return null;
360
+ }
361
+ let entity;
362
+ if (initial.entityKind === "Indeterminate") {
363
+ entity = getValueFromIndeterminate(initial.type, constraint, node);
364
+ }
365
+ else {
366
+ entity = initial;
367
+ }
368
+ if (options.legacyTupleAndModelCast && entity !== null && isType(entity)) {
369
+ entity = legacy_tryTypeToValueCast(entity, constraint, node);
370
+ }
371
+ if (entity === null) {
372
+ return null;
373
+ }
374
+ if (isValue(entity)) {
375
+ return constraint ? inferScalarsFromConstraints(entity, constraint.type) : entity;
376
+ }
377
+ reportExpectedValue(node, entity);
378
+ return null;
379
+ }
380
+ function reportExpectedValue(target, type) {
381
+ if (type.kind === "Model" && type.name === "" && target.kind === SyntaxKind.ModelExpression) {
382
+ reportCheckerDiagnostic(createDiagnostic({
383
+ code: "expect-value",
384
+ messageId: "model",
385
+ format: { name: getTypeName(type) },
386
+ codefixes: [createModelToObjectValueCodeFix(target)],
387
+ target,
388
+ }));
389
+ }
390
+ else if (type.kind === "Tuple" && target.kind === SyntaxKind.TupleExpression) {
391
+ reportCheckerDiagnostic(createDiagnostic({
392
+ code: "expect-value",
393
+ messageId: "tuple",
394
+ format: { name: getTypeName(type) },
395
+ codefixes: [createTupleToArrayValueCodeFix(target)],
396
+ target,
397
+ }));
398
+ }
399
+ else {
400
+ reportCheckerDiagnostic(createDiagnostic({
401
+ code: "expect-value",
402
+ format: { name: getTypeName(type) },
403
+ target,
404
+ }));
405
+ }
406
+ }
407
+ /** In certain context for types that can also be value if the constraint allows it we try to use it as a value instead of a type. */
408
+ function getValueFromIndeterminate(type, constraint, node) {
409
+ switch (type.kind) {
410
+ case "String":
411
+ case "StringTemplate":
412
+ return checkStringValue(type, constraint, node);
413
+ case "Number":
414
+ return checkNumericValue(type, constraint, node);
415
+ case "Boolean":
416
+ return checkBooleanValue(type, constraint, node);
417
+ case "EnumMember":
418
+ return checkEnumValue(type, constraint, node);
419
+ case "UnionVariant":
420
+ return getValueFromIndeterminate(type.type, constraint, node);
421
+ case "Intrinsic":
422
+ switch (type.name) {
423
+ case "null":
424
+ return checkNullValue(type, constraint, node);
425
+ }
426
+ return type;
427
+ default:
428
+ return type;
429
+ }
430
+ }
431
+ function legacy_tryTypeToValueCast(type, constraint, node) {
432
+ switch (type.kind) {
433
+ case "Tuple":
434
+ return legacy_tryUsingTupleAsArrayValue(type, constraint?.type, node);
435
+ case "Model":
436
+ return legacy_tryUsingModelAsObjectValue(type, constraint?.type, node);
437
+ default:
438
+ return type;
439
+ }
440
+ }
441
+ // Legacy behavior to smooth transition to object values.
442
+ function legacy_tryUsingModelAsObjectValue(model, type, node) {
443
+ if (model.node?.kind !== SyntaxKind.ModelExpression) {
444
+ return model; // we only want to convert model expressions
445
+ }
446
+ reportCheckerDiagnostic(createDiagnostic({
447
+ code: "deprecated",
448
+ codefixes: [createModelToObjectValueCodeFix(model.node)],
449
+ format: {
450
+ message: "Using a model as a value is deprecated. Use an object value instead(with #{}).",
451
+ },
452
+ target: model.node,
453
+ }));
454
+ const value = {
455
+ entityKind: "Value",
456
+ valueKind: "ObjectValue",
457
+ type: type ?? model,
458
+ node: model.node,
459
+ properties: new Map(),
460
+ };
461
+ for (const prop of model.properties.values()) {
462
+ let propValue = getValueFromIndeterminate(prop.type, { kind: "assignment", type: prop.type }, node);
463
+ if (propValue !== null && isType(propValue)) {
464
+ propValue = legacy_tryTypeToValueCast(propValue, { kind: "assignment", type: prop.type }, node);
465
+ }
466
+ if (propValue == null) {
467
+ return null;
468
+ }
469
+ else if (!isValue(propValue)) {
470
+ return model;
471
+ }
472
+ value.properties.set(prop.name, {
473
+ name: prop.name,
474
+ value: propValue,
475
+ node: prop.node,
476
+ });
477
+ }
478
+ if (type !== undefined && !checkTypeAssignable(model, type, node)) {
479
+ return null;
480
+ }
481
+ return value;
482
+ }
483
+ // Legacy behavior to smooth transition to array values.
484
+ function legacy_tryUsingTupleAsArrayValue(tuple, type, node) {
485
+ if (tuple.node.kind !== SyntaxKind.TupleExpression) {
486
+ return tuple; // we won't convert dynamic tuples to array values
487
+ }
488
+ reportCheckerDiagnostic(createDiagnostic({
489
+ code: "deprecated",
490
+ codefixes: [createTupleToArrayValueCodeFix(tuple.node)],
491
+ format: {
492
+ message: "Using a tuple as a value is deprecated. Use an array value instead(with #[]).",
493
+ },
494
+ target: tuple.node,
495
+ }));
496
+ const values = [];
497
+ for (const [index, item] of tuple.values.entries()) {
498
+ const itemType = type?.kind === "Model" && isArrayModelType(program, type)
499
+ ? type.indexer.value
500
+ : type?.kind === "Tuple"
501
+ ? type.values[index]
502
+ : undefined;
503
+ let value = getValueFromIndeterminate(item, itemType && { kind: "assignment", type: itemType }, node);
504
+ if (value !== null && isType(value)) {
505
+ value = legacy_tryTypeToValueCast(value, itemType && { kind: "assignment", type: itemType }, node);
506
+ }
507
+ if (value === null) {
508
+ return null;
509
+ }
510
+ else if (!isValue(value)) {
511
+ return tuple;
512
+ }
513
+ values.push(value);
514
+ }
515
+ if (type !== undefined && !checkTypeAssignable(tuple, type, node)) {
516
+ return null;
517
+ }
518
+ return {
519
+ entityKind: "Value",
520
+ valueKind: "ArrayValue",
521
+ type: type ?? tuple,
522
+ node: tuple.node,
523
+ values,
524
+ };
525
+ }
526
+ /**
527
+ * Gets a type or value depending on the node and current constraint.
528
+ * For nodes that can be both type or values(e.g. string), the value will be returned if the constraint expect a value of that type even if the constrain also allows the type.
529
+ * This means that if the constraint is `string | valueof string` passing `"abc"` will send the value `"abc"` and not the type `"abc"`.
530
+ */
531
+ function getTypeOrValueForNode(node, mapper, constraint) {
532
+ const valueConstraint = extractValueOfConstraints(constraint);
533
+ const entity = checkNode(node, mapper, valueConstraint);
534
+ if (entity === null) {
535
+ return entity;
536
+ }
537
+ else if (isType(entity)) {
538
+ if (valueConstraint) {
539
+ return legacy_tryTypeToValueCast(entity, valueConstraint, node);
540
+ }
541
+ else {
542
+ return entity;
543
+ }
544
+ }
545
+ else if (isValue(entity)) {
546
+ return entity;
547
+ }
548
+ compilerAssert(entity.entityKind === "Indeterminate", "Expected indeterminate entity");
549
+ if (valueConstraint) {
550
+ const valueDiagnostics = [];
551
+ const oldDiagnosticHook = onCheckerDiagnostic;
552
+ onCheckerDiagnostic = (x) => valueDiagnostics.push(x);
553
+ const result = getValueFromIndeterminate(entity.type, valueConstraint, node);
554
+ onCheckerDiagnostic = oldDiagnosticHook;
555
+ if (result) {
556
+ // If there were diagnostic reported but we still got a value this means that the value might be invalid.
557
+ reportCheckerDiagnostics(valueDiagnostics);
558
+ return result;
559
+ }
560
+ }
561
+ return entity.type;
562
+ }
563
+ /** Extact the type constraint a value should match. */
564
+ function extractValueOfConstraints(constraint) {
565
+ if (constraint?.constraint.valueType) {
566
+ return { kind: constraint.kind, type: constraint.constraint.valueType };
567
+ }
568
+ else {
569
+ return undefined;
570
+ }
571
+ }
572
+ /**
573
+ * Gets a type, value or indeterminate depending on the node and current constraint.
574
+ * For nodes that can be both type or values(e.g. string literals), an indeterminate entity will be returned.
575
+ * It is the job of of the consumer to decide if it should be a type or a value depending on the context.
576
+ */
577
+ function checkNode(node, mapper, valueConstraint) {
319
578
  switch (node.kind) {
320
579
  case SyntaxKind.ModelExpression:
321
580
  return checkModel(node, mapper);
@@ -346,10 +605,10 @@ export function createChecker(program) {
346
605
  return checkNumericLiteral(node);
347
606
  case SyntaxKind.BooleanLiteral:
348
607
  return checkBooleanLiteral(node);
349
- case SyntaxKind.TupleExpression:
350
- return checkTupleExpression(node, mapper);
351
608
  case SyntaxKind.StringLiteral:
352
609
  return checkStringLiteral(node);
610
+ case SyntaxKind.TupleExpression:
611
+ return checkTupleExpression(node, mapper);
353
612
  case SyntaxKind.StringTemplateExpression:
354
613
  return checkStringTemplateExpresion(node, mapper);
355
614
  case SyntaxKind.ArrayExpression:
@@ -363,7 +622,7 @@ export function createChecker(program) {
363
622
  case SyntaxKind.FunctionDeclarationStatement:
364
623
  return checkFunctionDeclaration(node, mapper);
365
624
  case SyntaxKind.TypeReference:
366
- return checkTypeReference(node, mapper);
625
+ return checkTypeOrValueReference(node, mapper);
367
626
  case SyntaxKind.TemplateArgument:
368
627
  return checkTemplateArgument(node, mapper);
369
628
  case SyntaxKind.TemplateParameterDeclaration:
@@ -376,12 +635,19 @@ export function createChecker(program) {
376
635
  return neverType;
377
636
  case SyntaxKind.UnknownKeyword:
378
637
  return unknownType;
638
+ case SyntaxKind.ObjectLiteral:
639
+ return checkObjectValue(node, mapper, valueConstraint);
640
+ case SyntaxKind.ArrayLiteral:
641
+ return checkArrayValue(node, mapper, valueConstraint);
642
+ case SyntaxKind.ConstStatement:
643
+ return checkConst(node);
644
+ case SyntaxKind.CallExpression:
645
+ return checkCallExpression(node, mapper);
646
+ case SyntaxKind.TypeOfExpression:
647
+ return checkTypeOfExpression(node, mapper);
648
+ default:
649
+ return errorType;
379
650
  }
380
- // we don't emit an error here as we blindly call this function
381
- // with any node type, but some nodes don't produce a type
382
- // (e.g. imports). errorType should result in an error if it
383
- // bubbles out somewhere its not supposed to be.
384
- return errorType;
385
651
  }
386
652
  /**
387
653
  * Return a fully qualified id of node
@@ -440,7 +706,7 @@ export function createChecker(program) {
440
706
  });
441
707
  if (node.constraint) {
442
708
  pendingResolutions.start(getNodeSymId(node), ResolutionKind.Constraint);
443
- type.constraint = getTypeOrValueTypeForNode(node.constraint);
709
+ type.constraint = getParamConstraintEntityForNode(node.constraint);
444
710
  pendingResolutions.finish(getNodeSymId(node), ResolutionKind.Constraint);
445
711
  }
446
712
  if (node.default) {
@@ -453,23 +719,24 @@ export function createChecker(program) {
453
719
  if (declaredType.default === undefined) {
454
720
  return undefined;
455
721
  }
456
- if (isErrorType(declaredType.default)) {
722
+ if ((isType(declaredType.default) && isErrorType(declaredType.default)) ||
723
+ declaredType.default === null) {
457
724
  return declaredType.default;
458
725
  }
459
- return getTypeForNode(node.default, mapper);
726
+ return checkNode(node.default, mapper);
460
727
  }
461
728
  function checkTemplateParameterDefault(nodeDefault, templateParameters, index, constraint) {
462
729
  function visit(node) {
463
- const type = getTypeForNode(node);
730
+ const entity = checkNode(node);
464
731
  let hasError = false;
465
- if (type.kind === "TemplateParameter") {
732
+ if (entity !== null && "kind" in entity && entity.kind === "TemplateParameter") {
466
733
  for (let i = index; i < templateParameters.length; i++) {
467
- if (type.node.symbol === templateParameters[i].symbol) {
734
+ if (entity.node.symbol === templateParameters[i].symbol) {
468
735
  reportCheckerDiagnostic(createDiagnostic({ code: "invalid-template-default", target: node }));
469
736
  return undefined;
470
737
  }
471
738
  }
472
- return type;
739
+ return entity;
473
740
  }
474
741
  visitChildren(node, (x) => {
475
742
  const visited = visit(x);
@@ -477,10 +744,10 @@ export function createChecker(program) {
477
744
  hasError = true;
478
745
  }
479
746
  });
480
- return hasError ? undefined : type;
747
+ return hasError ? undefined : entity;
481
748
  }
482
749
  const type = visit(nodeDefault) ?? errorType;
483
- if (!isErrorType(type) && constraint) {
750
+ if (!("kind" in type && isErrorType(type)) && constraint) {
484
751
  checkTypeAssignable(type, constraint, nodeDefault);
485
752
  }
486
753
  return type;
@@ -500,8 +767,22 @@ export function createChecker(program) {
500
767
  const type = checkTypeReferenceSymbol(sym, node, mapper, instantiateTemplate);
501
768
  return type;
502
769
  }
770
+ /**
771
+ * Check and resolve a type for the given type reference node.
772
+ * @param node Node.
773
+ * @param mapper Type mapper for template instantiation context.
774
+ * @param instantiateTemplate If templated type should be instantiated if they haven't yet.
775
+ * @returns Resolved type.
776
+ */
777
+ function checkTypeOrValueReference(node, mapper, instantiateTemplate = true) {
778
+ const sym = resolveTypeReferenceSym(node, mapper);
779
+ if (!sym) {
780
+ return errorType;
781
+ }
782
+ return checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplate) ?? errorType;
783
+ }
503
784
  function checkTemplateArgument(node, mapper) {
504
- return getTypeForNode(node.argument, mapper);
785
+ return checkNode(node.argument, mapper);
505
786
  }
506
787
  function resolveTypeReference(node) {
507
788
  const oldDiagnosticHook = onCheckerDiagnostic;
@@ -567,8 +848,8 @@ export function createChecker(program) {
567
848
  function checkTemplateInstantiationArgs(node, args, decls, mapper) {
568
849
  const params = new Map();
569
850
  const positional = [];
570
- const initMap = new Map(decls.map(function (decl) {
571
- const declaredType = getTypeForNode(decl);
851
+ const initMap = new Map(decls.map((decl) => {
852
+ const declaredType = checkTemplateParameterDeclaration(decl, undefined);
572
853
  positional.push(declaredType);
573
854
  params.set(decl.id.sv, declaredType);
574
855
  return [
@@ -582,7 +863,7 @@ export function createChecker(program) {
582
863
  let named = false;
583
864
  for (const [arg, idx] of args.map((v, i) => [v, i])) {
584
865
  function deferredCheck() {
585
- return [arg, getTypeForNode(arg.argument, mapper)];
866
+ return [arg, checkNode(arg.argument, mapper)];
586
867
  }
587
868
  if (arg.name) {
588
869
  named = true;
@@ -657,18 +938,30 @@ export function createChecker(program) {
657
938
  target: node,
658
939
  }));
659
940
  // TODO-TIM check if we expose this below
660
- commit(param, param.constraint?.kind === "Value" ? unknownType : param.constraint ?? unknownType);
941
+ commit(param, param.constraint?.type ?? unknownType);
661
942
  }
662
943
  continue;
663
944
  }
664
945
  const [argNode, type] = init();
946
+ if (type === null) {
947
+ commit(param, unknownType);
948
+ continue;
949
+ }
665
950
  if (param.constraint) {
666
- const constraint = param.constraint.kind === "TemplateParameter"
667
- ? finalMap.get(param.constraint)
951
+ const constraint = param.constraint.type?.kind === "TemplateParameter"
952
+ ? finalMap.get(param.constraint.type)
668
953
  : param.constraint;
669
- if (!checkTypeAssignable(type, constraint, argNode)) {
670
- // TODO-TIM check if we expose this below
671
- const effectiveType = param.constraint?.kind === "Value" ? unknownType : param.constraint;
954
+ if (isType(type) && param.constraint?.valueType) {
955
+ const converted = legacy_tryTypeToValueCast(type, { kind: "argument", type: param.constraint.valueType }, argNode);
956
+ // If we manage to convert it means this might be convertable so we skip type checking.
957
+ // However we still return the original entity
958
+ if (converted !== type) {
959
+ commit(param, type);
960
+ continue;
961
+ }
962
+ }
963
+ if (param.constraint && !checkArgumentAssignable(type, constraint, argNode)) {
964
+ const effectiveType = param.constraint.type ?? unknownType;
672
965
  commit(param, effectiveType);
673
966
  continue;
674
967
  }
@@ -679,6 +972,15 @@ export function createChecker(program) {
679
972
  commit(param, unknownType);
680
973
  continue;
681
974
  }
975
+ else if (isValue(type)) {
976
+ reportCheckerDiagnostic(createDiagnostic({
977
+ code: "value-in-type",
978
+ messageId: "noTemplateConstraint",
979
+ target: argNode,
980
+ }));
981
+ commit(param, unknownType);
982
+ continue;
983
+ }
682
984
  commit(param, type);
683
985
  }
684
986
  return finalMap;
@@ -692,6 +994,20 @@ export function createChecker(program) {
692
994
  * @returns resolved type.
693
995
  */
694
996
  function checkTypeReferenceSymbol(sym, node, mapper, instantiateTemplates = true) {
997
+ const result = checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplates);
998
+ if (result === null || isValue(result)) {
999
+ reportCheckerDiagnostic(createDiagnostic({ code: "value-in-type", target: node }));
1000
+ return errorType;
1001
+ }
1002
+ if (result.entityKind === "Indeterminate") {
1003
+ return result.type;
1004
+ }
1005
+ return result;
1006
+ }
1007
+ function checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplates = true) {
1008
+ if (sym.flags & 16777216 /* SymbolFlags.Const */) {
1009
+ return getValueForNode(sym.declarations[0], mapper);
1010
+ }
695
1011
  if (sym.flags & 16384 /* SymbolFlags.Decorator */) {
696
1012
  reportCheckerDiagnostic(createDiagnostic({ code: "invalid-type-ref", messageId: "decorator", target: sym }));
697
1013
  return errorType;
@@ -719,14 +1035,14 @@ export function createChecker(program) {
719
1035
  target: node,
720
1036
  }));
721
1037
  }
722
- if (sym.flags & 16777216 /* SymbolFlags.LateBound */) {
1038
+ if (sym.flags & 67108864 /* SymbolFlags.LateBound */) {
723
1039
  compilerAssert(sym.type, "Expected late bound symbol to have type");
724
1040
  return sym.type;
725
1041
  }
726
1042
  else if (symbolLinks.declaredType) {
727
1043
  baseType = symbolLinks.declaredType;
728
1044
  }
729
- else if (sym.flags & 1348 /* SymbolFlags.Member */) {
1045
+ else if (sym.flags & 33555780 /* SymbolFlags.Member */) {
730
1046
  baseType = checkMemberSym(sym, mapper);
731
1047
  }
732
1048
  else {
@@ -749,12 +1065,13 @@ export function createChecker(program) {
749
1065
  target: node,
750
1066
  }));
751
1067
  }
752
- if (sym.flags & 16777216 /* SymbolFlags.LateBound */) {
753
- compilerAssert(sym.type, "Expected late bound symbol to have type");
1068
+ if (sym.flags & 67108864 /* SymbolFlags.LateBound */) {
1069
+ compilerAssert(sym.type, `Expected late bound symbol to have type`);
754
1070
  return sym.type;
755
1071
  }
756
1072
  else if (sym.flags & 32768 /* SymbolFlags.TemplateParameter */) {
757
- baseType = checkTemplateParameterDeclaration(sym.declarations[0], mapper);
1073
+ const mapped = checkTemplateParameterDeclaration(sym.declarations[0], mapper);
1074
+ baseType = mapped;
758
1075
  }
759
1076
  else if (symbolLinks.type) {
760
1077
  // Have a cached type for non-declarations
@@ -764,7 +1081,7 @@ export function createChecker(program) {
764
1081
  baseType = symbolLinks.declaredType;
765
1082
  }
766
1083
  else {
767
- if (sym.flags & 1348 /* SymbolFlags.Member */) {
1084
+ if (sym.flags & 33555780 /* SymbolFlags.Member */) {
768
1085
  baseType = checkMemberSym(sym, mapper);
769
1086
  }
770
1087
  else {
@@ -783,6 +1100,12 @@ export function createChecker(program) {
783
1100
  checkDeprecated(baseType, declarationNode, node);
784
1101
  }
785
1102
  }
1103
+ // Elements that could be used as type or values depending on the context
1104
+ if (baseType.kind === "EnumMember" ||
1105
+ baseType.kind === "UnionVariant" ||
1106
+ isNullType(baseType)) {
1107
+ return createIndeterminateEntity(baseType);
1108
+ }
786
1109
  return baseType;
787
1110
  }
788
1111
  /**
@@ -797,11 +1120,11 @@ export function createChecker(program) {
797
1120
  if (symbolLinks.declaredType) {
798
1121
  return symbolLinks.declaredType;
799
1122
  }
800
- if (sym.flags & 16777216 /* SymbolFlags.LateBound */) {
1123
+ if (sym.flags & 67108864 /* SymbolFlags.LateBound */) {
801
1124
  compilerAssert(sym.type, "Expected late bound symbol to have type");
802
1125
  return sym.type;
803
1126
  }
804
- if (sym.flags & 1348 /* SymbolFlags.Member */) {
1127
+ if (sym.flags & 33555780 /* SymbolFlags.Member */) {
805
1128
  return checkMemberSym(sym, mapper);
806
1129
  }
807
1130
  else {
@@ -816,7 +1139,7 @@ export function createChecker(program) {
816
1139
  * @returns The declared type for the given node.
817
1140
  */
818
1141
  function checkDeclaredType(sym, node, mapper) {
819
- return sym.flags & 2 /* SymbolFlags.Model */
1142
+ const type = sym.flags & 2 /* SymbolFlags.Model */
820
1143
  ? checkModelStatement(node, mapper)
821
1144
  : sym.flags & 8 /* SymbolFlags.Scalar */
822
1145
  ? checkScalar(node, mapper)
@@ -827,6 +1150,7 @@ export function createChecker(program) {
827
1150
  : sym.flags & 16 /* SymbolFlags.Operation */
828
1151
  ? checkOperation(node, mapper)
829
1152
  : checkUnion(node, mapper);
1153
+ return type;
830
1154
  }
831
1155
  function getOrInstantiateTemplate(templateNode, params, args, parentMapper, instantiateTempalates = true) {
832
1156
  const symbolLinks = templateNode.kind === SyntaxKind.OperationStatement &&
@@ -874,6 +1198,57 @@ export function createChecker(program) {
874
1198
  }
875
1199
  return type;
876
1200
  }
1201
+ /** Check a union expresion used in a parameter constraint, those allow the use of `valueof` as a variant. */
1202
+ function checkMixedParameterConstraintUnion(node, mapper) {
1203
+ const values = [];
1204
+ const types = [];
1205
+ for (const option of node.options) {
1206
+ const [kind, type] = getTypeOrValueOfTypeForNode(option, mapper);
1207
+ if (kind === "value") {
1208
+ values.push(type);
1209
+ }
1210
+ else {
1211
+ types.push(type);
1212
+ }
1213
+ }
1214
+ return {
1215
+ entityKind: "MixedParameterConstraint",
1216
+ node,
1217
+ valueType: values.length === 0
1218
+ ? undefined
1219
+ : values.length === 1
1220
+ ? values[0]
1221
+ : createConstraintUnion(node, values),
1222
+ type: types.length === 0
1223
+ ? undefined
1224
+ : types.length === 1
1225
+ ? types[0]
1226
+ : createConstraintUnion(node, types),
1227
+ };
1228
+ }
1229
+ function createConstraintUnion(node, options) {
1230
+ const variants = createRekeyableMap();
1231
+ const union = createAndFinishType({
1232
+ kind: "Union",
1233
+ node,
1234
+ options,
1235
+ decorators: [],
1236
+ variants,
1237
+ expression: true,
1238
+ });
1239
+ for (const option of options) {
1240
+ const name = Symbol("indexer-union-variant");
1241
+ variants.set(name, createAndFinishType({
1242
+ kind: "UnionVariant",
1243
+ node: undefined,
1244
+ type: option,
1245
+ name,
1246
+ union,
1247
+ decorators: [],
1248
+ }));
1249
+ }
1250
+ return union;
1251
+ }
877
1252
  function checkUnionExpression(node, mapper) {
878
1253
  const unionType = createAndFinishType({
879
1254
  kind: "Union",
@@ -910,13 +1285,6 @@ export function createChecker(program) {
910
1285
  }
911
1286
  return unionType;
912
1287
  }
913
- function checkValueOfExpression(node, mapper) {
914
- const target = getTypeForNode(node.target, mapper);
915
- return {
916
- kind: "Value",
917
- target,
918
- };
919
- }
920
1288
  /**
921
1289
  * Intersection produces a model type from the properties of its operands.
922
1290
  * So this doesn't work if we don't have a known set of properties (e.g.
@@ -948,14 +1316,43 @@ export function createChecker(program) {
948
1316
  name: `@${name}`,
949
1317
  namespace,
950
1318
  node,
951
- target: checkFunctionParameter(node.target, mapper),
952
- parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper)),
1319
+ target: checkFunctionParameter(node.target, mapper, true),
1320
+ parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, true)),
953
1321
  implementation: implementation ?? (() => { }),
954
1322
  });
955
1323
  namespace.decoratorDeclarations.set(name, decoratorType);
956
1324
  linkType(links, decoratorType, mapper);
1325
+ checkDecoratorLegacyMarshalling(decoratorType);
957
1326
  return decoratorType;
958
1327
  }
1328
+ function checkDecoratorLegacyMarshalling(decorator) {
1329
+ const marshalling = resolveDecoratorArgMarshalling(decorator);
1330
+ function reportDeprecatedLegacyMarshalling(param, message) {
1331
+ reportDeprecated(program, [
1332
+ `Parameter ${param.name} of decorator ${decorator.name} is using legacy marshalling but is accepting ${message}.`,
1333
+ `This will change in the future.`,
1334
+ 'Add `export const $flags = {decoratorArgMarshalling: "new"}}` to your library to opt-in to the new marshalling behavior.',
1335
+ ].join("\n"), param.node);
1336
+ }
1337
+ if (marshalling === "legacy") {
1338
+ for (const param of decorator.parameters) {
1339
+ if (param.type.valueType) {
1340
+ if (ignoreDiagnostics(isTypeAssignableTo(nullType, param.type.valueType, param.type))) {
1341
+ reportDeprecatedLegacyMarshalling(param, "null as a type");
1342
+ }
1343
+ else if (param.type.valueType.kind === "Enum" ||
1344
+ param.type.valueType.kind === "EnumMember" ||
1345
+ (isReflectionType(param.type.valueType) && param.type.valueType.name === "EnumMember")) {
1346
+ reportDeprecatedLegacyMarshalling(param, "enum members");
1347
+ }
1348
+ else if (ignoreDiagnostics(isTypeAssignableTo(param.type.valueType, getStdType("numeric"), param.type.valueType)) &&
1349
+ !canNumericConstraintBeJsNumber(param.type.valueType)) {
1350
+ reportDeprecatedLegacyMarshalling(param, "a numeric type that is not representable as a JS Number");
1351
+ }
1352
+ }
1353
+ }
1354
+ }
1355
+ }
959
1356
  function checkFunctionDeclaration(node, mapper) {
960
1357
  const symbol = getMergedSymbol(node.symbol);
961
1358
  const links = getSymbolLinks(symbol);
@@ -978,7 +1375,7 @@ export function createChecker(program) {
978
1375
  name,
979
1376
  namespace,
980
1377
  node,
981
- parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper)),
1378
+ parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, true)),
982
1379
  returnType: node.returnType ? getTypeForNode(node.returnType, mapper) : unknownType,
983
1380
  implementation: implementation ?? (() => { }),
984
1381
  });
@@ -986,7 +1383,7 @@ export function createChecker(program) {
986
1383
  linkType(links, functionType, mapper);
987
1384
  return functionType;
988
1385
  }
989
- function checkFunctionParameter(node, mapper) {
1386
+ function checkFunctionParameter(node, mapper, mixed) {
990
1387
  const links = getSymbolLinks(node.symbol);
991
1388
  if (links.declaredType) {
992
1389
  return links.declaredType;
@@ -998,24 +1395,62 @@ export function createChecker(program) {
998
1395
  node.type.target.kind === SyntaxKind.ArrayExpression))) {
999
1396
  reportCheckerDiagnostic(createDiagnostic({ code: "rest-parameter-array", target: node.type }));
1000
1397
  }
1001
- const type = node.type ? getTypeOrValueTypeForNode(node.type) : unknownType;
1002
- const parameterType = createType({
1398
+ const base = {
1003
1399
  kind: "FunctionParameter",
1004
1400
  node,
1005
1401
  name: node.id.sv,
1006
1402
  optional: node.optional,
1007
1403
  rest: node.rest,
1008
- type,
1009
1404
  implementation: node.symbol.value,
1010
- });
1405
+ };
1406
+ let parameterType;
1407
+ if (mixed) {
1408
+ const type = node.type
1409
+ ? getParamConstraintEntityForNode(node.type)
1410
+ : ({
1411
+ entityKind: "MixedParameterConstraint",
1412
+ type: unknownType,
1413
+ });
1414
+ parameterType = createType({
1415
+ ...base,
1416
+ type,
1417
+ mixed: true,
1418
+ implementation: node.symbol.value,
1419
+ });
1420
+ }
1421
+ else {
1422
+ parameterType = createType({
1423
+ ...base,
1424
+ mixed: false,
1425
+ type: node.type ? getTypeForNode(node.type) : unknownType,
1426
+ implementation: node.symbol.value,
1427
+ });
1428
+ }
1011
1429
  linkType(links, parameterType, mapper);
1012
1430
  return parameterType;
1013
1431
  }
1014
- function getTypeOrValueTypeForNode(node, mapper) {
1015
- if (node.kind === SyntaxKind.ValueOfExpression) {
1016
- return checkValueOfExpression(node, mapper);
1432
+ function getTypeOrValueOfTypeForNode(node, mapper) {
1433
+ switch (node.kind) {
1434
+ case SyntaxKind.ValueOfExpression:
1435
+ const target = getTypeForNode(node.target, mapper);
1436
+ return ["value", target];
1437
+ default:
1438
+ return ["type", getTypeForNode(node, mapper)];
1439
+ }
1440
+ }
1441
+ function getParamConstraintEntityForNode(node, mapper) {
1442
+ switch (node.kind) {
1443
+ case SyntaxKind.UnionExpression:
1444
+ return checkMixedParameterConstraintUnion(node, mapper);
1445
+ default:
1446
+ const [kind, entity] = getTypeOrValueOfTypeForNode(node, mapper);
1447
+ return {
1448
+ entityKind: "MixedParameterConstraint",
1449
+ node: node,
1450
+ type: kind === "value" ? undefined : entity,
1451
+ valueType: kind === "value" ? entity : undefined,
1452
+ };
1017
1453
  }
1018
- return getTypeForNode(node, mapper);
1019
1454
  }
1020
1455
  function mergeModelTypes(node, options, mapper) {
1021
1456
  const properties = createRekeyableMap();
@@ -1104,7 +1539,7 @@ export function createChecker(program) {
1104
1539
  }
1105
1540
  if (node.kind === SyntaxKind.NamespaceStatement) {
1106
1541
  if (isArray(node.statements)) {
1107
- node.statements.forEach((x) => getTypeForNode(x));
1542
+ node.statements.forEach((x) => checkNode(x));
1108
1543
  }
1109
1544
  else if (node.statements) {
1110
1545
  const subNs = checkNamespace(node.statements);
@@ -1397,7 +1832,10 @@ export function createChecker(program) {
1397
1832
  break;
1398
1833
  }
1399
1834
  compilerAssert(node.parent, "Parent expected.");
1400
- const containerType = getTypeForNode(node.parent, mapper);
1835
+ const containerType = getTypeOrValueForNode(node.parent, mapper);
1836
+ if (containerType === null || isValue(containerType)) {
1837
+ return undefined;
1838
+ }
1401
1839
  if (isAnonymous(containerType)) {
1402
1840
  return undefined; // member of anonymous type cannot be referenced.
1403
1841
  }
@@ -1746,9 +2184,9 @@ export function createChecker(program) {
1746
2184
  }));
1747
2185
  return undefined;
1748
2186
  }
1749
- else if (base.flags & 674 /* SymbolFlags.MemberContainer */) {
2187
+ else if (base.flags & 682 /* SymbolFlags.MemberContainer */) {
1750
2188
  if (options.checkTemplateTypes && isTemplatedNode(base.declarations[0])) {
1751
- const type = base.flags & 16777216 /* SymbolFlags.LateBound */
2189
+ const type = base.flags & 67108864 /* SymbolFlags.LateBound */
1752
2190
  ? base.type
1753
2191
  : getTypeForNode(base.declarations[0], mapper);
1754
2192
  if (isTemplateInstance(type)) {
@@ -1863,17 +2301,112 @@ export function createChecker(program) {
1863
2301
  }
1864
2302
  }
1865
2303
  function checkStringTemplateExpresion(node, mapper) {
1866
- const spans = [createTemplateSpanLiteral(node.head)];
1867
- for (const span of node.spans) {
1868
- spans.push(createTemplateSpanValue(span.expression, mapper));
1869
- spans.push(createTemplateSpanLiteral(span.literal));
2304
+ let hasType = false;
2305
+ let hasValue = false;
2306
+ const spanTypeOrValues = node.spans.map((span) => [span, checkNode(span.expression, mapper)]);
2307
+ for (const [_, typeOrValue] of spanTypeOrValues) {
2308
+ if (typeOrValue !== null) {
2309
+ if (isValue(typeOrValue)) {
2310
+ hasValue = true;
2311
+ }
2312
+ else if ("kind" in typeOrValue && typeOrValue.kind === "TemplateParameter") {
2313
+ if (typeOrValue.constraint) {
2314
+ if (typeOrValue.constraint.valueType) {
2315
+ hasValue = true;
2316
+ }
2317
+ if (typeOrValue.constraint.type) {
2318
+ hasType = true;
2319
+ }
2320
+ }
2321
+ else {
2322
+ hasType = true;
2323
+ }
2324
+ }
2325
+ else {
2326
+ hasType = true;
2327
+ }
2328
+ }
2329
+ }
2330
+ if (hasType && hasValue) {
2331
+ reportCheckerDiagnostic(createDiagnostic({
2332
+ code: "mixed-string-template",
2333
+ target: node,
2334
+ }));
2335
+ return null;
2336
+ }
2337
+ if (hasValue) {
2338
+ let str = node.head.value;
2339
+ for (const [span, typeOrValue] of spanTypeOrValues) {
2340
+ if (typeOrValue !== null &&
2341
+ (!("kind" in typeOrValue) || typeOrValue.kind !== "TemplateParameter")) {
2342
+ compilerAssert(typeOrValue !== null && isValue(typeOrValue), "Expected value.");
2343
+ str += stringifyValueForTemplate(typeOrValue);
2344
+ }
2345
+ str += span.literal.value;
2346
+ }
2347
+ return checkStringValue(createLiteralType(str), undefined, node);
2348
+ }
2349
+ else {
2350
+ let hasNonStringElement = false;
2351
+ let stringValue = node.head.value;
2352
+ const spans = [createTemplateSpanLiteral(node.head)];
2353
+ for (const [span, typeOrValue] of spanTypeOrValues) {
2354
+ compilerAssert(typeOrValue !== null && !isValue(typeOrValue), "Expected type.");
2355
+ const type = typeOrValue.entityKind === "Indeterminate" ? typeOrValue.type : typeOrValue;
2356
+ const spanValue = createTemplateSpanValue(span.expression, type);
2357
+ spans.push(spanValue);
2358
+ const spanValueAsString = stringifyTypeForTemplate(type);
2359
+ if (spanValueAsString) {
2360
+ stringValue += spanValueAsString;
2361
+ }
2362
+ else {
2363
+ hasNonStringElement = true;
2364
+ }
2365
+ spans.push(createTemplateSpanLiteral(span.literal));
2366
+ stringValue += span.literal.value;
2367
+ }
2368
+ return createIndeterminateEntity(createType({
2369
+ kind: "StringTemplate",
2370
+ node,
2371
+ spans,
2372
+ stringValue: hasNonStringElement ? undefined : stringValue,
2373
+ }));
2374
+ }
2375
+ }
2376
+ function createIndeterminateEntity(type) {
2377
+ return {
2378
+ entityKind: "Indeterminate",
2379
+ type,
2380
+ };
2381
+ }
2382
+ function stringifyTypeForTemplate(type) {
2383
+ switch (type.kind) {
2384
+ case "String":
2385
+ case "Number":
2386
+ case "Boolean":
2387
+ return String(type.value);
2388
+ case "StringTemplate":
2389
+ if (type.stringValue !== undefined) {
2390
+ return type.stringValue;
2391
+ }
2392
+ return undefined;
2393
+ default:
2394
+ return undefined;
2395
+ }
2396
+ }
2397
+ function stringifyValueForTemplate(value) {
2398
+ switch (value.valueKind) {
2399
+ case "StringValue":
2400
+ case "NumericValue":
2401
+ case "BooleanValue":
2402
+ return value.value.toString();
2403
+ default:
2404
+ reportCheckerDiagnostic(createDiagnostic({
2405
+ code: "non-literal-string-template",
2406
+ target: value,
2407
+ }));
2408
+ return `[${value.valueKind}]`;
1870
2409
  }
1871
- const type = createType({
1872
- kind: "StringTemplate",
1873
- node,
1874
- spans,
1875
- });
1876
- return type;
1877
2410
  }
1878
2411
  function createTemplateSpanLiteral(node) {
1879
2412
  return createType({
@@ -1883,22 +2416,31 @@ export function createChecker(program) {
1883
2416
  type: getLiteralType(node),
1884
2417
  });
1885
2418
  }
1886
- function createTemplateSpanValue(node, mapper) {
2419
+ function createTemplateSpanValue(node, type) {
1887
2420
  return createType({
1888
2421
  kind: "StringTemplateSpan",
1889
2422
  node: node,
1890
2423
  isInterpolated: true,
1891
- type: getTypeForNode(node, mapper),
2424
+ type: type,
1892
2425
  });
1893
2426
  }
1894
2427
  function checkStringLiteral(str) {
1895
- return getLiteralType(str);
2428
+ return {
2429
+ entityKind: "Indeterminate",
2430
+ type: getLiteralType(str),
2431
+ };
1896
2432
  }
1897
2433
  function checkNumericLiteral(num) {
1898
- return getLiteralType(num);
2434
+ return {
2435
+ entityKind: "Indeterminate",
2436
+ type: getLiteralType(num),
2437
+ };
1899
2438
  }
1900
2439
  function checkBooleanLiteral(bool) {
1901
- return getLiteralType(bool);
2440
+ return {
2441
+ entityKind: "Indeterminate",
2442
+ type: getLiteralType(bool),
2443
+ };
1902
2444
  }
1903
2445
  function checkProgram() {
1904
2446
  program.reportDuplicateSymbols(globalNamespaceNode.symbol.exports);
@@ -1947,7 +2489,7 @@ export function createChecker(program) {
1947
2489
  }
1948
2490
  function checkSourceFile(file) {
1949
2491
  for (const statement of file.statements) {
1950
- getTypeForNode(statement, undefined);
2492
+ checkNode(statement, undefined);
1951
2493
  }
1952
2494
  }
1953
2495
  /**
@@ -2056,7 +2598,8 @@ export function createChecker(program) {
2056
2598
  return false;
2057
2599
  }
2058
2600
  // Some of the mapper args are still template parameter so we shouldn't create the type.
2059
- return !mapper.partial && mapper.args.every((t) => t.kind !== "TemplateParameter");
2601
+ return (!mapper.partial &&
2602
+ mapper.args.every((t) => isValue(t) || t.entityKind === "Indeterminate" || t.kind !== "TemplateParameter"));
2060
2603
  }
2061
2604
  function checkModelExpression(node, mapper) {
2062
2605
  const properties = createRekeyableMap();
@@ -2149,6 +2692,414 @@ export function createChecker(program) {
2149
2692
  };
2150
2693
  }
2151
2694
  }
2695
+ function checkObjectValue(node, mapper, constraint) {
2696
+ const properties = checkObjectLiteralProperties(node, mapper);
2697
+ if (properties === null) {
2698
+ return null;
2699
+ }
2700
+ const preciseType = createTypeForObjectValue(node, properties);
2701
+ if (constraint && !checkTypeOfValueMatchConstraint(preciseType, constraint, node)) {
2702
+ return null;
2703
+ }
2704
+ return {
2705
+ entityKind: "Value",
2706
+ valueKind: "ObjectValue",
2707
+ node: node,
2708
+ properties,
2709
+ type: constraint ? constraint.type : preciseType,
2710
+ };
2711
+ }
2712
+ function createTypeForObjectValue(node, properties) {
2713
+ const model = createType({
2714
+ kind: "Model",
2715
+ name: "",
2716
+ node,
2717
+ properties: createRekeyableMap(),
2718
+ decorators: [],
2719
+ derivedModels: [],
2720
+ sourceModels: [],
2721
+ });
2722
+ for (const prop of properties.values()) {
2723
+ model.properties.set(prop.name, createModelPropertyForObjectPropertyDescriptor(prop, model));
2724
+ }
2725
+ return finishType(model);
2726
+ }
2727
+ function createModelPropertyForObjectPropertyDescriptor(prop, parentModel) {
2728
+ return createAndFinishType({
2729
+ kind: "ModelProperty",
2730
+ node: prop.node,
2731
+ model: parentModel,
2732
+ optional: false,
2733
+ name: prop.name,
2734
+ type: prop.value.type,
2735
+ decorators: [],
2736
+ });
2737
+ }
2738
+ function checkObjectLiteralProperties(node, mapper) {
2739
+ const properties = new Map();
2740
+ let hasError = false;
2741
+ for (const prop of node.properties) {
2742
+ if ("id" in prop) {
2743
+ const value = getValueForNode(prop.value, mapper);
2744
+ if (value === null) {
2745
+ hasError = true;
2746
+ }
2747
+ else {
2748
+ properties.set(prop.id.sv, { name: prop.id.sv, value: value, node: prop });
2749
+ }
2750
+ }
2751
+ else {
2752
+ const targetType = checkObjectSpreadProperty(prop.target, mapper);
2753
+ if (targetType) {
2754
+ for (const [name, value] of targetType.properties) {
2755
+ properties.set(name, { ...value });
2756
+ }
2757
+ }
2758
+ }
2759
+ }
2760
+ return hasError ? null : properties;
2761
+ }
2762
+ function checkObjectSpreadProperty(targetNode, mapper) {
2763
+ const value = getValueForNode(targetNode, mapper);
2764
+ if (value === null) {
2765
+ return null;
2766
+ }
2767
+ if (value.valueKind !== "ObjectValue") {
2768
+ reportCheckerDiagnostic(createDiagnostic({ code: "spread-object", target: targetNode }));
2769
+ return null;
2770
+ }
2771
+ return value;
2772
+ }
2773
+ function checkArrayValue(node, mapper, constraint) {
2774
+ let hasError = false;
2775
+ const values = node.values.map((itemNode) => {
2776
+ const value = getValueForNode(itemNode, mapper);
2777
+ if (value === null) {
2778
+ hasError = true;
2779
+ }
2780
+ return value;
2781
+ });
2782
+ if (hasError) {
2783
+ return null;
2784
+ }
2785
+ const preciseType = createTypeForArrayValue(node, values);
2786
+ if (constraint && !checkTypeOfValueMatchConstraint(preciseType, constraint, node)) {
2787
+ return null;
2788
+ }
2789
+ return {
2790
+ entityKind: "Value",
2791
+ valueKind: "ArrayValue",
2792
+ node: node,
2793
+ values: values,
2794
+ type: constraint ? constraint.type : preciseType,
2795
+ };
2796
+ }
2797
+ function createTypeForArrayValue(node, values) {
2798
+ return createAndFinishType({
2799
+ kind: "Tuple",
2800
+ node,
2801
+ values: values.map((x) => x.type),
2802
+ });
2803
+ }
2804
+ function inferScalarForPrimitiveValue(type, literalType) {
2805
+ if (type === undefined) {
2806
+ return undefined;
2807
+ }
2808
+ switch (type.kind) {
2809
+ case "Scalar":
2810
+ if (ignoreDiagnostics(isTypeAssignableTo(literalType, type, literalType))) {
2811
+ return type;
2812
+ }
2813
+ return undefined;
2814
+ case "Union":
2815
+ let found = undefined;
2816
+ for (const variant of type.variants.values()) {
2817
+ const scalar = inferScalarForPrimitiveValue(variant.type, literalType);
2818
+ if (scalar) {
2819
+ if (found) {
2820
+ reportCheckerDiagnostic(createDiagnostic({
2821
+ code: "ambiguous-scalar-type",
2822
+ format: {
2823
+ value: getTypeName(literalType),
2824
+ types: [found, scalar].map((x) => x.name).join(", "),
2825
+ example: found.name,
2826
+ },
2827
+ target: literalType,
2828
+ }));
2829
+ return undefined;
2830
+ }
2831
+ else {
2832
+ found = scalar;
2833
+ }
2834
+ }
2835
+ }
2836
+ return found;
2837
+ default:
2838
+ return undefined;
2839
+ }
2840
+ }
2841
+ function checkStringValue(literalType, constraint, node) {
2842
+ if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
2843
+ return null;
2844
+ }
2845
+ let value;
2846
+ if (literalType.kind === "StringTemplate") {
2847
+ if (literalType.stringValue) {
2848
+ value = literalType.stringValue;
2849
+ }
2850
+ else {
2851
+ reportCheckerDiagnostics(explainStringTemplateNotSerializable(literalType));
2852
+ return null;
2853
+ }
2854
+ }
2855
+ else {
2856
+ value = literalType.value;
2857
+ }
2858
+ const scalar = inferScalarForPrimitiveValue(constraint?.type, literalType);
2859
+ return {
2860
+ entityKind: "Value",
2861
+ valueKind: "StringValue",
2862
+ value,
2863
+ type: constraint ? constraint.type : literalType,
2864
+ scalar,
2865
+ };
2866
+ }
2867
+ function checkNumericValue(literalType, constraint, node) {
2868
+ if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
2869
+ return null;
2870
+ }
2871
+ const scalar = inferScalarForPrimitiveValue(constraint?.type, literalType);
2872
+ return {
2873
+ entityKind: "Value",
2874
+ valueKind: "NumericValue",
2875
+ value: Numeric(literalType.valueAsString),
2876
+ type: constraint ? constraint.type : literalType,
2877
+ scalar,
2878
+ };
2879
+ }
2880
+ function checkBooleanValue(literalType, constraint, node) {
2881
+ if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
2882
+ return null;
2883
+ }
2884
+ const scalar = inferScalarForPrimitiveValue(constraint?.type, literalType);
2885
+ return {
2886
+ entityKind: "Value",
2887
+ valueKind: "BooleanValue",
2888
+ value: literalType.value,
2889
+ type: constraint ? constraint.type : literalType,
2890
+ scalar,
2891
+ };
2892
+ }
2893
+ function checkNullValue(literalType, constraint, node) {
2894
+ if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
2895
+ return null;
2896
+ }
2897
+ return {
2898
+ entityKind: "Value",
2899
+ valueKind: "NullValue",
2900
+ type: constraint ? constraint.type : literalType,
2901
+ value: null,
2902
+ };
2903
+ }
2904
+ function checkEnumValue(literalType, constraint, node) {
2905
+ if (constraint && !checkTypeOfValueMatchConstraint(literalType, constraint, node)) {
2906
+ return null;
2907
+ }
2908
+ return {
2909
+ entityKind: "Value",
2910
+ valueKind: "EnumValue",
2911
+ type: constraint ? constraint.type : literalType,
2912
+ value: literalType,
2913
+ };
2914
+ }
2915
+ function checkCallExpressionTarget(node, mapper) {
2916
+ const target = checkTypeReference(node.target, mapper);
2917
+ if (target.kind === "Scalar" || target.kind === "ScalarConstructor") {
2918
+ return target;
2919
+ }
2920
+ else {
2921
+ reportCheckerDiagnostic(createDiagnostic({
2922
+ code: "non-callable",
2923
+ format: { type: target.kind },
2924
+ target: node.target,
2925
+ }));
2926
+ return null;
2927
+ }
2928
+ }
2929
+ /** Check the arguments of the call expression are a single value of the given syntax. */
2930
+ function checkPrimitiveArg(node, scalar, valueKind) {
2931
+ if (node.arguments.length !== 1) {
2932
+ reportCheckerDiagnostic(createDiagnostic({
2933
+ code: "invalid-primitive-init",
2934
+ target: node.target,
2935
+ }));
2936
+ return null;
2937
+ }
2938
+ const argNode = node.arguments[0];
2939
+ const value = getValueForNode(argNode, undefined);
2940
+ if (value === null) {
2941
+ return null; // error should already have been reported above.
2942
+ }
2943
+ if (value.valueKind !== valueKind) {
2944
+ reportCheckerDiagnostic(createDiagnostic({
2945
+ code: "invalid-primitive-init",
2946
+ messageId: "invalidArg",
2947
+ format: { actual: value.valueKind, expected: valueKind },
2948
+ target: argNode,
2949
+ }));
2950
+ return null;
2951
+ }
2952
+ if (!checkValueOfType(value, scalar, argNode)) {
2953
+ return null;
2954
+ }
2955
+ return { ...value, scalar, type: scalar };
2956
+ }
2957
+ function createScalarValue(node, mapper, declaration) {
2958
+ let hasError = false;
2959
+ const minArgs = declaration.parameters.filter((x) => !x.optional && !x.rest).length ?? 0;
2960
+ const maxArgs = declaration.parameters[declaration.parameters.length - 1]?.rest
2961
+ ? undefined
2962
+ : declaration.parameters.length;
2963
+ if (node.arguments.length < minArgs ||
2964
+ (maxArgs !== undefined && node.arguments.length > maxArgs)) {
2965
+ // In the case we have too little args then this decorator is not applicable.
2966
+ // If there is too many args then we can still run the decorator as long as the args are valid.
2967
+ if (node.arguments.length < minArgs) {
2968
+ hasError = true;
2969
+ }
2970
+ if (maxArgs === undefined) {
2971
+ reportCheckerDiagnostic(createDiagnostic({
2972
+ code: "invalid-argument-count",
2973
+ messageId: "atLeast",
2974
+ format: { actual: node.arguments.length.toString(), expected: minArgs.toString() },
2975
+ target: node,
2976
+ }));
2977
+ }
2978
+ else {
2979
+ const expected = minArgs === maxArgs ? minArgs.toString() : `${minArgs}-${maxArgs}`;
2980
+ reportCheckerDiagnostic(createDiagnostic({
2981
+ code: "invalid-argument-count",
2982
+ format: { actual: node.arguments.length.toString(), expected },
2983
+ target: node,
2984
+ }));
2985
+ }
2986
+ }
2987
+ const resolvedArgs = [];
2988
+ for (const [index, parameter] of declaration.parameters.entries()) {
2989
+ if (parameter.rest) {
2990
+ const restType = getIndexType(parameter.type);
2991
+ if (restType) {
2992
+ for (let i = index; i < node.arguments.length; i++) {
2993
+ const argNode = node.arguments[i];
2994
+ if (argNode) {
2995
+ const arg = getValueForNode(argNode, mapper, { kind: "argument", type: restType });
2996
+ if (arg === null) {
2997
+ hasError = true;
2998
+ continue;
2999
+ }
3000
+ if (checkValueOfType(arg, restType, argNode)) {
3001
+ resolvedArgs.push(arg);
3002
+ }
3003
+ else {
3004
+ hasError = true;
3005
+ }
3006
+ }
3007
+ }
3008
+ }
3009
+ break;
3010
+ }
3011
+ const argNode = node.arguments[index];
3012
+ if (argNode) {
3013
+ const arg = getValueForNode(argNode, mapper, {
3014
+ kind: "argument",
3015
+ type: parameter.type,
3016
+ });
3017
+ if (arg === null) {
3018
+ hasError = true;
3019
+ continue;
3020
+ }
3021
+ if (checkValueOfType(arg, parameter.type, argNode)) {
3022
+ resolvedArgs.push(arg);
3023
+ }
3024
+ else {
3025
+ hasError = true;
3026
+ }
3027
+ }
3028
+ }
3029
+ if (hasError) {
3030
+ return null;
3031
+ }
3032
+ return {
3033
+ entityKind: "Value",
3034
+ valueKind: "ScalarValue",
3035
+ value: {
3036
+ name: declaration.name,
3037
+ args: resolvedArgs,
3038
+ },
3039
+ scalar: declaration.scalar,
3040
+ type: declaration.scalar,
3041
+ };
3042
+ }
3043
+ function checkCallExpression(node, mapper) {
3044
+ const target = checkCallExpressionTarget(node, mapper);
3045
+ if (target === null) {
3046
+ return null;
3047
+ }
3048
+ if (target.kind === "ScalarConstructor") {
3049
+ return createScalarValue(node, mapper, target);
3050
+ }
3051
+ if (areScalarsRelated(target, getStdType("string"))) {
3052
+ return checkPrimitiveArg(node, target, "StringValue");
3053
+ }
3054
+ else if (areScalarsRelated(target, getStdType("numeric"))) {
3055
+ return checkPrimitiveArg(node, target, "NumericValue");
3056
+ }
3057
+ else if (areScalarsRelated(target, getStdType("boolean"))) {
3058
+ return checkPrimitiveArg(node, target, "BooleanValue");
3059
+ }
3060
+ else {
3061
+ reportCheckerDiagnostic(createDiagnostic({
3062
+ code: "named-init-required",
3063
+ format: { typeKind: target.kind },
3064
+ target: node.target,
3065
+ }));
3066
+ return null;
3067
+ }
3068
+ }
3069
+ function checkTypeOfExpression(node, mapper) {
3070
+ const entity = checkNode(node.target, mapper, undefined);
3071
+ if (entity === null) {
3072
+ // Shouldn't need to emit error as we assume null value already emitted error when produced
3073
+ return errorType;
3074
+ }
3075
+ if (entity.entityKind === "Indeterminate") {
3076
+ return entity.type;
3077
+ }
3078
+ if (isType(entity)) {
3079
+ if (entity.kind === "TemplateParameter") {
3080
+ if (entity.constraint === undefined || entity.constraint.type !== undefined) {
3081
+ // means this template constraint will accept values
3082
+ reportCheckerDiagnostic(createDiagnostic({
3083
+ code: "expect-value",
3084
+ messageId: "templateConstraint",
3085
+ format: { name: getTypeName(entity) },
3086
+ target: node.target,
3087
+ }));
3088
+ return errorType;
3089
+ }
3090
+ else if (entity.constraint.valueType) {
3091
+ return entity.constraint.valueType;
3092
+ }
3093
+ }
3094
+ reportCheckerDiagnostic(createDiagnostic({
3095
+ code: "expect-value",
3096
+ format: { name: getTypeName(entity) },
3097
+ target: node.target,
3098
+ }));
3099
+ return entity;
3100
+ }
3101
+ return entity.type;
3102
+ }
2152
3103
  function createUnion(options) {
2153
3104
  const variants = createRekeyableMap();
2154
3105
  const union = createAndFinishType({
@@ -2229,6 +3180,15 @@ export function createChecker(program) {
2229
3180
  }
2230
3181
  }
2231
3182
  break;
3183
+ case SyntaxKind.ScalarStatement:
3184
+ if (node.extends && node.extends.kind === SyntaxKind.TypeReference) {
3185
+ resolveAndCopyMembers(node.extends);
3186
+ }
3187
+ for (const member of node.members) {
3188
+ const name = member.id.sv;
3189
+ bindMember(name, member, 33554432 /* SymbolFlags.ScalarMember */);
3190
+ }
3191
+ break;
2232
3192
  case SyntaxKind.ModelExpression:
2233
3193
  for (const prop of node.properties) {
2234
3194
  if (prop.kind === SyntaxKind.ModelSpreadProperty) {
@@ -2356,7 +3316,7 @@ export function createChecker(program) {
2356
3316
  const sigTable = getOrCreateAugmentedSymbolTable(sig.metatypeMembers);
2357
3317
  const sigParameterSym = sigTable.get("parameters");
2358
3318
  if (sigParameterSym !== undefined) {
2359
- const parametersSym = createSymbol(sigParameterSym.declarations[0], "parameters", 2 /* SymbolFlags.Model */ & 674 /* SymbolFlags.MemberContainer */);
3319
+ const parametersSym = createSymbol(sigParameterSym.declarations[0], "parameters", 2 /* SymbolFlags.Model */ & 682 /* SymbolFlags.MemberContainer */);
2360
3320
  copyMembersToContainer(parametersSym, sigParameterSym.members);
2361
3321
  table.set("parameters", parametersSym);
2362
3322
  table.set("returnType", sigTable.get("returnType"));
@@ -2381,17 +3341,17 @@ export function createChecker(program) {
2381
3341
  return;
2382
3342
  switch (type.kind) {
2383
3343
  case "Model":
2384
- type.symbol = createSymbol(type.node, type.name, 2 /* SymbolFlags.Model */ | 16777216 /* SymbolFlags.LateBound */);
3344
+ type.symbol = createSymbol(type.node, type.name, 2 /* SymbolFlags.Model */ | 67108864 /* SymbolFlags.LateBound */);
2385
3345
  mutate(type.symbol).type = type;
2386
3346
  break;
2387
3347
  case "Interface":
2388
- type.symbol = createSymbol(type.node, type.name, 128 /* SymbolFlags.Interface */ | 16777216 /* SymbolFlags.LateBound */);
3348
+ type.symbol = createSymbol(type.node, type.name, 128 /* SymbolFlags.Interface */ | 67108864 /* SymbolFlags.LateBound */);
2389
3349
  mutate(type.symbol).type = type;
2390
3350
  break;
2391
3351
  case "Union":
2392
3352
  if (!type.name)
2393
3353
  return; // don't make a symbol for anonymous unions
2394
- type.symbol = createSymbol(type.node, type.name, 512 /* SymbolFlags.Union */ | 16777216 /* SymbolFlags.LateBound */);
3354
+ type.symbol = createSymbol(type.node, type.name, 512 /* SymbolFlags.Union */ | 67108864 /* SymbolFlags.LateBound */);
2395
3355
  mutate(type.symbol).type = type;
2396
3356
  break;
2397
3357
  }
@@ -2404,6 +3364,11 @@ export function createChecker(program) {
2404
3364
  lateBindMember(prop, 4 /* SymbolFlags.ModelProperty */);
2405
3365
  }
2406
3366
  break;
3367
+ case "Scalar":
3368
+ for (const member of type.constructors.values()) {
3369
+ lateBindMember(member, 33555780 /* SymbolFlags.Member */);
3370
+ }
3371
+ break;
2407
3372
  case "Enum":
2408
3373
  for (const member of type.members.values()) {
2409
3374
  lateBindMember(member, 64 /* SymbolFlags.EnumMember */);
@@ -2425,7 +3390,7 @@ export function createChecker(program) {
2425
3390
  // don't bind anything for union expressions
2426
3391
  return;
2427
3392
  }
2428
- const sym = createSymbol(member.node, member.name, kind | 16777216 /* SymbolFlags.LateBound */, containerSym);
3393
+ const sym = createSymbol(member.node, member.name, kind | 67108864 /* SymbolFlags.LateBound */, containerSym);
2429
3394
  mutate(sym).type = member;
2430
3395
  compilerAssert(containerSym.members, "containerSym.members is undefined");
2431
3396
  containerMembers ??= getOrCreateAugmentedSymbolTable(containerSym.members);
@@ -2611,7 +3576,14 @@ export function createChecker(program) {
2611
3576
  else {
2612
3577
  pendingResolutions.start(symId, ResolutionKind.Type);
2613
3578
  type.type = getTypeForNode(prop.value, mapper);
2614
- type.default = prop.default && checkDefault(prop.default, type.type);
3579
+ if (prop.default) {
3580
+ const defaultValue = checkDefaultValue(prop.default, type.type);
3581
+ if (defaultValue !== null) {
3582
+ type.defaultValue = defaultValue;
3583
+ // eslint-disable-next-line deprecation/deprecation
3584
+ type.default = checkLegacyDefault(prop.default);
3585
+ }
3586
+ }
2615
3587
  if (links) {
2616
3588
  linkType(links, type, mapper);
2617
3589
  }
@@ -2641,43 +3613,42 @@ export function createChecker(program) {
2641
3613
  ],
2642
3614
  };
2643
3615
  }
2644
- function isValueType(type) {
2645
- if (type === nullType) {
2646
- return true;
2647
- }
2648
- if (type.kind === "StringTemplate") {
2649
- const [valid] = isStringTemplateSerializable(type);
2650
- return valid;
2651
- }
2652
- if (type.kind === "UnionVariant") {
2653
- return isValueType(type.type);
2654
- }
2655
- const valueTypes = new Set(["String", "Number", "Boolean", "EnumMember", "Tuple"]);
2656
- return valueTypes.has(type.kind);
2657
- }
2658
- function checkDefault(defaultNode, type) {
2659
- const defaultType = getTypeForNode(defaultNode, undefined);
3616
+ function checkDefaultValue(defaultNode, type) {
2660
3617
  if (isErrorType(type)) {
2661
- return errorType;
3618
+ // if the prop type is an error we don't need to validate again.
3619
+ return null;
2662
3620
  }
2663
- if (!isValueType(defaultType)) {
2664
- reportCheckerDiagnostic(createDiagnostic({
2665
- code: "unsupported-default",
2666
- format: { type: defaultType.kind },
2667
- target: defaultNode,
2668
- }));
2669
- return errorType;
3621
+ const defaultValue = getValueForNode(defaultNode, undefined, {
3622
+ kind: "assignment",
3623
+ type,
3624
+ }, { legacyTupleAndModelCast: true });
3625
+ if (defaultValue === null) {
3626
+ return null;
2670
3627
  }
2671
- const [related, diagnostics] = isTypeAssignableTo(defaultType, type, defaultNode);
3628
+ const [related, diagnostics] = isValueOfType(defaultValue, type, defaultNode);
2672
3629
  if (!related) {
2673
3630
  reportCheckerDiagnostics(diagnostics);
2674
- return errorType;
3631
+ return null;
2675
3632
  }
2676
3633
  else {
2677
- return defaultType;
3634
+ return { ...defaultValue, type };
3635
+ }
3636
+ }
3637
+ /**
3638
+ * Fill in the legacy `.default` property.
3639
+ * We do do checking here we just keep existing behavior.
3640
+ */
3641
+ function checkLegacyDefault(defaultNode) {
3642
+ const resolved = checkNode(defaultNode, undefined);
3643
+ if (resolved === null || isValue(resolved)) {
3644
+ return undefined;
2678
3645
  }
3646
+ if (resolved.entityKind === "Indeterminate") {
3647
+ return resolved.type;
3648
+ }
3649
+ return resolved;
2679
3650
  }
2680
- function checkDecorator(targetType, decNode, mapper) {
3651
+ function checkDecoratorApplication(targetType, decNode, mapper) {
2681
3652
  const sym = resolveTypeReferenceSym(decNode.target, undefined, true);
2682
3653
  if (!sym) {
2683
3654
  reportCheckerDiagnostic(createDiagnostic({
@@ -2695,7 +3666,6 @@ export function createChecker(program) {
2695
3666
  return undefined;
2696
3667
  }
2697
3668
  const symbolLinks = getSymbolLinks(sym);
2698
- let args = checkDecoratorArguments(decNode, mapper);
2699
3669
  let hasError = false;
2700
3670
  if (symbolLinks.declaredType === undefined) {
2701
3671
  const decoratorDeclNode = sym.declarations.find((x) => x.kind === SyntaxKind.DecoratorDeclarationStatement);
@@ -2705,10 +3675,12 @@ export function createChecker(program) {
2705
3675
  }
2706
3676
  if (symbolLinks.declaredType) {
2707
3677
  compilerAssert(symbolLinks.declaredType.kind === "Decorator", "Expected to find a decorator type.");
2708
- // Means we have a decorator declaration.
2709
- [hasError, args] = checkDecoratorUsage(targetType, symbolLinks.declaredType, args, decNode);
3678
+ if (!checkDecoratorTarget(targetType, symbolLinks.declaredType, decNode)) {
3679
+ hasError = true;
3680
+ }
2710
3681
  }
2711
- if (hasError) {
3682
+ const [argsHaveError, args] = checkDecoratorArguments(decNode, mapper, symbolLinks.declaredType);
3683
+ if (hasError || argsHaveError) {
2712
3684
  return undefined;
2713
3685
  }
2714
3686
  return {
@@ -2718,62 +3690,121 @@ export function createChecker(program) {
2718
3690
  args,
2719
3691
  };
2720
3692
  }
2721
- function checkDecoratorUsage(targetType, declaration, args, decoratorNode) {
2722
- let hasError = false;
3693
+ function resolveDecoratorArgMarshalling(declaredType) {
3694
+ if (declaredType) {
3695
+ const location = getLocationContext(program, declaredType);
3696
+ if (location.type === "compiler") {
3697
+ return "new";
3698
+ }
3699
+ else if ((location.type === "library" || location.type === "project") &&
3700
+ location.flags?.decoratorArgMarshalling) {
3701
+ return location.flags.decoratorArgMarshalling;
3702
+ }
3703
+ else {
3704
+ return "legacy";
3705
+ }
3706
+ }
3707
+ return "new";
3708
+ }
3709
+ /** Check the decorator target is valid */
3710
+ function checkDecoratorTarget(targetType, declaration, decoratorNode) {
2723
3711
  const [targetValid] = isTypeAssignableTo(targetType, declaration.target.type, decoratorNode);
2724
3712
  if (!targetValid) {
2725
- hasError = true;
2726
3713
  reportCheckerDiagnostic(createDiagnostic({
2727
3714
  code: "decorator-wrong-target",
2728
3715
  messageId: "withExpected",
2729
3716
  format: {
2730
3717
  decorator: declaration.name,
2731
3718
  to: getTypeName(targetType),
2732
- expected: getTypeName(declaration.target.type),
3719
+ expected: getEntityName(declaration.target.type),
2733
3720
  },
2734
3721
  target: decoratorNode,
2735
3722
  }));
2736
3723
  }
2737
- const minArgs = declaration.parameters.filter((x) => !x.optional && !x.rest).length;
3724
+ return targetValid;
3725
+ }
3726
+ function checkDecoratorArguments(node, mapper, declaration) {
3727
+ // if we don't have a declaration we can just return the types or values if
3728
+ if (declaration === undefined) {
3729
+ return [
3730
+ false,
3731
+ node.arguments.map((argNode) => {
3732
+ let type = checkNode(argNode, mapper) ?? errorType;
3733
+ if (type.entityKind === "Indeterminate") {
3734
+ type = type.type;
3735
+ }
3736
+ return {
3737
+ value: type,
3738
+ jsValue: type,
3739
+ node: argNode,
3740
+ };
3741
+ }),
3742
+ ];
3743
+ }
3744
+ let hasError = false;
3745
+ const minArgs = declaration.parameters.filter((x) => !x.optional && !x.rest).length ?? 0;
2738
3746
  const maxArgs = declaration.parameters[declaration.parameters.length - 1]?.rest
2739
3747
  ? undefined
2740
3748
  : declaration.parameters.length;
2741
- if (args.length < minArgs || (maxArgs !== undefined && args.length > maxArgs)) {
3749
+ if (node.arguments.length < minArgs ||
3750
+ (maxArgs !== undefined && node.arguments.length > maxArgs)) {
2742
3751
  // In the case we have too little args then this decorator is not applicable.
2743
3752
  // If there is too many args then we can still run the decorator as long as the args are valid.
2744
- if (args.length < minArgs) {
3753
+ if (node.arguments.length < minArgs) {
2745
3754
  hasError = true;
2746
3755
  }
2747
3756
  if (maxArgs === undefined) {
2748
3757
  reportCheckerDiagnostic(createDiagnostic({
2749
3758
  code: "invalid-argument-count",
2750
3759
  messageId: "atLeast",
2751
- format: { actual: args.length.toString(), expected: minArgs.toString() },
2752
- target: decoratorNode,
3760
+ format: { actual: node.arguments.length.toString(), expected: minArgs.toString() },
3761
+ target: node,
2753
3762
  }));
2754
3763
  }
2755
3764
  else {
2756
3765
  const expected = minArgs === maxArgs ? minArgs.toString() : `${minArgs}-${maxArgs}`;
2757
3766
  reportCheckerDiagnostic(createDiagnostic({
2758
3767
  code: "invalid-argument-count",
2759
- format: { actual: args.length.toString(), expected },
2760
- target: decoratorNode,
3768
+ format: { actual: node.arguments.length.toString(), expected },
3769
+ target: node,
2761
3770
  }));
2762
3771
  }
2763
3772
  }
2764
3773
  const resolvedArgs = [];
3774
+ const jsMarshalling = resolveDecoratorArgMarshalling(declaration);
3775
+ function resolveArg(argNode, perParamType) {
3776
+ const arg = getTypeOrValueForNode(argNode, mapper, {
3777
+ kind: "argument",
3778
+ constraint: perParamType,
3779
+ });
3780
+ if (arg !== null &&
3781
+ !(isType(arg) && isErrorType(arg)) &&
3782
+ checkArgumentAssignable(arg, perParamType, argNode)) {
3783
+ return {
3784
+ value: arg,
3785
+ node: argNode,
3786
+ jsValue: resolveDecoratorArgJsValue(arg, extractValueOfConstraints({
3787
+ kind: "argument",
3788
+ constraint: perParamType,
3789
+ }), jsMarshalling),
3790
+ };
3791
+ }
3792
+ else {
3793
+ return undefined;
3794
+ }
3795
+ }
2765
3796
  for (const [index, parameter] of declaration.parameters.entries()) {
2766
3797
  if (parameter.rest) {
2767
- const restType = getIndexType(parameter.type.kind === "Value" ? parameter.type.target : parameter.type);
3798
+ const restType = extractRestParamConstraint(parameter.type);
2768
3799
  if (restType) {
2769
- for (let i = index; i < args.length; i++) {
2770
- const arg = args[i];
2771
- if (arg && arg.value) {
2772
- resolvedArgs.push({
2773
- ...arg,
2774
- jsValue: resolveDecoratorArgJsValue(arg.value, parameter.type.kind === "Value"),
2775
- });
2776
- if (!checkArgumentAssignable(arg.value, restType, arg.node)) {
3800
+ for (let i = index; i < node.arguments.length; i++) {
3801
+ const argNode = node.arguments[i];
3802
+ if (argNode) {
3803
+ const arg = resolveArg(argNode, restType);
3804
+ if (arg) {
3805
+ resolvedArgs.push(arg);
3806
+ }
3807
+ else {
2777
3808
  hasError = true;
2778
3809
  }
2779
3810
  }
@@ -2781,29 +3812,58 @@ export function createChecker(program) {
2781
3812
  }
2782
3813
  break;
2783
3814
  }
2784
- const arg = args[index];
2785
- if (arg && arg.value) {
2786
- resolvedArgs.push({
2787
- ...arg,
2788
- jsValue: resolveDecoratorArgJsValue(arg.value, parameter.type.kind === "Value"),
2789
- });
2790
- if (!checkArgumentAssignable(arg.value, parameter.type, arg.node)) {
3815
+ const argNode = node.arguments[index];
3816
+ if (argNode) {
3817
+ const arg = resolveArg(argNode, parameter.type);
3818
+ if (arg) {
3819
+ resolvedArgs.push(arg);
3820
+ }
3821
+ else {
2791
3822
  hasError = true;
2792
3823
  }
2793
3824
  }
2794
3825
  }
2795
3826
  return [hasError, resolvedArgs];
2796
3827
  }
3828
+ /** For a rest param of constraint T[] or valueof T[] return the T or valueof T */
3829
+ function extractRestParamConstraint(constraint) {
3830
+ let valueType;
3831
+ let type;
3832
+ if (constraint.valueType) {
3833
+ if (constraint.valueType.kind === "Model" &&
3834
+ isArrayModelType(program, constraint.valueType)) {
3835
+ valueType = constraint.valueType.indexer.value;
3836
+ }
3837
+ else {
3838
+ return undefined;
3839
+ }
3840
+ }
3841
+ if (constraint.type) {
3842
+ if (constraint.type.kind === "Model" && isArrayModelType(program, constraint.type)) {
3843
+ type = constraint.type.indexer.value;
3844
+ }
3845
+ else {
3846
+ return undefined;
3847
+ }
3848
+ }
3849
+ return {
3850
+ entityKind: "MixedParameterConstraint",
3851
+ type,
3852
+ valueType,
3853
+ };
3854
+ }
2797
3855
  function getIndexType(type) {
2798
3856
  return type.kind === "Model" ? type.indexer?.value : undefined;
2799
3857
  }
2800
- function resolveDecoratorArgJsValue(value, valueOf) {
2801
- if (valueOf) {
2802
- if (value.kind === "Boolean" || value.kind === "String" || value.kind === "Number") {
2803
- return literalTypeToValue(value);
3858
+ function resolveDecoratorArgJsValue(value, valueConstraint, jsMarshalling) {
3859
+ if (valueConstraint !== undefined) {
3860
+ if (isValue(value)) {
3861
+ return jsMarshalling === "legacy"
3862
+ ? legacyMarshallTypeForJS(checker, value)
3863
+ : marshallTypeForJS(value, valueConstraint.type);
2804
3864
  }
2805
- else if (value.kind === "StringTemplate") {
2806
- return stringTemplateToString(value)[0];
3865
+ else {
3866
+ return value;
2807
3867
  }
2808
3868
  }
2809
3869
  return value;
@@ -2814,8 +3874,8 @@ export function createChecker(program) {
2814
3874
  reportCheckerDiagnostic(createDiagnostic({
2815
3875
  code: "invalid-argument",
2816
3876
  format: {
2817
- value: getTypeName(argumentType),
2818
- expected: getTypeName(parameterType),
3877
+ value: getEntityName(argumentType),
3878
+ expected: getEntityName(parameterType),
2819
3879
  },
2820
3880
  target: diagnosticTarget,
2821
3881
  }));
@@ -2826,7 +3886,7 @@ export function createChecker(program) {
2826
3886
  const augmentDecoratorNodes = augmentDecoratorsForSym.get(sym) ?? [];
2827
3887
  const decorators = [];
2828
3888
  for (const decNode of augmentDecoratorNodes) {
2829
- const decorator = checkDecorator(targetType, decNode, mapper);
3889
+ const decorator = checkDecoratorApplication(targetType, decNode, mapper);
2830
3890
  if (decorator) {
2831
3891
  decorators.unshift(decorator);
2832
3892
  }
@@ -2842,7 +3902,7 @@ export function createChecker(program) {
2842
3902
  ...node.decorators,
2843
3903
  ];
2844
3904
  for (const decNode of decoratorNodes) {
2845
- const decorator = checkDecorator(targetType, decNode, mapper);
3905
+ const decorator = checkDecoratorApplication(targetType, decNode, mapper);
2846
3906
  if (decorator) {
2847
3907
  decorators.unshift(decorator);
2848
3908
  }
@@ -2863,16 +3923,6 @@ export function createChecker(program) {
2863
3923
  }
2864
3924
  return decorators;
2865
3925
  }
2866
- function checkDecoratorArguments(decorator, mapper) {
2867
- return decorator.arguments.map((argNode) => {
2868
- const type = getTypeForNode(argNode, mapper);
2869
- return {
2870
- value: type,
2871
- jsValue: type,
2872
- node: argNode,
2873
- };
2874
- });
2875
- }
2876
3926
  function checkScalar(node, mapper) {
2877
3927
  const links = getSymbolLinks(node.symbol);
2878
3928
  if (links.declaredType && mapper === undefined) {
@@ -2885,10 +3935,12 @@ export function createChecker(program) {
2885
3935
  kind: "Scalar",
2886
3936
  name: node.id.sv,
2887
3937
  node: node,
3938
+ constructors: new Map(),
2888
3939
  namespace: getParentNamespaceType(node),
2889
3940
  decorators,
2890
3941
  derivedScalars: [],
2891
3942
  });
3943
+ checkScalarConstructors(type, node, type.constructors, mapper);
2892
3944
  linkType(links, type, mapper);
2893
3945
  if (node.extends) {
2894
3946
  type.baseScalar = checkScalarExtends(node, node.extends, mapper);
@@ -2939,6 +3991,43 @@ export function createChecker(program) {
2939
3991
  }
2940
3992
  return extendsType;
2941
3993
  }
3994
+ function checkScalarConstructors(parentScalar, node, constructors, mapper) {
3995
+ for (const member of node.members) {
3996
+ const constructor = checkScalarConstructor(member, mapper, parentScalar);
3997
+ if (constructors.has(constructor.name)) {
3998
+ reportCheckerDiagnostic(createDiagnostic({
3999
+ code: "constructor-duplicate",
4000
+ format: { name: constructor.name.toString() },
4001
+ target: member,
4002
+ }));
4003
+ continue;
4004
+ }
4005
+ constructors.set(constructor.name, constructor);
4006
+ }
4007
+ }
4008
+ function checkScalarConstructor(node, mapper, parentScalar) {
4009
+ const name = node.id.sv;
4010
+ const links = getSymbolLinksForMember(node);
4011
+ if (links && links.declaredType && mapper === undefined) {
4012
+ // we're not instantiating this scalar constructor and we've already checked it
4013
+ return links.declaredType;
4014
+ }
4015
+ const member = createType({
4016
+ kind: "ScalarConstructor",
4017
+ scalar: parentScalar,
4018
+ name,
4019
+ node,
4020
+ parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, false)),
4021
+ });
4022
+ linkMapper(member, mapper);
4023
+ if (shouldCreateTypeForTemplate(node.parent, mapper)) {
4024
+ finishType(member);
4025
+ }
4026
+ if (links) {
4027
+ linkType(links, member, mapper);
4028
+ }
4029
+ return finishType(member);
4030
+ }
2942
4031
  function checkAlias(node, mapper) {
2943
4032
  const links = getSymbolLinks(node.symbol);
2944
4033
  if (links.declaredType && mapper === undefined) {
@@ -2959,10 +4048,55 @@ export function createChecker(program) {
2959
4048
  }
2960
4049
  pendingResolutions.start(aliasSymId, ResolutionKind.Type);
2961
4050
  const type = getTypeForNode(node.value, mapper);
2962
- linkType(links, type, mapper);
4051
+ if (!isValue(type)) {
4052
+ linkType(links, type, mapper);
4053
+ }
2963
4054
  pendingResolutions.finish(aliasSymId, ResolutionKind.Type);
2964
4055
  return type;
2965
4056
  }
4057
+ function checkConst(node) {
4058
+ const links = getSymbolLinks(node.symbol);
4059
+ if (links.value !== undefined) {
4060
+ return links.value;
4061
+ }
4062
+ const type = node.type ? getTypeForNode(node.type, undefined) : undefined;
4063
+ const symId = getSymbolId(node.symbol);
4064
+ if (pendingResolutions.has(symId, ResolutionKind.Value)) {
4065
+ reportCheckerDiagnostic(createDiagnostic({
4066
+ code: "circular-const",
4067
+ format: { name: node.id.sv },
4068
+ target: node,
4069
+ }));
4070
+ return null;
4071
+ }
4072
+ pendingResolutions.start(symId, ResolutionKind.Value);
4073
+ const value = getValueForNode(node.value, undefined, type && { kind: "assignment", type });
4074
+ pendingResolutions.finish(symId, ResolutionKind.Value);
4075
+ if (value === null || (type && !checkValueOfType(value, type, node.id))) {
4076
+ links.value = null;
4077
+ return links.value;
4078
+ }
4079
+ links.value = type ? { ...value, type } : { ...value };
4080
+ return links.value;
4081
+ }
4082
+ function inferScalarsFromConstraints(value, type) {
4083
+ switch (value.valueKind) {
4084
+ case "BooleanValue":
4085
+ case "StringValue":
4086
+ case "NumericValue":
4087
+ if (value.scalar === undefined) {
4088
+ const scalar = inferScalarForPrimitiveValue(type, value.type);
4089
+ return { ...value, scalar };
4090
+ }
4091
+ return value;
4092
+ case "ArrayValue":
4093
+ case "ObjectValue":
4094
+ case "EnumValue":
4095
+ case "NullValue":
4096
+ case "ScalarValue":
4097
+ return value;
4098
+ }
4099
+ }
2966
4100
  function checkEnum(node, mapper) {
2967
4101
  const links = getSymbolLinks(node.symbol);
2968
4102
  if (!links.type) {
@@ -3279,6 +4413,7 @@ export function createChecker(program) {
3279
4413
  // If the type has an associated syntax node, check any directives that
3280
4414
  // might be attached.
3281
4415
  const createdType = typeDef;
4416
+ createdType.entityKind = "Type";
3282
4417
  if (createdType.node) {
3283
4418
  checkDirectives(createdType.node, createdType);
3284
4419
  }
@@ -4024,6 +5159,7 @@ export function createChecker(program) {
4024
5159
  kind: "Number",
4025
5160
  value,
4026
5161
  valueAsString,
5162
+ numericValue: Numeric(valueAsString),
4027
5163
  });
4028
5164
  break;
4029
5165
  }
@@ -4036,7 +5172,7 @@ export function createChecker(program) {
4036
5172
  throw new ProjectionError("Can't find decorator.");
4037
5173
  compilerAssert(ref.flags & 16384 /* SymbolFlags.Decorator */, "should only resolve decorator symbols");
4038
5174
  return createFunctionType((...args) => {
4039
- ref.value({ program }, ...marshalArgumentsForJS(args));
5175
+ ref.value({ program }, ...args.map(unsafe_projectionArgumentMarshalForJS));
4040
5176
  return voidType;
4041
5177
  });
4042
5178
  }
@@ -4061,7 +5197,7 @@ export function createChecker(program) {
4061
5197
  else if (ref.flags & 131072 /* SymbolFlags.Function */) {
4062
5198
  // TODO: store this in a symbol link probably?
4063
5199
  const t = createFunctionType((...args) => {
4064
- const retval = ref.value(program, ...marshalArgumentsForJS(args));
5200
+ const retval = ref.value(program, ...args.map(unsafe_projectionArgumentMarshalForJS));
4065
5201
  return marshalProjectionReturn(retval, { functionName: node.sv });
4066
5202
  });
4067
5203
  return t;
@@ -4135,6 +5271,31 @@ export function createChecker(program) {
4135
5271
  parts.push(current.sv);
4136
5272
  return parts.reverse().join(".");
4137
5273
  }
5274
+ /**
5275
+ * Check if the source type can be assigned to the target type and emit diagnostics
5276
+ * @param source Type of a value
5277
+ * @param constraint
5278
+ * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
5279
+ */
5280
+ function checkTypeOfValueMatchConstraint(source, constraint, diagnosticTarget) {
5281
+ const [related, diagnostics] = isTypeAssignableTo(source, constraint.type, diagnosticTarget);
5282
+ if (!related) {
5283
+ if (constraint.kind === "argument") {
5284
+ reportCheckerDiagnostic(createDiagnostic({
5285
+ code: "invalid-argument",
5286
+ format: {
5287
+ value: getEntityName(source),
5288
+ expected: getEntityName(constraint.type),
5289
+ },
5290
+ target: diagnosticTarget,
5291
+ }));
5292
+ }
5293
+ else {
5294
+ reportCheckerDiagnostics(diagnostics);
5295
+ }
5296
+ }
5297
+ return related;
5298
+ }
4138
5299
  /**
4139
5300
  * Check if the source type can be assigned to the target type and emit diagnostics
4140
5301
  * @param source Source type
@@ -4148,6 +5309,13 @@ export function createChecker(program) {
4148
5309
  }
4149
5310
  return related;
4150
5311
  }
5312
+ function checkValueOfType(source, target, diagnosticTarget) {
5313
+ const [related, diagnostics] = isValueOfType(source, target, diagnosticTarget);
5314
+ if (!related) {
5315
+ reportCheckerDiagnostics(diagnostics);
5316
+ }
5317
+ return related;
5318
+ }
4151
5319
  /**
4152
5320
  * Check if the source type can be assigned to the target type.
4153
5321
  * @param source Source type
@@ -4158,6 +5326,16 @@ export function createChecker(program) {
4158
5326
  const [related, diagnostics] = isTypeAssignableToInternal(source, target, diagnosticTarget, new MultiKeyMap());
4159
5327
  return [related === Related.true, diagnostics];
4160
5328
  }
5329
+ /**
5330
+ * Check if the given Value type is of the given type.
5331
+ * @param source Value
5332
+ * @param target Target type
5333
+ * @param diagnosticTarget Target for the diagnostic, unless something better can be inferred.
5334
+ */
5335
+ function isValueOfType(source, target, diagnosticTarget) {
5336
+ const [related, diagnostics] = isValueOfTypeInternal(source, target, diagnosticTarget, new MultiKeyMap());
5337
+ return [related === Related.true, diagnostics];
5338
+ }
4161
5339
  function isTypeAssignableToInternal(source, target, diagnosticTarget, relationCache) {
4162
5340
  const cached = relationCache.get([source, target]);
4163
5341
  if (cached !== undefined) {
@@ -4168,26 +5346,44 @@ export function createChecker(program) {
4168
5346
  return [result, diagnostics];
4169
5347
  }
4170
5348
  function isTypeAssignableToWorker(source, target, diagnosticTarget, relationCache) {
4171
- // BACKCOMPAT: Added May 2023 sprint, to be removed by June 2023 sprint
4172
- if (source.kind === "TemplateParameter" && source.constraint && target.kind === "Value") {
4173
- const [assignable] = isTypeAssignableToInternal(source.constraint, target.target, diagnosticTarget, relationCache);
5349
+ // BACKCOMPAT: Allow certain type to be accepted as values
5350
+ if ("kind" in source &&
5351
+ "entityKind" in target &&
5352
+ source.kind === "TemplateParameter" &&
5353
+ source.constraint?.type &&
5354
+ source.constraint.valueType === undefined &&
5355
+ target.entityKind === "MixedParameterConstraint" &&
5356
+ target.valueType) {
5357
+ const [assignable] = isTypeAssignableToInternal(source.constraint.type, target.valueType, diagnosticTarget, relationCache);
4174
5358
  if (assignable) {
4175
- const constraint = getTypeName(source.constraint);
4176
- reportDeprecated(program, `Template constrainted to '${constraint}' will not be assignable to '${getTypeName(target)}' in the future. Update the constraint to be 'valueof ${constraint}'`, diagnosticTarget);
5359
+ const constraint = getEntityName(source.constraint);
5360
+ reportDeprecated(program, `Template constrainted to '${constraint}' will not be assignable to '${getEntityName(target)}' in the future. Update the constraint to be 'valueof ${constraint}'`, diagnosticTarget);
4177
5361
  return [Related.true, []];
4178
5362
  }
4179
5363
  }
4180
- while (source.kind === "TemplateParameter" && source.constraint !== source) {
5364
+ if ("kind" in source && source.kind === "TemplateParameter") {
4181
5365
  source = source.constraint ?? unknownType;
4182
5366
  }
5367
+ if (target.entityKind === "Indeterminate") {
5368
+ target = target.type;
5369
+ }
4183
5370
  if (source === target)
4184
5371
  return [Related.true, []];
4185
- if (target.kind === "Value") {
4186
- return isAssignableToValueType(source, target, diagnosticTarget, relationCache);
5372
+ if (isValue(target)) {
5373
+ return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5374
+ }
5375
+ if (source.entityKind === "Indeterminate") {
5376
+ return isIndeterminateEntityAssignableTo(source, target, diagnosticTarget, relationCache);
4187
5377
  }
4188
- if (source.kind === "Value") {
5378
+ if (target.entityKind === "MixedParameterConstraint") {
5379
+ return isAssignableToMixedParameterConstraint(source, target, diagnosticTarget, relationCache);
5380
+ }
5381
+ if (isValue(source) || (source.entityKind === "MixedParameterConstraint" && source.valueType)) {
4189
5382
  return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
4190
5383
  }
5384
+ if (source.entityKind === "MixedParameterConstraint") {
5385
+ return isTypeAssignableToInternal(source.type, target, diagnosticTarget, relationCache);
5386
+ }
4191
5387
  const isSimpleTypeRelated = isSimpleTypeAssignableTo(source, target);
4192
5388
  if (isSimpleTypeRelated === true) {
4193
5389
  return [Related.true, []];
@@ -4227,19 +5423,21 @@ export function createChecker(program) {
4227
5423
  else if (target.kind === "Model" &&
4228
5424
  isArrayModelType(program, target) &&
4229
5425
  source.kind === "Model") {
4230
- return hasIndexAndIsAssignableTo(source, target, diagnosticTarget, relationCache);
5426
+ if (isArrayModelType(program, source)) {
5427
+ return hasIndexAndIsAssignableTo(source, target, diagnosticTarget, relationCache);
5428
+ }
5429
+ else {
5430
+ // For other models just fallback to unassignable
5431
+ return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5432
+ }
4231
5433
  }
4232
5434
  else if (target.kind === "Model" && source.kind === "Model") {
4233
5435
  return isModelRelatedTo(source, target, diagnosticTarget, relationCache);
4234
5436
  }
4235
- else if (target.kind === "Model" && target.indexer && source.kind === "Tuple") {
4236
- for (const item of source.values) {
4237
- const [related, diagnostics] = isTypeAssignableToInternal(item, target.indexer.value, diagnosticTarget, relationCache);
4238
- if (!related) {
4239
- return [Related.false, diagnostics];
4240
- }
4241
- }
4242
- return [Related.true, []];
5437
+ else if (target.kind === "Model" &&
5438
+ isArrayModelType(program, target) &&
5439
+ source.kind === "Tuple") {
5440
+ return isTupleAssignableToArray(source, target, diagnosticTarget, relationCache);
4243
5441
  }
4244
5442
  else if (target.kind === "Tuple" && source.kind === "Tuple") {
4245
5443
  return isTupleAssignableToTuple(source, target, diagnosticTarget, relationCache);
@@ -4252,18 +5450,60 @@ export function createChecker(program) {
4252
5450
  }
4253
5451
  return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
4254
5452
  }
4255
- function isAssignableToValueType(source, target, diagnosticTarget, relationCache) {
4256
- if (source.kind === "Value") {
4257
- return isTypeAssignableToInternal(source.target, target.target, diagnosticTarget, relationCache);
5453
+ function isIndeterminateEntityAssignableTo(indeterminate, target, diagnosticTarget, relationCache) {
5454
+ const [typeRelated, typeDiagnostics] = isTypeAssignableToInternal(indeterminate.type, target, diagnosticTarget, relationCache);
5455
+ if (typeRelated) {
5456
+ return [Related.true, []];
4258
5457
  }
4259
- const [assignable, diagnostics] = isTypeAssignableToInternal(source, target.target, diagnosticTarget, relationCache);
4260
- if (!assignable) {
4261
- return [assignable, diagnostics];
5458
+ if (target.entityKind === "MixedParameterConstraint" && target.valueType) {
5459
+ const [valueRelated] = isTypeAssignableToInternal(indeterminate.type, target.valueType, diagnosticTarget, relationCache);
5460
+ if (valueRelated) {
5461
+ return [Related.true, []];
5462
+ }
4262
5463
  }
4263
- if (!isValueType(source)) {
5464
+ return [Related.false, typeDiagnostics];
5465
+ }
5466
+ function isAssignableToValueType(source, target, diagnosticTarget, relationCache) {
5467
+ if (!isValue(source)) {
4264
5468
  return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
4265
5469
  }
4266
- return [Related.true, []];
5470
+ return isValueOfTypeInternal(source, target, diagnosticTarget, relationCache);
5471
+ }
5472
+ function isAssignableToMixedParameterConstraint(source, target, diagnosticTarget, relationCache) {
5473
+ if ("entityKind" in source && source.entityKind === "MixedParameterConstraint") {
5474
+ if (source.type && target.type) {
5475
+ const [variantAssignable, diagnostics] = isTypeAssignableToInternal(source.type, target.type, diagnosticTarget, relationCache);
5476
+ if (variantAssignable === Related.false) {
5477
+ return [Related.false, diagnostics];
5478
+ }
5479
+ return [Related.true, []];
5480
+ }
5481
+ if (source.valueType && target.valueType) {
5482
+ const [variantAssignable, diagnostics] = isTypeAssignableToInternal(source.valueType, target.valueType, diagnosticTarget, relationCache);
5483
+ if (variantAssignable === Related.false) {
5484
+ return [Related.false, diagnostics];
5485
+ }
5486
+ return [Related.true, []];
5487
+ }
5488
+ return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5489
+ }
5490
+ if (target.type) {
5491
+ const [related] = isTypeAssignableToInternal(source, target.type, diagnosticTarget, relationCache);
5492
+ if (related) {
5493
+ return [Related.true, []];
5494
+ }
5495
+ }
5496
+ if (target.valueType) {
5497
+ const [related] = isAssignableToValueType(source, target.valueType, diagnosticTarget, relationCache);
5498
+ if (related) {
5499
+ return [Related.true, []];
5500
+ }
5501
+ }
5502
+ return [Related.false, [createUnassignableDiagnostic(source, target, diagnosticTarget)]];
5503
+ }
5504
+ /** Check if the value is assignable to the given type. */
5505
+ function isValueOfTypeInternal(source, target, diagnosticTarget, relationCache) {
5506
+ return isTypeAssignableToInternal(source.type, target, diagnosticTarget, relationCache);
4267
5507
  }
4268
5508
  function isReflectionType(type) {
4269
5509
  return (type.kind === "Model" &&
@@ -4276,7 +5516,7 @@ export function createChecker(program) {
4276
5516
  return isNumericLiteralRelatedTo(source, target);
4277
5517
  case "String":
4278
5518
  case "StringTemplate":
4279
- return areScalarsRelated(target, getStdType("string"));
5519
+ return isStringLiteralRelatedTo(source, target);
4280
5520
  case "Boolean":
4281
5521
  return areScalarsRelated(target, getStdType("boolean"));
4282
5522
  case "Scalar":
@@ -4314,7 +5554,12 @@ export function createChecker(program) {
4314
5554
  return false;
4315
5555
  }
4316
5556
  if (target.kind === "String") {
4317
- return source.kind === "String" && target.value === source.value;
5557
+ return ((source.kind === "String" && source.value === target.value) ||
5558
+ (source.kind === "StringTemplate" && source.stringValue === target.value));
5559
+ }
5560
+ if (target.kind === "StringTemplate" && target.stringValue) {
5561
+ return ((source.kind === "String" && source.value === target.stringValue) ||
5562
+ (source.kind === "StringTemplate" && source.stringValue === target.stringValue));
4318
5563
  }
4319
5564
  if (target.kind === "Number") {
4320
5565
  return source.kind === "Number" && target.value === source.value;
@@ -4322,6 +5567,29 @@ export function createChecker(program) {
4322
5567
  return undefined;
4323
5568
  }
4324
5569
  function isNumericLiteralRelatedTo(source, target) {
5570
+ // First check that the source numeric literal is assignable to the target scalar
5571
+ if (!isNumericAssignableToNumericScalar(source.numericValue, target)) {
5572
+ return false;
5573
+ }
5574
+ const min = getMinValueAsNumeric(program, target);
5575
+ const max = getMaxValueAsNumeric(program, target);
5576
+ const minExclusive = getMinValueExclusiveAsNumeric(program, target);
5577
+ const maxExclusive = getMaxValueExclusiveAsNumeric(program, target);
5578
+ if (min && source.numericValue.lt(min)) {
5579
+ return false;
5580
+ }
5581
+ if (minExclusive && source.numericValue.lte(minExclusive)) {
5582
+ return false;
5583
+ }
5584
+ if (max && source.numericValue.gt(max)) {
5585
+ return false;
5586
+ }
5587
+ if (maxExclusive && source.numericValue.gte(maxExclusive)) {
5588
+ return false;
5589
+ }
5590
+ return true;
5591
+ }
5592
+ function isNumericAssignableToNumericScalar(source, target) {
4325
5593
  // if the target does not derive from numeric, then it can't be assigned a numeric literal
4326
5594
  if (!areScalarsRelated(target, getStdType("numeric"))) {
4327
5595
  return false;
@@ -4338,7 +5606,7 @@ export function createChecker(program) {
4338
5606
  return true;
4339
5607
  if (target.name === "decimal128")
4340
5608
  return true;
4341
- const isInt = Number.isInteger(source.value);
5609
+ const isInt = source.isInteger;
4342
5610
  if (target.name === "integer")
4343
5611
  return isInt;
4344
5612
  if (target.name === "float")
@@ -4346,7 +5614,25 @@ export function createChecker(program) {
4346
5614
  if (!(target.name in numericRanges))
4347
5615
  return false;
4348
5616
  const [low, high, options] = numericRanges[target.name];
4349
- return source.value >= low && source.value <= high && (!options.int || isInt);
5617
+ return source.gte(low) && source.lte(high) && (!options.int || isInt);
5618
+ }
5619
+ function isStringLiteralRelatedTo(source, target) {
5620
+ if (!areScalarsRelated(target, getStdType("string"))) {
5621
+ return false;
5622
+ }
5623
+ if (source.kind === "StringTemplate") {
5624
+ return true;
5625
+ }
5626
+ const len = source.value.length;
5627
+ const min = getMinLength(program, target);
5628
+ const max = getMaxLength(program, target);
5629
+ if (min && len < min) {
5630
+ return false;
5631
+ }
5632
+ if (max && len > max) {
5633
+ return false;
5634
+ }
5635
+ return true;
4350
5636
  }
4351
5637
  function isModelRelatedTo(source, target, diagnosticTarget, relationCache) {
4352
5638
  relationCache.set([source, target], Related.maybe);
@@ -4396,8 +5682,30 @@ export function createChecker(program) {
4396
5682
  }
4397
5683
  }
4398
5684
  }
5685
+ else if (shouldCheckExcessProperties(source)) {
5686
+ for (const [propName, prop] of remainingProperties) {
5687
+ if (shouldCheckExcessProperty(prop)) {
5688
+ diagnostics.push(createDiagnostic({
5689
+ code: "unexpected-property",
5690
+ format: {
5691
+ propertyName: propName,
5692
+ type: getEntityName(target),
5693
+ },
5694
+ target: prop,
5695
+ }));
5696
+ }
5697
+ }
5698
+ }
4399
5699
  return [diagnostics.length === 0 ? Related.true : Related.false, diagnostics];
4400
5700
  }
5701
+ /** If we should check for excess properties on the given model. */
5702
+ function shouldCheckExcessProperties(model) {
5703
+ return model.node?.kind === SyntaxKind.ObjectLiteral;
5704
+ }
5705
+ /** If we should check for this specific property */
5706
+ function shouldCheckExcessProperty(prop) {
5707
+ return (prop.node?.kind === SyntaxKind.ObjectLiteralProperty && prop.node.parent === prop.model?.node);
5708
+ }
4401
5709
  function getProperty(model, name) {
4402
5710
  return (model.properties.get(name) ??
4403
5711
  (model.baseModel !== undefined ? getProperty(model.baseModel, name) : undefined));
@@ -4430,6 +5738,51 @@ export function createChecker(program) {
4430
5738
  }
4431
5739
  return isTypeAssignableToInternal(source.indexer.value, target.indexer.value, diagnosticTarget, relationCache);
4432
5740
  }
5741
+ function isTupleAssignableToArray(source, target, diagnosticTarget, relationCache) {
5742
+ const minItems = getMinItems(program, target);
5743
+ const maxItems = getMaxItems(program, target);
5744
+ if (minItems !== undefined && source.values.length < minItems) {
5745
+ return [
5746
+ Related.false,
5747
+ [
5748
+ createDiagnostic({
5749
+ code: "unassignable",
5750
+ messageId: "withDetails",
5751
+ format: {
5752
+ sourceType: getEntityName(source),
5753
+ targetType: getTypeName(target),
5754
+ details: `Source has ${source.values.length} element(s) but target requires ${minItems}.`,
5755
+ },
5756
+ target: diagnosticTarget,
5757
+ }),
5758
+ ],
5759
+ ];
5760
+ }
5761
+ if (maxItems !== undefined && source.values.length > maxItems) {
5762
+ return [
5763
+ Related.false,
5764
+ [
5765
+ createDiagnostic({
5766
+ code: "unassignable",
5767
+ messageId: "withDetails",
5768
+ format: {
5769
+ sourceType: getEntityName(source),
5770
+ targetType: getTypeName(target),
5771
+ details: `Source has ${source.values.length} element(s) but target only allows ${maxItems}.`,
5772
+ },
5773
+ target: diagnosticTarget,
5774
+ }),
5775
+ ],
5776
+ ];
5777
+ }
5778
+ for (const item of source.values) {
5779
+ const [related, diagnostics] = isTypeAssignableToInternal(item, target.indexer.value, diagnosticTarget, relationCache);
5780
+ if (!related) {
5781
+ return [Related.false, diagnostics];
5782
+ }
5783
+ }
5784
+ return [Related.true, []];
5785
+ }
4433
5786
  function isTupleAssignableToTuple(source, target, diagnosticTarget, relationCache) {
4434
5787
  if (source.values.length !== target.values.length) {
4435
5788
  return [
@@ -4439,7 +5792,7 @@ export function createChecker(program) {
4439
5792
  code: "unassignable",
4440
5793
  messageId: "withDetails",
4441
5794
  format: {
4442
- sourceType: getTypeName(source),
5795
+ sourceType: getEntityName(source),
4443
5796
  targetType: getTypeName(target),
4444
5797
  details: `Source has ${source.values.length} element(s) but target requires ${target.values.length}.`,
4445
5798
  },
@@ -4492,7 +5845,7 @@ export function createChecker(program) {
4492
5845
  function createUnassignableDiagnostic(source, target, diagnosticTarget) {
4493
5846
  return createDiagnostic({
4494
5847
  code: "unassignable",
4495
- format: { targetType: getTypeName(target), value: getTypeName(source) },
5848
+ format: { targetType: getEntityName(target), value: getEntityName(source) },
4496
5849
  target: diagnosticTarget,
4497
5850
  });
4498
5851
  }
@@ -4516,22 +5869,6 @@ export function createChecker(program) {
4516
5869
  function isAnonymous(type) {
4517
5870
  return !("name" in type) || typeof type.name !== "string" || !type.name;
4518
5871
  }
4519
- function isErrorType(type) {
4520
- return type.kind === "Intrinsic" && type.name === "ErrorType";
4521
- }
4522
- const numericRanges = {
4523
- int64: [BigInt("-9223372036854775807"), BigInt("9223372036854775808"), { int: true }],
4524
- int32: [-2147483648, 2147483647, { int: true }],
4525
- int16: [-32768, 32767, { int: true }],
4526
- int8: [-128, 127, { int: true }],
4527
- uint64: [0, BigInt("18446744073709551615"), { int: true }],
4528
- uint32: [0, 4294967295, { int: true }],
4529
- uint16: [0, 65535, { int: true }],
4530
- uint8: [0, 255, { int: true }],
4531
- safeint: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, { int: true }],
4532
- float32: [-3.4e38, 3.4e38, { int: false }],
4533
- float64: [-Number.MAX_VALUE, Number.MAX_VALUE, { int: false }],
4534
- };
4535
5872
  /**
4536
5873
  * Find all named models that could have been the source of the given
4537
5874
  * property. This includes the named parents of all property sources in a
@@ -4831,7 +6168,7 @@ function reportDeprecation(program, target, message, reportFunc) {
4831
6168
  function applyDecoratorToType(program, decApp, target) {
4832
6169
  compilerAssert("decorators" in target, "Cannot apply decorator to non-decoratable type", target);
4833
6170
  for (const arg of decApp.args) {
4834
- if (isErrorType(arg.value)) {
6171
+ if (isType(arg.value) && isErrorType(arg.value)) {
4835
6172
  // If one of the decorator argument is an error don't run it.
4836
6173
  return;
4837
6174
  }
@@ -4886,23 +6223,6 @@ function createDecoratorContext(program, decApp) {
4886
6223
  },
4887
6224
  };
4888
6225
  }
4889
- /**
4890
- * Convert TypeSpec argument to JS argument.
4891
- */
4892
- function marshalArgumentsForJS(args) {
4893
- return args.map((arg) => {
4894
- if (arg.kind === "Boolean" || arg.kind === "String" || arg.kind === "Number") {
4895
- return literalTypeToValue(arg);
4896
- }
4897
- else if (arg.kind === "StringTemplate") {
4898
- return stringTemplateToString(arg)[0];
4899
- }
4900
- return arg;
4901
- });
4902
- }
4903
- function literalTypeToValue(type) {
4904
- return type.value;
4905
- }
4906
6226
  function isTemplatedNode(node) {
4907
6227
  return "templateParameters" in node && node.templateParameters.length > 0;
4908
6228
  }
@@ -4926,9 +6246,10 @@ const ReflectionNameToKind = {
4926
6246
  const _assertReflectionNameToKind = ReflectionNameToKind;
4927
6247
  var ResolutionKind;
4928
6248
  (function (ResolutionKind) {
4929
- ResolutionKind[ResolutionKind["Type"] = 0] = "Type";
4930
- ResolutionKind[ResolutionKind["BaseType"] = 1] = "BaseType";
4931
- ResolutionKind[ResolutionKind["Constraint"] = 2] = "Constraint";
6249
+ ResolutionKind[ResolutionKind["Value"] = 0] = "Value";
6250
+ ResolutionKind[ResolutionKind["Type"] = 1] = "Type";
6251
+ ResolutionKind[ResolutionKind["BaseType"] = 2] = "BaseType";
6252
+ ResolutionKind[ResolutionKind["Constraint"] = 3] = "Constraint";
4932
6253
  })(ResolutionKind || (ResolutionKind = {}));
4933
6254
  class PendingResolutions {
4934
6255
  #data = new Map();
@@ -4964,4 +6285,19 @@ const defaultSymbolResolutionOptions = {
4964
6285
  resolveDecorators: false,
4965
6286
  checkTemplateTypes: true,
4966
6287
  };
6288
+ /**
6289
+ * Convert LEGACY for projection.
6290
+ * THIS IS BROKEN. Some decorators will not receive the correct type.
6291
+ * It has been broken since the introduction of valueof.
6292
+ * As projection as put on hold as long as versioning works we are in a good state.
6293
+ */
6294
+ function unsafe_projectionArgumentMarshalForJS(arg) {
6295
+ if (arg.kind === "Boolean" || arg.kind === "String" || arg.kind === "Number") {
6296
+ return arg.value;
6297
+ }
6298
+ else if (arg.kind === "StringTemplate") {
6299
+ return arg.stringValue;
6300
+ }
6301
+ return arg;
6302
+ }
4967
6303
  //# sourceMappingURL=checker.js.map