@typespec/compiler 1.9.0-dev.0 → 1.9.0-dev.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/manifest.js +2 -2
  2. package/dist/src/core/checker.d.ts.map +1 -1
  3. package/dist/src/core/checker.js +520 -393
  4. package/dist/src/core/checker.js.map +1 -1
  5. package/dist/src/core/cli/actions/compile/args.d.ts.map +1 -1
  6. package/dist/src/core/cli/actions/compile/args.js +3 -0
  7. package/dist/src/core/cli/actions/compile/args.js.map +1 -1
  8. package/dist/src/core/cli/actions/compile/compile.js +3 -1
  9. package/dist/src/core/cli/actions/compile/compile.js.map +1 -1
  10. package/dist/src/core/diagnostics.d.ts +2 -1
  11. package/dist/src/core/diagnostics.d.ts.map +1 -1
  12. package/dist/src/core/diagnostics.js +13 -7
  13. package/dist/src/core/diagnostics.js.map +1 -1
  14. package/dist/src/core/emitter-utils.d.ts +1 -1
  15. package/dist/src/core/emitter-utils.d.ts.map +1 -1
  16. package/dist/src/core/emitter-utils.js +12 -4
  17. package/dist/src/core/emitter-utils.js.map +1 -1
  18. package/dist/src/core/linter.d.ts.map +1 -1
  19. package/dist/src/core/linter.js +4 -4
  20. package/dist/src/core/linter.js.map +1 -1
  21. package/dist/src/core/perf.d.ts +12 -0
  22. package/dist/src/core/perf.d.ts.map +1 -0
  23. package/dist/src/core/perf.js +57 -0
  24. package/dist/src/core/perf.js.map +1 -0
  25. package/dist/src/core/program.d.ts.map +1 -1
  26. package/dist/src/core/program.js +20 -17
  27. package/dist/src/core/program.js.map +1 -1
  28. package/dist/src/core/stats.d.ts +6 -7
  29. package/dist/src/core/stats.d.ts.map +1 -1
  30. package/dist/src/core/stats.js +1 -18
  31. package/dist/src/core/stats.js.map +1 -1
  32. package/dist/src/core/type-relation-checker.d.ts.map +1 -1
  33. package/dist/src/core/type-relation-checker.js +3 -7
  34. package/dist/src/core/type-relation-checker.js.map +1 -1
  35. package/dist/src/core/type-utils.d.ts +17 -2
  36. package/dist/src/core/type-utils.d.ts.map +1 -1
  37. package/dist/src/core/type-utils.js +4 -9
  38. package/dist/src/core/type-utils.js.map +1 -1
  39. package/dist/src/core/types.d.ts +42 -0
  40. package/dist/src/core/types.d.ts.map +1 -1
  41. package/dist/src/index.d.ts.map +1 -1
  42. package/dist/src/index.js +2 -0
  43. package/dist/src/index.js.map +1 -1
  44. package/dist/src/lib/decorators.d.ts.map +1 -1
  45. package/dist/src/lib/decorators.js +1 -1
  46. package/dist/src/lib/decorators.js.map +1 -1
  47. package/dist/src/lib/examples.d.ts +21 -2
  48. package/dist/src/lib/examples.d.ts.map +1 -1
  49. package/dist/src/lib/examples.js +43 -10
  50. package/dist/src/lib/examples.js.map +1 -1
  51. package/dist/src/lib/paging.d.ts.map +1 -1
  52. package/dist/src/lib/paging.js +3 -14
  53. package/dist/src/lib/paging.js.map +1 -1
  54. package/dist/src/server/serverlib.d.ts.map +1 -1
  55. package/dist/src/server/serverlib.js +1 -1
  56. package/dist/src/server/serverlib.js.map +1 -1
  57. package/dist/src/typekit/kits/array.js +1 -1
  58. package/dist/src/typekit/kits/array.js.map +1 -1
  59. package/dist/src/typekit/kits/record.js +1 -1
  60. package/dist/src/typekit/kits/record.js.map +1 -1
  61. package/dist/src/utils/index.d.ts +1 -0
  62. package/dist/src/utils/index.d.ts.map +1 -1
  63. package/dist/src/utils/index.js +1 -0
  64. package/dist/src/utils/index.js.map +1 -1
  65. package/package.json +7 -7
@@ -7,7 +7,7 @@ import { createSymbol, getSymNode } from "./binder.js";
7
7
  import { createChangeIdentifierCodeFix } from "./compiler-code-fixes/change-identifier.codefix.js";
8
8
  import { createModelToObjectValueCodeFix, createTupleToArrayValueCodeFix, } from "./compiler-code-fixes/convert-to-value.codefix.js";
9
9
  import { getDeprecationDetails, markDeprecated } from "./deprecation.js";
10
- import { compilerAssert, ignoreDiagnostics } from "./diagnostics.js";
10
+ import { compilerAssert, ignoreDiagnostics, reportDeprecated } from "./diagnostics.js";
11
11
  import { validateInheritanceDiscriminatedUnions } from "./helpers/discriminator-utils.js";
12
12
  import { explainStringTemplateNotSerializable } from "./helpers/string-template-utils.js";
13
13
  import { typeReferenceToString } from "./helpers/syntax-utils.js";
@@ -19,6 +19,106 @@ import { exprIsBareIdentifier, getFirstAncestor, getIdentifierContext, hasParseE
19
19
  import { createTypeRelationChecker } from "./type-relation-checker.js";
20
20
  import { getFullyQualifiedSymbolName, getParentTemplateNode, isArrayModelType, isErrorType, isNullType, isTemplateInstance, isType, isValue, } from "./type-utils.js";
21
21
  import { IdentifierKind, ResolutionResultFlags, SyntaxKind, } from "./types.js";
22
+ var CheckFlags;
23
+ (function (CheckFlags) {
24
+ /** No flags set. */
25
+ CheckFlags[CheckFlags["None"] = 0] = "None";
26
+ /** Currently checking within an uninstantiated template declaration. */
27
+ CheckFlags[CheckFlags["InTemplateDeclaration"] = 1] = "InTemplateDeclaration";
28
+ })(CheckFlags || (CheckFlags = {}));
29
+ class CheckContext {
30
+ /** The type mapper associated with this context, if any. */
31
+ mapper;
32
+ /** The flags enabled in this context. */
33
+ flags;
34
+ #templateParametersObserved;
35
+ static from(contextOrMapper) {
36
+ if (contextOrMapper instanceof CheckContext) {
37
+ return contextOrMapper;
38
+ }
39
+ return new CheckContext(contextOrMapper, CheckFlags.None);
40
+ }
41
+ /**
42
+ * The default CheckContext to use at API entrypoints.
43
+ */
44
+ static DEFAULT = new CheckContext(undefined, CheckFlags.None);
45
+ constructor(mapper, flags, templateParametersObserved) {
46
+ this.mapper = mapper;
47
+ this.flags = flags;
48
+ this.#templateParametersObserved = templateParametersObserved;
49
+ Object.freeze(this);
50
+ }
51
+ /**
52
+ * Returns a new context with the given flags _added_ to the existing flags.
53
+ *
54
+ * @param flags - the flags to enable
55
+ * @returns a new CheckContext with the given flags enabled.
56
+ */
57
+ withFlags(flags) {
58
+ return new CheckContext(this.mapper, this.flags | flags, this.#templateParametersObserved);
59
+ }
60
+ /**
61
+ * Returns a new context with the given flags disabled.
62
+ *
63
+ * @param flags - the flags to disable
64
+ * @returns a new CheckContext with the given flags disabled.
65
+ */
66
+ maskFlags(flags) {
67
+ return new CheckContext(this.mapper, this.flags & ~flags, this.#templateParametersObserved);
68
+ }
69
+ /**
70
+ * Returns true if ALL of the given flags are enabled in this context.
71
+ */
72
+ hasFlags(flags) {
73
+ return (this.flags & flags) === flags;
74
+ }
75
+ /**
76
+ * Returns a new context with the given mapper.
77
+ *
78
+ * @param mapper - the new type mapper, or undefined to clear the mapper
79
+ * @returns a new CheckContext with the given mapper.
80
+ */
81
+ withMapper(mapper) {
82
+ return new CheckContext(mapper, this.flags, this.#templateParametersObserved);
83
+ }
84
+ /**
85
+ * Observes a template parameter within the current observation scope, if any.
86
+ *
87
+ * @param param - the TemplateParameter type instance to observe
88
+ */
89
+ observeTemplateParameter(param) {
90
+ this.#templateParametersObserved?.add(param);
91
+ }
92
+ /**
93
+ * Returns a new CheckContext with a new (empty) template parameter observation scope.
94
+ *
95
+ * Call this when you need to observe template parameters used within a specific context.
96
+ *
97
+ * @returns a new CheckContext with an empty template parameter observation scope.
98
+ */
99
+ enterTemplateObserverScope() {
100
+ return new CheckContext(this.mapper, this.flags, new Set());
101
+ }
102
+ /**
103
+ * Creates a new CheckContext with no template parameter observation enabled.
104
+ *
105
+ * Call this when the checker is moving from one declaration to another, where usage of template parameters
106
+ * from the next scope should not impact the usage from the previous scope.
107
+ *
108
+ * @returns a new CheckContext with no template parameter observation.
109
+ */
110
+ exitTemplateObserverScope() {
111
+ return new CheckContext(this.mapper, this.flags, undefined);
112
+ }
113
+ /**
114
+ * @returns true if the observer scope in this context has seen any template parameter usage.
115
+ */
116
+ hasObservedTemplateParameters() {
117
+ return this.#templateParametersObserved !== undefined
118
+ ? this.#templateParametersObserved.size > 0
119
+ : false;
120
+ }
121
+ }
22
122
  /**
23
123
  * Maps type arguments to type instantiation.
24
124
  */
@@ -140,10 +240,10 @@ export function createChecker(program, resolver) {
140
240
  const sym = typespecNamespaceBinding?.exports?.get(name);
141
241
  compilerAssert(sym, `Unexpected missing symbol to std type "${name}"`);
142
242
  if (sym.flags & 2 /* SymbolFlags.Model */) {
143
- checkModelStatement(sym.declarations[0], undefined);
243
+ checkModelStatement(CheckContext.DEFAULT, sym.declarations[0]);
144
244
  }
145
245
  else {
146
- checkScalar(sym.declarations[0], undefined);
246
+ checkScalar(CheckContext.DEFAULT, sym.declarations[0]);
147
247
  }
148
248
  const loadedType = stdTypes[name];
149
249
  compilerAssert(loadedType, `TypeSpec std type "${name}" should have been initalized before using array syntax.`);
@@ -157,17 +257,17 @@ export function createChecker(program, resolver) {
157
257
  * @param type Type
158
258
  * @param mapper Type mapper if in an template instantiation
159
259
  */
160
- function linkType(links, type, mapper) {
161
- if (mapper === undefined) {
260
+ function linkType(ctx, links, type) {
261
+ if (ctx.mapper === undefined) {
162
262
  links.declaredType = type;
163
263
  links.instantiations = new TypeInstantiationMap();
164
264
  }
165
265
  else if (links.instantiations) {
166
- links.instantiations.set(mapper.args, type);
266
+ links.instantiations.set(ctx.mapper.args, type);
167
267
  }
168
268
  }
169
- function linkMemberType(links, type, mapper) {
170
- if (mapper === undefined) {
269
+ function linkMemberType(ctx, links, type) {
270
+ if (ctx.mapper === undefined) {
171
271
  links.declaredType = type;
172
272
  }
173
273
  }
@@ -177,15 +277,15 @@ export function createChecker(program, resolver) {
177
277
  * @param mapper Type mapper.
178
278
  * @returns Checked type for the given member symbol.
179
279
  */
180
- function checkMemberSym(sym, mapper) {
280
+ function checkMemberSym(ctx, sym) {
181
281
  const symbolLinks = getSymbolLinks(sym);
182
- const memberContainer = getTypeForNode(getSymNode(sym.parent), mapper);
282
+ const memberContainer = getTypeForNode(getSymNode(sym.parent), ctx);
183
283
  const type = symbolLinks.declaredType ?? symbolLinks.type;
184
284
  if (type) {
185
285
  return type;
186
286
  }
187
287
  else {
188
- return checkMember(getSymNode(sym), mapper, memberContainer);
288
+ return checkMember(ctx, getSymNode(sym), memberContainer);
189
289
  }
190
290
  }
191
291
  /**
@@ -195,18 +295,18 @@ export function createChecker(program, resolver) {
195
295
  * @param containerType Member node container type(Interface, Model, Union, etc.)
196
296
  * @returns Checked member
197
297
  */
198
- function checkMember(node, mapper, containerType) {
298
+ function checkMember(ctx, node, containerType) {
199
299
  switch (node.kind) {
200
300
  case SyntaxKind.ModelProperty:
201
- return checkModelProperty(node, mapper);
301
+ return checkModelProperty(ctx, node);
202
302
  case SyntaxKind.EnumMember:
203
- return checkEnumMember(node, mapper, containerType);
303
+ return checkEnumMember(ctx, node, containerType);
204
304
  case SyntaxKind.OperationStatement:
205
- return checkOperation(node, mapper, containerType);
305
+ return checkOperation(ctx, node, containerType);
206
306
  case SyntaxKind.UnionVariant:
207
- return checkUnionVariant(node, mapper);
307
+ return checkUnionVariant(ctx, node);
208
308
  case SyntaxKind.ScalarConstructor:
209
- return checkScalarConstructor(node, mapper, containerType);
309
+ return checkScalarConstructor(ctx, node, containerType);
210
310
  }
211
311
  }
212
312
  function getTypeForTypeOrIndeterminate(entity) {
@@ -215,8 +315,9 @@ export function createChecker(program, resolver) {
215
315
  }
216
316
  return entity;
217
317
  }
218
- function getTypeForNode(node, mapper) {
219
- const entity = checkNode(node, mapper);
318
+ function getTypeForNode(node, mapperOrContext) {
319
+ const ctx = CheckContext.from(mapperOrContext);
320
+ const entity = checkNode(ctx, node);
220
321
  if (entity === null) {
221
322
  return errorType;
222
323
  }
@@ -242,8 +343,9 @@ export function createChecker(program, resolver) {
242
343
  }
243
344
  return entity;
244
345
  }
245
- function getValueForNode(node, mapper, constraint) {
246
- const initial = checkNode(node, mapper, constraint);
346
+ function getValueForNode(node, mapperOrContext, constraint) {
347
+ const ctx = CheckContext.from(mapperOrContext);
348
+ const initial = checkNode(ctx, node, constraint);
247
349
  if (initial === null) {
248
350
  return null;
249
351
  }
@@ -264,7 +366,9 @@ export function createChecker(program, resolver) {
264
366
  if (entity.kind === "TemplateParameter" &&
265
367
  entity.constraint?.valueType &&
266
368
  entity.constraint.type === undefined &&
267
- mapper === undefined) {
369
+ ctx.mapper === undefined) {
370
+ // We must also observe that the template parameter is used here.
371
+ // ctx.observeTemplateParameter(entity);
268
372
  return createValue({
269
373
  entityKind: "Value",
270
374
  valueKind: "TemplateValue",
@@ -374,8 +478,9 @@ export function createChecker(program, resolver) {
374
478
  * This means that if the constraint is `string | valueof string` passing `"abc"` will send the value `"abc"` and not the type `"abc"`.
375
479
  */
376
480
  function getTypeOrValueForNode(node, mapper, constraint) {
481
+ const ctx = CheckContext.from(mapper);
377
482
  const valueConstraint = extractValueOfConstraints(constraint);
378
- const entity = checkNode(node, mapper, valueConstraint);
483
+ const entity = checkNode(ctx, node, valueConstraint);
379
484
  if (entity === null) {
380
485
  return entity;
381
486
  }
@@ -419,33 +524,33 @@ export function createChecker(program, resolver) {
419
524
  * For nodes that can be both type or values(e.g. string literals), an indeterminate entity will be returned.
420
525
  * It is the job of of the consumer to decide if it should be a type or a value depending on the context.
421
526
  */
422
- function checkNode(node, mapper, valueConstraint) {
527
+ function checkNode(ctx, node, valueConstraint) {
423
528
  switch (node.kind) {
424
529
  case SyntaxKind.ModelExpression:
425
- return checkModel(node, mapper);
530
+ return checkModel(ctx, node);
426
531
  case SyntaxKind.ModelStatement:
427
- return checkModel(node, mapper);
532
+ return checkModel(ctx, node);
428
533
  case SyntaxKind.ModelProperty:
429
- return checkModelProperty(node, mapper);
534
+ return checkModelProperty(ctx, node);
430
535
  case SyntaxKind.ScalarStatement:
431
- return checkScalar(node, mapper);
536
+ return checkScalar(ctx, node);
432
537
  case SyntaxKind.AliasStatement:
433
- return checkAlias(node, mapper);
538
+ return checkAlias(ctx, node);
434
539
  case SyntaxKind.EnumStatement:
435
- return checkEnum(node, mapper);
540
+ return checkEnum(ctx, node);
436
541
  case SyntaxKind.EnumMember:
437
- return checkEnumMember(node, mapper);
542
+ return checkEnumMember(ctx, node);
438
543
  case SyntaxKind.InterfaceStatement:
439
- return checkInterface(node, mapper);
544
+ return checkInterface(ctx, node);
440
545
  case SyntaxKind.UnionStatement:
441
- return checkUnion(node, mapper);
546
+ return checkUnion(ctx, node);
442
547
  case SyntaxKind.UnionVariant:
443
- return checkUnionVariant(node, mapper);
548
+ return checkUnionVariant(ctx, node);
444
549
  case SyntaxKind.NamespaceStatement:
445
550
  case SyntaxKind.JsNamespaceDeclaration:
446
- return checkNamespace(node);
551
+ return checkNamespace(ctx, node);
447
552
  case SyntaxKind.OperationStatement:
448
- return checkOperation(node, mapper);
553
+ return checkOperation(ctx, node);
449
554
  case SyntaxKind.NumericLiteral:
450
555
  return checkNumericLiteral(node);
451
556
  case SyntaxKind.BooleanLiteral:
@@ -453,25 +558,25 @@ export function createChecker(program, resolver) {
453
558
  case SyntaxKind.StringLiteral:
454
559
  return checkStringLiteral(node);
455
560
  case SyntaxKind.TupleExpression:
456
- return checkTupleExpression(node, mapper);
561
+ return checkTupleExpression(ctx, node);
457
562
  case SyntaxKind.StringTemplateExpression:
458
- return checkStringTemplateExpresion(node, mapper);
563
+ return checkStringTemplateExpresion(ctx, node);
459
564
  case SyntaxKind.ArrayExpression:
460
- return checkArrayExpression(node, mapper);
565
+ return checkArrayExpression(ctx, node);
461
566
  case SyntaxKind.UnionExpression:
462
- return checkUnionExpression(node, mapper);
567
+ return checkUnionExpression(ctx, node);
463
568
  case SyntaxKind.IntersectionExpression:
464
- return checkIntersectionExpression(node, mapper);
569
+ return checkIntersectionExpression(ctx, node);
465
570
  case SyntaxKind.DecoratorDeclarationStatement:
466
- return checkDecoratorDeclaration(node, mapper);
571
+ return checkDecoratorDeclaration(ctx, node);
467
572
  case SyntaxKind.FunctionDeclarationStatement:
468
- return checkFunctionDeclaration(node, mapper);
573
+ return checkFunctionDeclaration(ctx, node);
469
574
  case SyntaxKind.TypeReference:
470
- return checkTypeOrValueReference(node, mapper);
575
+ return checkTypeOrValueReference(ctx, node);
471
576
  case SyntaxKind.TemplateArgument:
472
- return checkTemplateArgument(node, mapper);
577
+ return checkTemplateArgument(ctx, node);
473
578
  case SyntaxKind.TemplateParameterDeclaration:
474
- return checkTemplateParameterDeclaration(node, mapper);
579
+ return checkTemplateParameterDeclaration(ctx, node);
475
580
  case SyntaxKind.VoidKeyword:
476
581
  return voidType;
477
582
  case SyntaxKind.NeverKeyword:
@@ -479,19 +584,19 @@ export function createChecker(program, resolver) {
479
584
  case SyntaxKind.UnknownKeyword:
480
585
  return unknownType;
481
586
  case SyntaxKind.ObjectLiteral:
482
- return checkObjectValue(node, mapper, valueConstraint);
587
+ return checkObjectValue(ctx, node, valueConstraint);
483
588
  case SyntaxKind.ArrayLiteral:
484
- return checkArrayValue(node, mapper, valueConstraint);
589
+ return checkArrayValue(ctx, node, valueConstraint);
485
590
  case SyntaxKind.ConstStatement:
486
591
  return checkConst(node);
487
592
  case SyntaxKind.CallExpression:
488
- return checkCallExpression(node, mapper);
593
+ return checkCallExpression(ctx, node);
489
594
  case SyntaxKind.TypeOfExpression:
490
- return checkTypeOfExpression(node, mapper);
595
+ return checkTypeOfExpression(ctx, node);
491
596
  case SyntaxKind.AugmentDecoratorStatement:
492
- return checkAugmentDecorator(node);
597
+ return checkAugmentDecorator(ctx, node);
493
598
  case SyntaxKind.UsingStatement:
494
- return checkUsings(node);
599
+ return checkUsings(ctx, node);
495
600
  default:
496
601
  return errorType;
497
602
  }
@@ -518,7 +623,7 @@ export function createChecker(program, resolver) {
518
623
  function isInTypeSpecNamespace(type) {
519
624
  return Boolean(type.namespace && isTypeSpecNamespace(type.namespace));
520
625
  }
521
- function checkTemplateParameterDeclaration(node, mapper) {
626
+ function checkTemplateParameterDeclaration(ctx, node) {
522
627
  const parentNode = node.parent;
523
628
  const grandParentNode = parentNode.parent;
524
629
  const links = getSymbolLinks(node.symbol);
@@ -526,7 +631,7 @@ export function createChecker(program, resolver) {
526
631
  templateParameterUsageMap.set(node, false);
527
632
  }
528
633
  if (pendingResolutions.has(getNodeSym(node), ResolutionKind.Constraint)) {
529
- if (mapper === undefined) {
634
+ if (ctx.mapper === undefined) {
530
635
  reportCheckerDiagnostic(createDiagnostic({
531
636
  code: "circular-constraint",
532
637
  format: { typeName: node.id.sv },
@@ -553,18 +658,18 @@ export function createChecker(program, resolver) {
553
658
  });
554
659
  if (node.constraint) {
555
660
  pendingResolutions.start(getNodeSym(node), ResolutionKind.Constraint);
556
- type.constraint = getParamConstraintEntityForNode(node.constraint);
661
+ type.constraint = getParamConstraintEntityForNode(ctx, node.constraint);
557
662
  pendingResolutions.finish(getNodeSym(node), ResolutionKind.Constraint);
558
663
  }
559
664
  if (node.default) {
560
665
  // Set this to unknownType in case the default points back to the template itself causing failures
561
666
  type.default = unknownType;
562
- type.default = checkTemplateParameterDefault(node.default, parentNode.templateParameters, index, type.constraint);
667
+ type.default = checkTemplateParameterDefault(ctx, node.default, parentNode.templateParameters, index, type.constraint);
563
668
  }
564
669
  }
565
- return mapper ? mapper.getMappedType(type) : type;
670
+ return ctx.mapper ? ctx.mapper.getMappedType(type) : type;
566
671
  }
567
- function getResolvedTypeParameterDefault(declaredType, node, mapper) {
672
+ function getResolvedTypeParameterDefault(ctx, declaredType, node) {
568
673
  if (declaredType.default === undefined) {
569
674
  return undefined;
570
675
  }
@@ -572,11 +677,11 @@ export function createChecker(program, resolver) {
572
677
  declaredType.default === null) {
573
678
  return declaredType.default;
574
679
  }
575
- return checkNode(node.default, mapper);
680
+ return checkNode(ctx, node.default);
576
681
  }
577
- function checkTemplateParameterDefault(nodeDefault, templateParameters, index, constraint) {
682
+ function checkTemplateParameterDefault(ctx, nodeDefault, templateParameters, index, constraint) {
578
683
  function visit(node) {
579
- const entity = checkNode(node);
684
+ const entity = checkNode(ctx, node);
580
685
  let hasError = false;
581
686
  if (entity !== null && "kind" in entity && entity.kind === "TemplateParameter") {
582
687
  for (let i = index; i < templateParameters.length; i++) {
@@ -608,12 +713,12 @@ export function createChecker(program, resolver) {
608
713
  * @param instantiateTemplate If templated type should be instantiated if they haven't yet.
609
714
  * @returns Resolved type.
610
715
  */
611
- function checkTypeReference(node, mapper, instantiateTemplate = true) {
612
- const sym = resolveTypeReferenceSym(node, mapper);
716
+ function checkTypeReference(ctx, node, instantiateTemplate = true) {
717
+ const sym = resolveTypeReferenceSym(ctx, node);
613
718
  if (!sym) {
614
719
  return errorType;
615
720
  }
616
- const type = checkTypeReferenceSymbol(sym, node, mapper, instantiateTemplate);
721
+ const type = checkTypeReferenceSymbol(ctx, sym, node, instantiateTemplate);
617
722
  return type;
618
723
  }
619
724
  /**
@@ -623,21 +728,21 @@ export function createChecker(program, resolver) {
623
728
  * @param instantiateTemplate If templated type should be instantiated if they haven't yet.
624
729
  * @returns Resolved type.
625
730
  */
626
- function checkTypeOrValueReference(node, mapper, instantiateTemplate = true) {
627
- const sym = resolveTypeReferenceSym(node, mapper);
731
+ function checkTypeOrValueReference(ctx, node, instantiateTemplate = true) {
732
+ const sym = resolveTypeReferenceSym(ctx, node);
628
733
  if (!sym) {
629
734
  return errorType;
630
735
  }
631
- return checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplate) ?? errorType;
736
+ return checkTypeOrValueReferenceSymbol(ctx, sym, node, instantiateTemplate) ?? errorType;
632
737
  }
633
- function checkTemplateArgument(node, mapper) {
634
- return checkNode(node.argument, mapper);
738
+ function checkTemplateArgument(ctx, node) {
739
+ return checkNode(ctx, node.argument);
635
740
  }
636
741
  function resolveTypeOrValueReference(node) {
637
742
  const oldDiagnosticHook = onCheckerDiagnostic;
638
743
  const diagnostics = [];
639
744
  onCheckerDiagnostic = (x) => diagnostics.push(x);
640
- const entity = checkTypeOrValueReference(node, undefined, false);
745
+ const entity = checkTypeOrValueReference(CheckContext.DEFAULT, node, false);
641
746
  onCheckerDiagnostic = oldDiagnosticHook;
642
747
  return [entity === errorType ? undefined : entity, diagnostics];
643
748
  }
@@ -645,7 +750,7 @@ export function createChecker(program, resolver) {
645
750
  const oldDiagnosticHook = onCheckerDiagnostic;
646
751
  const diagnostics = [];
647
752
  onCheckerDiagnostic = (x) => diagnostics.push(x);
648
- const type = checkTypeReference(node, undefined, false);
753
+ const type = checkTypeReference(CheckContext.DEFAULT, node, false);
649
754
  onCheckerDiagnostic = oldDiagnosticHook;
650
755
  return [type === errorType ? undefined : type, diagnostics];
651
756
  }
@@ -659,13 +764,13 @@ export function createChecker(program, resolver) {
659
764
  if (node) {
660
765
  const deprecationDetails = getDeprecationDetails(program, node);
661
766
  if (deprecationDetails) {
662
- reportDeprecation(program, target, deprecationDetails.message, reportCheckerDiagnostic);
767
+ reportDeprecated(program, deprecationDetails.message, target, reportCheckerDiagnostic);
663
768
  return;
664
769
  }
665
770
  }
666
771
  const deprecationDetails = getDeprecationDetails(program, type);
667
772
  if (deprecationDetails) {
668
- reportDeprecation(program, target, deprecationDetails.message, reportCheckerDiagnostic);
773
+ reportDeprecated(program, deprecationDetails.message, target, reportCheckerDiagnostic);
669
774
  }
670
775
  }
671
776
  function isTypeReferenceContextDeprecated(node) {
@@ -702,11 +807,11 @@ export function createChecker(program, resolver) {
702
807
  return false;
703
808
  }
704
809
  }
705
- function checkTemplateInstantiationArgs(node, args, decls, mapper, parentMapper) {
810
+ function checkTemplateInstantiationArgs(ctx, node, args, decls, parentMapper) {
706
811
  const params = new Map();
707
812
  const positional = [];
708
813
  const initMap = new Map(decls.map((decl) => {
709
- const declaredType = checkTemplateParameterDeclaration(decl, undefined);
814
+ const declaredType = checkTemplateParameterDeclaration(CheckContext.DEFAULT, decl);
710
815
  positional.push(declaredType);
711
816
  params.set(decl.id.sv, declaredType);
712
817
  return [
@@ -720,7 +825,7 @@ export function createChecker(program, resolver) {
720
825
  let named = false;
721
826
  for (const [arg, idx] of args.map((v, i) => [v, i])) {
722
827
  function deferredCheck() {
723
- return [arg, checkNode(arg.argument, mapper)];
828
+ return [arg, checkNode(ctx, arg.argument)];
724
829
  }
725
830
  if (arg.name) {
726
831
  named = true;
@@ -780,8 +885,8 @@ export function createChecker(program, resolver) {
780
885
  mapperArgs.push(type);
781
886
  }
782
887
  if (init === null) {
783
- const argumentMapper = createTypeMapper(mapperParams, mapperArgs, { node, mapper }, parentMapper);
784
- const defaultValue = getResolvedTypeParameterDefault(param, decl, argumentMapper);
888
+ const argumentMapper = createTypeMapper(mapperParams, mapperArgs, { node, mapper: ctx.mapper }, parentMapper);
889
+ const defaultValue = getResolvedTypeParameterDefault(ctx.withMapper(argumentMapper), param, decl);
785
890
  if (defaultValue) {
786
891
  commit(param, defaultValue);
787
892
  }
@@ -850,8 +955,8 @@ export function createChecker(program, resolver) {
850
955
  * @param instantiateTemplates If a templated type should be instantiated if not yet @default true
851
956
  * @returns resolved type.
852
957
  */
853
- function checkTypeReferenceSymbol(sym, node, mapper, instantiateTemplates = true) {
854
- const result = checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplates);
958
+ function checkTypeReferenceSymbol(ctx, sym, node, instantiateTemplates = true) {
959
+ const result = checkTypeOrValueReferenceSymbol(ctx, sym, node, instantiateTemplates);
855
960
  if (result === null || isValue(result)) {
856
961
  reportCheckerDiagnostic(createDiagnostic({ code: "value-in-type", target: node }));
857
962
  return errorType;
@@ -861,16 +966,17 @@ export function createChecker(program, resolver) {
861
966
  }
862
967
  return result;
863
968
  }
864
- function checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplates = true) {
865
- const entity = checkTypeOrValueReferenceSymbolWorker(sym, node, mapper, instantiateTemplates);
969
+ function checkTypeOrValueReferenceSymbol(ctx, sym, node, instantiateTemplates = true) {
970
+ const entity = checkTypeOrValueReferenceSymbolWorker(ctx, sym, node, instantiateTemplates);
866
971
  if (entity !== null && isType(entity) && entity.kind === "TemplateParameter") {
972
+ ctx.observeTemplateParameter(entity);
867
973
  templateParameterUsageMap.set(entity.node, true);
868
974
  }
869
975
  return entity;
870
976
  }
871
- function checkTypeOrValueReferenceSymbolWorker(sym, node, mapper, instantiateTemplates = true) {
977
+ function checkTypeOrValueReferenceSymbolWorker(ctx, sym, node, instantiateTemplates = true) {
872
978
  if (sym.flags & 131072 /* SymbolFlags.Const */) {
873
- return getValueForNode(sym.declarations[0], mapper);
979
+ return getValueForNode(sym.declarations[0], ctx.mapper);
874
980
  }
875
981
  if (sym.flags & 512 /* SymbolFlags.Decorator */) {
876
982
  reportCheckerDiagnostic(createDiagnostic({ code: "invalid-type-ref", messageId: "decorator", target: sym }));
@@ -893,6 +999,12 @@ export function createChecker(program, resolver) {
893
999
  64 /* SymbolFlags.Union */)) {
894
1000
  const decl = sym.declarations[0];
895
1001
  if (!isTemplatedNode(decl)) {
1002
+ // Not a templated node, and we are moving through a typeref to a new declaration.
1003
+ // Therefore, we are no longer in a template declaration if we were before, and we are
1004
+ // visiting a new declaration, so we exit the active template observer scope, if any.
1005
+ const innerCtx = ctx
1006
+ .maskFlags(CheckFlags.InTemplateDeclaration)
1007
+ .exitTemplateObserverScope();
896
1008
  if (argumentNodes.length > 0) {
897
1009
  reportCheckerDiagnostic(createDiagnostic({
898
1010
  code: "invalid-template-args",
@@ -908,17 +1020,26 @@ export function createChecker(program, resolver) {
908
1020
  baseType = symbolLinks.declaredType;
909
1021
  }
910
1022
  else if (sym.flags & 65536 /* SymbolFlags.Member */) {
911
- baseType = checkMemberSym(sym, mapper);
1023
+ baseType = checkMemberSym(innerCtx, sym);
912
1024
  }
913
1025
  else {
914
- baseType = checkDeclaredTypeOrIndeterminate(sym, decl, mapper);
1026
+ //
1027
+ baseType = checkDeclaredTypeOrIndeterminate(innerCtx, sym, decl);
915
1028
  }
916
1029
  }
917
1030
  else {
918
- const declaredType = getOrCheckDeclaredType(sym, decl, mapper);
1031
+ // Checking the declaration to ensure we have the template itself, so we don't need the mapper.
1032
+ const declaredType = getOrCheckDeclaredType(ctx.withMapper(undefined), sym, decl);
919
1033
  const templateParameters = decl.templateParameters;
920
- const instantiation = checkTemplateInstantiationArgs(node, argumentNodes, templateParameters, mapper, declaredType.templateMapper);
921
- baseType = getOrInstantiateTemplate(decl, [...instantiation.keys()], [...instantiation.values()], { node, mapper }, declaredType.templateMapper, instantiateTemplates);
1034
+ const instantiationArgsCtx = ctx.enterTemplateObserverScope();
1035
+ const instantiation = checkTemplateInstantiationArgs(instantiationArgsCtx, node, argumentNodes, templateParameters, declaredType.templateMapper);
1036
+ // If we didn't see any template parameters during argument checking, then this type reference is "pure"
1037
+ // and we can mask the InTemplateDeclaration flag downstream. In either case, we are going to a new declaration
1038
+ // so we exit the active template observer scope, if any.
1039
+ const innerCtx = (instantiationArgsCtx.hasObservedTemplateParameters()
1040
+ ? ctx
1041
+ : ctx.maskFlags(CheckFlags.InTemplateDeclaration)).exitTemplateObserverScope();
1042
+ baseType = getOrInstantiateTemplate(innerCtx, decl, [...instantiation.keys()], [...instantiation.values()], { node, mapper: ctx.mapper }, declaredType.templateMapper, instantiateTemplates);
922
1043
  }
923
1044
  }
924
1045
  else {
@@ -936,7 +1057,7 @@ export function createChecker(program, resolver) {
936
1057
  return sym.type;
937
1058
  }
938
1059
  else if (sym.flags & 1024 /* SymbolFlags.TemplateParameter */) {
939
- const mapped = checkTemplateParameterDeclaration(symNode, mapper);
1060
+ const mapped = checkTemplateParameterDeclaration(ctx, symNode);
940
1061
  baseType = mapped;
941
1062
  }
942
1063
  else if (symbolLinks.type) {
@@ -948,11 +1069,11 @@ export function createChecker(program, resolver) {
948
1069
  }
949
1070
  else {
950
1071
  if (sym.flags & 65536 /* SymbolFlags.Member */) {
951
- baseType = checkMemberSym(sym, mapper);
1072
+ baseType = checkMemberSym(ctx, sym);
952
1073
  }
953
1074
  else {
954
1075
  // don't have a cached type for this symbol, so go grab it and cache it
955
- baseType = getTypeForNode(symNode, mapper);
1076
+ baseType = getTypeForNode(symNode, ctx);
956
1077
  symbolLinks.type = baseType;
957
1078
  }
958
1079
  }
@@ -961,7 +1082,7 @@ export function createChecker(program, resolver) {
961
1082
  // don't raise deprecation when the usage site is also a deprecated
962
1083
  // declaration.
963
1084
  const declarationNode = getSymNode(sym);
964
- if (declarationNode && mapper === undefined && isType(baseType)) {
1085
+ if (declarationNode && ctx.mapper === undefined && isType(baseType)) {
965
1086
  if (!isTypeReferenceContextDeprecated(node.parent)) {
966
1087
  checkDeprecated(baseType, declarationNode, node);
967
1088
  }
@@ -980,7 +1101,7 @@ export function createChecker(program, resolver) {
980
1101
  * @param mapper Type mapper for template resolution
981
1102
  * @returns The declared type for the given node.
982
1103
  */
983
- function getOrCheckDeclaredType(sym, decl, mapper) {
1104
+ function getOrCheckDeclaredType(ctx, sym, decl) {
984
1105
  const symbolLinks = getSymbolLinks(sym);
985
1106
  if (symbolLinks.declaredType) {
986
1107
  return symbolLinks.declaredType;
@@ -990,10 +1111,10 @@ export function createChecker(program, resolver) {
990
1111
  return sym.type;
991
1112
  }
992
1113
  if (sym.flags & 65536 /* SymbolFlags.Member */) {
993
- return checkMemberSym(sym, mapper);
1114
+ return checkMemberSym(ctx, sym);
994
1115
  }
995
1116
  else {
996
- return checkDeclaredType(sym, decl, mapper);
1117
+ return checkDeclaredType(ctx, sym, decl);
997
1118
  }
998
1119
  }
999
1120
  /**
@@ -1003,24 +1124,24 @@ export function createChecker(program, resolver) {
1003
1124
  * @param mapper Type mapper for template resolution
1004
1125
  * @returns The declared type for the given node.
1005
1126
  */
1006
- function checkDeclaredTypeOrIndeterminate(sym, node, mapper) {
1127
+ function checkDeclaredTypeOrIndeterminate(ctx, sym, node) {
1007
1128
  const type = sym.flags & 2 /* SymbolFlags.Model */
1008
- ? checkModelStatement(node, mapper)
1129
+ ? checkModelStatement(ctx, node)
1009
1130
  : sym.flags & 4 /* SymbolFlags.Scalar */
1010
- ? checkScalar(node, mapper)
1131
+ ? checkScalar(ctx, node)
1011
1132
  : sym.flags & 128 /* SymbolFlags.Alias */
1012
- ? checkAlias(node, mapper)
1133
+ ? checkAlias(ctx, node)
1013
1134
  : sym.flags & 32 /* SymbolFlags.Interface */
1014
- ? checkInterface(node, mapper)
1135
+ ? checkInterface(ctx, node)
1015
1136
  : sym.flags & 8 /* SymbolFlags.Operation */
1016
- ? checkOperation(node, mapper)
1017
- : checkUnion(node, mapper);
1137
+ ? checkOperation(ctx, node)
1138
+ : checkUnion(ctx, node);
1018
1139
  return type;
1019
1140
  }
1020
- function checkDeclaredType(sym, node, mapper) {
1021
- return getTypeForTypeOrIndeterminate(checkDeclaredTypeOrIndeterminate(sym, node, mapper));
1141
+ function checkDeclaredType(ctx, sym, node) {
1142
+ return getTypeForTypeOrIndeterminate(checkDeclaredTypeOrIndeterminate(ctx, sym, node));
1022
1143
  }
1023
- function getOrInstantiateTemplate(templateNode, params, args, source, parentMapper, instantiateTempalates = true) {
1144
+ function getOrInstantiateTemplate(ctx, templateNode, params, args, source, parentMapper, instantiateTempalates = true) {
1024
1145
  const symbolLinks = templateNode.kind === SyntaxKind.OperationStatement &&
1025
1146
  templateNode.parent.kind === SyntaxKind.InterfaceStatement
1026
1147
  ? getSymbolLinksForMember(templateNode)
@@ -1041,7 +1162,7 @@ export function createChecker(program, resolver) {
1041
1162
  return cached;
1042
1163
  }
1043
1164
  if (instantiateTempalates) {
1044
- return instantiateTemplate(symbolLinks.instantiations, templateNode, params, mapper);
1165
+ return instantiateTemplate(ctx.withMapper(mapper), symbolLinks.instantiations, templateNode, params);
1045
1166
  }
1046
1167
  else {
1047
1168
  return errorType;
@@ -1056,10 +1177,10 @@ export function createChecker(program, resolver) {
1056
1177
  * twice at the same time, or if template parameters from more than one template
1057
1178
  * are ever in scope at once.
1058
1179
  */
1059
- function instantiateTemplate(instantiations, templateNode, params, mapper) {
1060
- const type = getTypeForNode(templateNode, mapper);
1061
- if (!instantiations.get(mapper.args)) {
1062
- instantiations.set(mapper.args, type);
1180
+ function instantiateTemplate(ctx, instantiations, templateNode, params) {
1181
+ const type = getTypeForNode(templateNode, ctx);
1182
+ if (!instantiations.get(ctx.mapper.args)) {
1183
+ instantiations.set(ctx.mapper.args, type);
1063
1184
  }
1064
1185
  if (type.kind === "Model") {
1065
1186
  type.templateNode = templateNode;
@@ -1067,11 +1188,11 @@ export function createChecker(program, resolver) {
1067
1188
  return type;
1068
1189
  }
1069
1190
  /** Check a union expresion used in a parameter constraint, those allow the use of `valueof` as a variant. */
1070
- function checkMixedParameterConstraintUnion(node, mapper) {
1191
+ function checkMixedParameterConstraintUnion(ctx, node) {
1071
1192
  const values = [];
1072
1193
  const types = [];
1073
1194
  for (const option of node.options) {
1074
- const [kind, type] = getTypeOrValueOfTypeForNode(option, mapper);
1195
+ const [kind, type] = getTypeOrValueOfTypeForNode(ctx, option);
1075
1196
  if (kind === "value") {
1076
1197
  values.push(type);
1077
1198
  }
@@ -1117,7 +1238,7 @@ export function createChecker(program, resolver) {
1117
1238
  }
1118
1239
  return union;
1119
1240
  }
1120
- function checkUnionExpression(node, mapper) {
1241
+ function checkUnionExpression(ctx, node) {
1121
1242
  const unionType = createAndFinishType({
1122
1243
  kind: "Union",
1123
1244
  node,
@@ -1130,7 +1251,7 @@ export function createChecker(program, resolver) {
1130
1251
  decorators: [],
1131
1252
  });
1132
1253
  for (const o of node.options) {
1133
- const type = getTypeForNode(o, mapper);
1254
+ const type = getTypeForNode(o, ctx);
1134
1255
  // The type `A | never` is just `A`
1135
1256
  if (type === neverType) {
1136
1257
  continue;
@@ -1152,7 +1273,7 @@ export function createChecker(program, resolver) {
1152
1273
  unionType.variants.set(variant.name, variant);
1153
1274
  }
1154
1275
  }
1155
- linkMapper(unionType, mapper);
1276
+ linkMapper(unionType, ctx.mapper);
1156
1277
  return unionType;
1157
1278
  }
1158
1279
  /**
@@ -1160,17 +1281,17 @@ export function createChecker(program, resolver) {
1160
1281
  * So this doesn't work if we don't have a known set of properties (e.g.
1161
1282
  * with unions). The resulting model is anonymous.
1162
1283
  */
1163
- function checkIntersectionExpression(node, mapper) {
1284
+ function checkIntersectionExpression(ctx, node) {
1164
1285
  const links = getSymbolLinks(node.symbol);
1165
- if (links.declaredType && mapper === undefined) {
1286
+ if (links.declaredType && ctx.mapper === undefined) {
1166
1287
  // we're not instantiating this model and we've already checked it
1167
1288
  return links.declaredType;
1168
1289
  }
1169
1290
  const intersection = initModel(node);
1170
- const options = node.options.map((o) => [o, getTypeForNode(o, mapper)]);
1291
+ const options = node.options.map((o) => [o, getTypeForNode(o, ctx)]);
1171
1292
  ensureResolved(options.map(([, type]) => type), intersection, () => {
1172
- const type = mergeModelTypes(node.symbol, node, options, mapper, intersection);
1173
- linkType(links, type, mapper);
1293
+ const type = mergeModelTypes(ctx, node.symbol, node, options, intersection);
1294
+ linkType(ctx, links, type);
1174
1295
  finishType(intersection);
1175
1296
  });
1176
1297
  return intersection;
@@ -1203,10 +1324,10 @@ export function createChecker(program, resolver) {
1203
1324
  }
1204
1325
  check();
1205
1326
  }
1206
- function checkDecoratorDeclaration(node, mapper) {
1327
+ function checkDecoratorDeclaration(ctx, node) {
1207
1328
  const symbol = getMergedSymbol(node.symbol);
1208
1329
  const links = getSymbolLinks(symbol);
1209
- if (links.declaredType && mapper === undefined) {
1330
+ if (links.declaredType && ctx.mapper === undefined) {
1210
1331
  // we're not instantiating this operation and we've already checked it
1211
1332
  return links.declaredType;
1212
1333
  }
@@ -1225,19 +1346,19 @@ export function createChecker(program, resolver) {
1225
1346
  name: `@${name}`,
1226
1347
  namespace,
1227
1348
  node,
1228
- target: checkFunctionParameter(node.target, mapper, true),
1229
- parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, true)),
1349
+ target: checkFunctionParameter(ctx, node.target, true),
1350
+ parameters: node.parameters.map((param) => checkFunctionParameter(ctx, param, true)),
1230
1351
  implementation: implementation ?? (() => { }),
1231
1352
  });
1232
1353
  namespace.decoratorDeclarations.set(name, decoratorType);
1233
- linkType(links, decoratorType, mapper);
1354
+ linkType(ctx, links, decoratorType);
1234
1355
  return decoratorType;
1235
1356
  }
1236
- function checkFunctionDeclaration(node, mapper) {
1357
+ function checkFunctionDeclaration(ctx, node) {
1237
1358
  reportCheckerDiagnostic(createDiagnostic({ code: "function-unsupported", target: node }));
1238
1359
  return errorType;
1239
1360
  }
1240
- function checkFunctionParameter(node, mapper, mixed) {
1361
+ function checkFunctionParameter(ctx, node, mixed) {
1241
1362
  const links = getSymbolLinks(node.symbol);
1242
1363
  if (links.declaredType) {
1243
1364
  return links.declaredType;
@@ -1260,7 +1381,7 @@ export function createChecker(program, resolver) {
1260
1381
  let parameterType;
1261
1382
  if (mixed) {
1262
1383
  const type = node.type
1263
- ? getParamConstraintEntityForNode(node.type)
1384
+ ? getParamConstraintEntityForNode(ctx, node.type)
1264
1385
  : {
1265
1386
  entityKind: "MixedParameterConstraint",
1266
1387
  type: unknownType,
@@ -1280,24 +1401,24 @@ export function createChecker(program, resolver) {
1280
1401
  implementation: node.symbol.value,
1281
1402
  });
1282
1403
  }
1283
- linkType(links, parameterType, mapper);
1404
+ linkType(ctx, links, parameterType);
1284
1405
  return parameterType;
1285
1406
  }
1286
- function getTypeOrValueOfTypeForNode(node, mapper) {
1407
+ function getTypeOrValueOfTypeForNode(ctx, node) {
1287
1408
  switch (node.kind) {
1288
1409
  case SyntaxKind.ValueOfExpression:
1289
- const target = getTypeForNode(node.target, mapper);
1410
+ const target = getTypeForNode(node.target, ctx);
1290
1411
  return ["value", target];
1291
1412
  default:
1292
- return ["type", getTypeForNode(node, mapper)];
1413
+ return ["type", getTypeForNode(node, ctx)];
1293
1414
  }
1294
1415
  }
1295
- function getParamConstraintEntityForNode(node, mapper) {
1416
+ function getParamConstraintEntityForNode(ctx, node) {
1296
1417
  switch (node.kind) {
1297
1418
  case SyntaxKind.UnionExpression:
1298
- return checkMixedParameterConstraintUnion(node, mapper);
1419
+ return checkMixedParameterConstraintUnion(ctx, node);
1299
1420
  default:
1300
- const [kind, entity] = getTypeOrValueOfTypeForNode(node, mapper);
1421
+ const [kind, entity] = getTypeOrValueOfTypeForNode(ctx, node);
1301
1422
  return {
1302
1423
  entityKind: "MixedParameterConstraint",
1303
1424
  node: node,
@@ -1306,7 +1427,7 @@ export function createChecker(program, resolver) {
1306
1427
  };
1307
1428
  }
1308
1429
  }
1309
- function mergeModelTypes(parentModelSym, node, options, mapper, intersection) {
1430
+ function mergeModelTypes(ctx, parentModelSym, node, options, intersection) {
1310
1431
  const properties = intersection.properties;
1311
1432
  const indexers = [];
1312
1433
  const modelOptions = options.filter((entry) => {
@@ -1355,7 +1476,7 @@ export function createChecker(program, resolver) {
1355
1476
  ? cloneTypeForSymbol(memberSym, prop, overrides)
1356
1477
  : cloneType(prop, overrides);
1357
1478
  properties.set(prop.name, newPropType);
1358
- linkIndirectMember(node, newPropType, mapper);
1479
+ linkIndirectMember(ctx, node, newPropType);
1359
1480
  for (const indexer of indexers.filter((x) => x !== option.indexer)) {
1360
1481
  checkPropertyCompatibleWithIndexer(indexer, prop, node);
1361
1482
  }
@@ -1367,20 +1488,24 @@ export function createChecker(program, resolver) {
1367
1488
  else if (indexers.length > 1) {
1368
1489
  intersection.indexer = {
1369
1490
  key: indexers[0].key,
1370
- value: mergeModelTypes(undefined, node, indexers.map((x) => [x.value.node, x.value]), mapper, initModel(node)),
1491
+ value: mergeModelTypes(ctx, undefined, node, indexers.map((x) => [x.value.node, x.value]), initModel(node)),
1371
1492
  };
1372
1493
  }
1373
- linkMapper(intersection, mapper);
1494
+ linkMapper(intersection, ctx.mapper);
1374
1495
  return finishType(intersection);
1375
1496
  }
1376
- function checkArrayExpression(node, mapper) {
1377
- const elementType = getTypeForNode(node.elementType, mapper);
1497
+ function checkArrayExpression(ctx, node) {
1498
+ const elementCtx = ctx.enterTemplateObserverScope();
1499
+ const elementType = getTypeForNode(node.elementType, elementCtx);
1500
+ const instantiationCtx = elementCtx.hasObservedTemplateParameters()
1501
+ ? ctx
1502
+ : ctx.maskFlags(CheckFlags.InTemplateDeclaration);
1378
1503
  const arrayType = getStdType("Array");
1379
1504
  const arrayNode = arrayType.node;
1380
1505
  const param = getTypeForNode(arrayNode.templateParameters[0]);
1381
- return getOrInstantiateTemplate(arrayNode, [param], [elementType], { node, mapper }, undefined);
1506
+ return getOrInstantiateTemplate(instantiationCtx, arrayNode, [param], [elementType], { node, mapper: ctx.mapper }, undefined);
1382
1507
  }
1383
- function checkNamespace(node) {
1508
+ function checkNamespace(ctx, node) {
1384
1509
  const links = getSymbolLinks(getMergedSymbol(node.symbol));
1385
1510
  let type = links.type;
1386
1511
  if (!type) {
@@ -1388,10 +1513,10 @@ export function createChecker(program, resolver) {
1388
1513
  }
1389
1514
  if (node.kind === SyntaxKind.NamespaceStatement) {
1390
1515
  if (isArray(node.statements)) {
1391
- node.statements.forEach((x) => checkNode(x));
1516
+ node.statements.forEach((x) => checkNode(ctx, x));
1392
1517
  }
1393
1518
  else if (node.statements) {
1394
- const subNs = checkNamespace(node.statements);
1519
+ const subNs = checkNamespace(ctx, node.statements);
1395
1520
  type.namespaces.set(subNs.name, subNs);
1396
1521
  }
1397
1522
  }
@@ -1426,7 +1551,7 @@ export function createChecker(program, resolver) {
1426
1551
  // namespaces created from TypeSpec scripts don't have decorators
1427
1552
  if (sourceNode.kind !== SyntaxKind.NamespaceStatement)
1428
1553
  continue;
1429
- type.decorators = type.decorators.concat(checkDecorators(type, sourceNode, undefined));
1554
+ type.decorators = type.decorators.concat(checkDecorators(CheckContext.DEFAULT, type, sourceNode));
1430
1555
  }
1431
1556
  finishType(type);
1432
1557
  namespace?.namespaces.set(name, type);
@@ -1484,23 +1609,26 @@ export function createChecker(program, resolver) {
1484
1609
  }
1485
1610
  return symbolLinks.type;
1486
1611
  }
1487
- function checkOperation(node, mapper, parentInterface) {
1612
+ function checkOperation(ctx, node, parentInterface) {
1488
1613
  const inInterface = node.parent?.kind === SyntaxKind.InterfaceStatement;
1489
1614
  const symbol = inInterface ? getSymbolForMember(node) : node.symbol;
1490
1615
  const links = symbol && getSymbolLinks(symbol);
1491
1616
  if (links) {
1492
- if (links.declaredType && mapper === undefined) {
1617
+ if (links.declaredType && ctx.mapper === undefined) {
1493
1618
  // we're not instantiating this operation and we've already checked it
1494
1619
  return links.declaredType;
1495
1620
  }
1496
1621
  }
1497
- if (mapper === undefined && inInterface) {
1622
+ if (ctx.mapper === undefined && inInterface) {
1498
1623
  compilerAssert(parentInterface, "Operation in interface should already have been checked.", node.parent);
1499
1624
  }
1500
- checkTemplateDeclaration(node, mapper);
1625
+ checkTemplateDeclaration(ctx, node);
1501
1626
  // If we are instantating operation inside of interface
1502
- if (isTemplatedNode(node) && mapper !== undefined && parentInterface) {
1503
- mapper = { ...mapper, partial: true };
1627
+ if (isTemplatedNode(node) && ctx.mapper !== undefined && parentInterface) {
1628
+ ctx = ctx.withMapper({ ...ctx.mapper, partial: true });
1629
+ }
1630
+ if ((ctx.mapper === undefined || ctx.mapper.partial) && node.templateParameters.length > 0) {
1631
+ ctx = ctx.withFlags(CheckFlags.InTemplateDeclaration);
1504
1632
  }
1505
1633
  const namespace = getParentNamespaceType(node);
1506
1634
  const name = node.id.sv;
@@ -1526,21 +1654,20 @@ export function createChecker(program, resolver) {
1526
1654
  interface: parentInterface,
1527
1655
  });
1528
1656
  if (links) {
1529
- linkType(links, operationType, mapper);
1657
+ linkType(ctx, links, operationType);
1530
1658
  }
1531
1659
  const parent = node.parent;
1532
1660
  function finishOperation() {
1533
1661
  operationType.parameters.namespace = namespace;
1534
- operationType.decorators.push(...checkDecorators(operationType, node, mapper));
1535
- const runDecorators = parent.kind === SyntaxKind.InterfaceStatement
1536
- ? shouldRunDecorators(parent, mapper) && shouldRunDecorators(node, mapper)
1537
- : shouldRunDecorators(node, mapper);
1538
- return finishType(operationType, { skipDecorators: !runDecorators });
1662
+ operationType.decorators.push(...checkDecorators(ctx, operationType, node));
1663
+ return finishType(operationType, {
1664
+ skipDecorators: ctx.hasFlags(CheckFlags.InTemplateDeclaration),
1665
+ });
1539
1666
  }
1540
1667
  // Is this a definition or reference?
1541
1668
  if (node.signature.kind === SyntaxKind.OperationSignatureReference) {
1542
1669
  // Attempt to resolve the operation
1543
- const baseOperation = checkOperationIs(node, node.signature.baseOperation, mapper);
1670
+ const baseOperation = checkOperationIs(ctx, node, node.signature.baseOperation);
1544
1671
  if (baseOperation) {
1545
1672
  ensureResolved([baseOperation], operationType, () => {
1546
1673
  operationType.sourceOperation = baseOperation;
@@ -1570,19 +1697,19 @@ export function createChecker(program, resolver) {
1570
1697
  }
1571
1698
  }
1572
1699
  else {
1573
- operationType.parameters = getTypeForNode(node.signature.parameters, mapper);
1574
- operationType.returnType = getTypeForNode(node.signature.returnType, mapper);
1700
+ operationType.parameters = getTypeForNode(node.signature.parameters, ctx);
1701
+ operationType.returnType = getTypeForNode(node.signature.returnType, ctx);
1575
1702
  ensureResolved([operationType.parameters], operationType, () => {
1576
1703
  finishOperation();
1577
1704
  });
1578
1705
  }
1579
- linkMapper(operationType, mapper);
1580
- if (parent.kind !== SyntaxKind.InterfaceStatement && mapper === undefined) {
1706
+ linkMapper(operationType, ctx.mapper);
1707
+ if (parent.kind !== SyntaxKind.InterfaceStatement && ctx.mapper === undefined) {
1581
1708
  namespace?.operations.set(name, operationType);
1582
1709
  }
1583
1710
  return operationType;
1584
1711
  }
1585
- function checkOperationIs(operation, opReference, mapper) {
1712
+ function checkOperationIs(ctx, operation, opReference) {
1586
1713
  if (!opReference)
1587
1714
  return undefined;
1588
1715
  // Ensure that we don't end up with a circular reference to the same operation
@@ -1593,7 +1720,7 @@ export function createChecker(program, resolver) {
1593
1720
  const target = resolver.getNodeLinks(opReference).resolvedSymbol;
1594
1721
  // Did we encounter a circular operation reference?
1595
1722
  if (target && pendingResolutions.has(target, ResolutionKind.BaseType)) {
1596
- if (mapper === undefined) {
1723
+ if (ctx.mapper === undefined) {
1597
1724
  reportCheckerDiagnostic(createDiagnostic({
1598
1725
  code: "circular-op-signature",
1599
1726
  format: { typeName: target.name },
@@ -1603,7 +1730,7 @@ export function createChecker(program, resolver) {
1603
1730
  return undefined;
1604
1731
  }
1605
1732
  // Resolve the base operation type
1606
- const baseOperation = getTypeForNode(opReference, mapper);
1733
+ const baseOperation = getTypeForNode(opReference, ctx);
1607
1734
  if (opSymId) {
1608
1735
  pendingResolutions.finish(opSymId, ResolutionKind.BaseType);
1609
1736
  }
@@ -1623,17 +1750,18 @@ export function createChecker(program, resolver) {
1623
1750
  function getGlobalNamespaceNode() {
1624
1751
  return resolver.symbols.global.declarations[0];
1625
1752
  }
1626
- function checkTupleExpression(node, mapper) {
1753
+ function checkTupleExpression(ctx, node) {
1627
1754
  return createAndFinishType({
1628
1755
  kind: "Tuple",
1629
1756
  node: node,
1630
- values: node.values.map((v) => getTypeForNode(v, mapper)),
1757
+ values: node.values.map((v) => getTypeForNode(v, ctx)),
1631
1758
  });
1632
1759
  }
1633
1760
  function getSymbolLinks(s) {
1634
1761
  return resolver.getSymbolLinks(s);
1635
1762
  }
1636
1763
  function resolveRelatedSymbols(id, mapper) {
1764
+ const ctx = CheckContext.from(mapper);
1637
1765
  let sym;
1638
1766
  const { node, kind } = getIdentifierContext(id);
1639
1767
  switch (kind) {
@@ -1666,10 +1794,10 @@ export function createChecker(program, resolver) {
1666
1794
  resolveDecorator = false;
1667
1795
  }
1668
1796
  }
1669
- sym = resolveTypeReferenceSym(ref, mapper, resolveDecorator);
1797
+ sym = resolveTypeReferenceSym(ctx, ref, resolveDecorator);
1670
1798
  break;
1671
1799
  case IdentifierKind.TemplateArgument:
1672
- const templates = getTemplateDeclarationsForArgument(node, mapper);
1800
+ const templates = getTemplateDeclarationsForArgument(ctx, node);
1673
1801
  const firstMatchingParameter = templates
1674
1802
  .flatMap((t) => t.templateParameters)
1675
1803
  .find((p) => p.id.sv === id.sv);
@@ -1691,14 +1819,14 @@ export function createChecker(program, resolver) {
1691
1819
  }
1692
1820
  return undefined; //sym?.symbolSource ?? sym;
1693
1821
  }
1694
- function getTemplateDeclarationsForArgument(node, mapper) {
1822
+ function getTemplateDeclarationsForArgument(ctx, node) {
1695
1823
  const ref = node.parent;
1696
- let resolved = resolveTypeReferenceSym(ref, mapper, false);
1824
+ let resolved = resolveTypeReferenceSym(ctx, ref, false);
1697
1825
  // if the reference type can't be resolved and has parse error,
1698
1826
  // it likely means the reference type hasn't been completed yet. i.e. Foo<string,
1699
1827
  // so try to resolve it by it's target directly to see if we can find its sym
1700
1828
  if (!resolved && hasParseError(ref) && ref.target !== undefined) {
1701
- resolved = resolveTypeReferenceSym(ref.target, mapper, false);
1829
+ resolved = resolveTypeReferenceSym(ctx, ref.target, false);
1702
1830
  }
1703
1831
  return (resolved?.declarations.filter((n) => isTemplatedNode(n)) ?? []);
1704
1832
  }
@@ -1819,9 +1947,9 @@ export function createChecker(program, resolver) {
1819
1947
  node?.parent?.parent?.kind === SyntaxKind.TypeReference) {
1820
1948
  const argNode = node.parent;
1821
1949
  const refNode = node.parent.parent;
1822
- const decl = getTemplateDeclarationsForArgument(argNode,
1950
+ const decl = getTemplateDeclarationsForArgument(
1823
1951
  // We should be giving the argument so the mapper here should be undefined
1824
- undefined /* mapper */);
1952
+ CheckContext.DEFAULT, argNode);
1825
1953
  const index = refNode.arguments.findIndex((n) => n === argNode);
1826
1954
  if (decl.length > 0 && decl[0].templateParameters.length > index) {
1827
1955
  templateParmaeterDeclNode = decl[0].templateParameters[index];
@@ -1850,7 +1978,7 @@ export function createChecker(program, resolver) {
1850
1978
  if (callExpNode?.kind !== SyntaxKind.CallExpression) {
1851
1979
  return undefined;
1852
1980
  }
1853
- const ctorType = checkCallExpressionTarget(callExpNode, undefined);
1981
+ const ctorType = checkCallExpressionTarget(CheckContext.DEFAULT, callExpNode);
1854
1982
  if (ctorType?.kind !== "ScalarConstructor") {
1855
1983
  return undefined;
1856
1984
  }
@@ -1921,7 +2049,7 @@ export function createChecker(program, resolver) {
1921
2049
  case IdentifierKind.Declaration:
1922
2050
  return completions; // cannot complete, name can be chosen arbitrarily
1923
2051
  case IdentifierKind.TemplateArgument: {
1924
- const templates = getTemplateDeclarationsForArgument(ancestor, undefined);
2052
+ const templates = getTemplateDeclarationsForArgument(CheckContext.DEFAULT, ancestor);
1925
2053
  for (const template of templates) {
1926
2054
  for (const param of template.templateParameters) {
1927
2055
  addCompletion(param.id.sv, param.symbol);
@@ -1975,7 +2103,7 @@ export function createChecker(program, resolver) {
1975
2103
  let base = resolver.getNodeLinks(identifier.parent.base).resolvedSymbol;
1976
2104
  if (base) {
1977
2105
  if (base.flags & 128 /* SymbolFlags.Alias */) {
1978
- base = getAliasedSymbol(base, undefined);
2106
+ base = getAliasedSymbol(CheckContext.DEFAULT, base);
1979
2107
  }
1980
2108
  if (base) {
1981
2109
  if (identifier.parent.selector === "::") {
@@ -2007,7 +2135,7 @@ export function createChecker(program, resolver) {
2007
2135
  exprIsBareIdentifier(ancestor) &&
2008
2136
  ancestor.parent?.kind === SyntaxKind.TemplateArgument &&
2009
2137
  ancestor.parent.name === undefined) {
2010
- const templates = getTemplateDeclarationsForArgument(ancestor.parent, undefined);
2138
+ const templates = getTemplateDeclarationsForArgument(CheckContext.DEFAULT, ancestor.parent);
2011
2139
  for (const template of templates) {
2012
2140
  for (const param of template.templateParameters) {
2013
2141
  addCompletion(param.id.sv, param.symbol, { suffix: " = " });
@@ -2102,34 +2230,34 @@ export function createChecker(program, resolver) {
2102
2230
  return undefined;
2103
2231
  }
2104
2232
  }
2105
- function resolveTypeReferenceSym(node, mapper, options) {
2233
+ function resolveTypeReferenceSym(ctx, node, options) {
2106
2234
  const resolvedOptions = typeof options === "boolean"
2107
2235
  ? { ...defaultSymbolResolutionOptions, resolveDecorators: options }
2108
2236
  : { ...defaultSymbolResolutionOptions, ...(options ?? {}) };
2109
- if (mapper === undefined &&
2237
+ if (ctx.mapper === undefined &&
2110
2238
  !resolvedOptions.resolveDeclarationOfTemplate &&
2111
2239
  referenceSymCache.has(node)) {
2112
2240
  return referenceSymCache.get(node);
2113
2241
  }
2114
- const sym = resolveTypeReferenceSymInternal(node, mapper, resolvedOptions);
2242
+ const sym = resolveTypeReferenceSymInternal(ctx, node, resolvedOptions);
2115
2243
  if (!resolvedOptions.resolveDeclarationOfTemplate) {
2116
2244
  referenceSymCache.set(node, sym);
2117
2245
  }
2118
2246
  return sym;
2119
2247
  }
2120
- function resolveTypeReferenceSymInternal(node, mapper, options) {
2248
+ function resolveTypeReferenceSymInternal(ctx, node, options) {
2121
2249
  if (hasParseError(node)) {
2122
2250
  // Don't report synthetic identifiers used for parser error recovery.
2123
2251
  // The parse error is the root cause and will already have been logged.
2124
2252
  return undefined;
2125
2253
  }
2126
2254
  if (node.kind === SyntaxKind.TypeReference) {
2127
- return resolveTypeReferenceSym(node.target, mapper, options);
2255
+ return resolveTypeReferenceSym(ctx, node.target, options);
2128
2256
  }
2129
2257
  else if (node.kind === SyntaxKind.Identifier) {
2130
2258
  const links = resolver.getNodeLinks(node);
2131
- if (mapper === undefined && links.resolutionResult) {
2132
- if (mapper === undefined && // do not report error when instantiating
2259
+ if (ctx.mapper === undefined && links.resolutionResult) {
2260
+ if (ctx.mapper === undefined && // do not report error when instantiating
2133
2261
  links.resolutionResult & (ResolutionResultFlags.NotFound | ResolutionResultFlags.Unknown)) {
2134
2262
  reportCheckerDiagnostic(createDiagnostic({
2135
2263
  code: "invalid-ref",
@@ -2147,7 +2275,7 @@ export function createChecker(program, resolver) {
2147
2275
  return sym?.symbolSource ?? sym;
2148
2276
  }
2149
2277
  else if (node.kind === SyntaxKind.MemberExpression) {
2150
- let base = resolveTypeReferenceSym(node.base, mapper, {
2278
+ let base = resolveTypeReferenceSym(ctx, node.base, {
2151
2279
  ...options,
2152
2280
  resolveDecorators: false, // when resolving decorator the base cannot also be one
2153
2281
  });
@@ -2156,7 +2284,7 @@ export function createChecker(program, resolver) {
2156
2284
  }
2157
2285
  // when resolving a type reference based on an alias, unwrap the alias.
2158
2286
  if (base.flags & 128 /* SymbolFlags.Alias */) {
2159
- const aliasedSym = getAliasedSymbol(base, mapper);
2287
+ const aliasedSym = getAliasedSymbol(ctx, base);
2160
2288
  if (!aliasedSym) {
2161
2289
  reportCheckerDiagnostic(createDiagnostic({
2162
2290
  code: "invalid-ref",
@@ -2174,7 +2302,7 @@ export function createChecker(program, resolver) {
2174
2302
  base = aliasedSym;
2175
2303
  }
2176
2304
  else if (!options.resolveDeclarationOfTemplate && isTemplatedNode(getSymNode(base))) {
2177
- const baseSym = getContainerTemplateSymbol(base, node.base, mapper);
2305
+ const baseSym = getContainerTemplateSymbol(ctx, base, node.base);
2178
2306
  if (!baseSym) {
2179
2307
  return undefined;
2180
2308
  }
@@ -2270,14 +2398,14 @@ export function createChecker(program, resolver) {
2270
2398
  * (i.e. they contain symbols we don't know until we've instantiated the type and the type is an
2271
2399
  * instantiation) we late bind the container which creates the symbol that will hold its members.
2272
2400
  */
2273
- function getAliasedSymbol(aliasSymbol, mapper) {
2401
+ function getAliasedSymbol(ctx, aliasSymbol) {
2274
2402
  const node = getSymNode(aliasSymbol);
2275
2403
  const links = resolver.getSymbolLinks(aliasSymbol);
2276
2404
  if (!links.aliasResolutionIsTemplate) {
2277
2405
  return links.aliasedSymbol ?? resolver.getNodeLinks(node).resolvedSymbol;
2278
2406
  }
2279
2407
  // Otherwise for templates we need to get the type and retrieve the late bound symbol.
2280
- const aliasType = getTypeForNode(node, mapper);
2408
+ const aliasType = getTypeForNode(node, ctx);
2281
2409
  return lateBindContainer(aliasType, aliasSymbol);
2282
2410
  }
2283
2411
  /** Check case where a template type member is referenced like
@@ -2286,9 +2414,9 @@ export function createChecker(program, resolver) {
2286
2414
  * model Test { t: Foo.t } // check `Foo` is correctly used as template
2287
2415
  * ```
2288
2416
  */
2289
- function getContainerTemplateSymbol(sym, node, mapper) {
2417
+ function getContainerTemplateSymbol(ctx, sym, node) {
2290
2418
  if (pendingResolutions.has(sym, ResolutionKind.Type)) {
2291
- if (mapper === undefined) {
2419
+ if (ctx.mapper === undefined) {
2292
2420
  reportCheckerDiagnostic(createDiagnostic({
2293
2421
  code: "circular-alias-type",
2294
2422
  format: { typeName: sym.name },
@@ -2298,7 +2426,7 @@ export function createChecker(program, resolver) {
2298
2426
  return undefined;
2299
2427
  }
2300
2428
  pendingResolutions.start(sym, ResolutionKind.Type);
2301
- const type = checkTypeReferenceSymbol(sym, node, mapper);
2429
+ const type = checkTypeReferenceSymbol(ctx, sym, node);
2302
2430
  pendingResolutions.finish(sym, ResolutionKind.Type);
2303
2431
  return lateBindContainer(type, sym);
2304
2432
  }
@@ -2322,10 +2450,10 @@ export function createChecker(program, resolver) {
2322
2450
  return getMergedSymbol(type.node.symbol) ?? sym;
2323
2451
  }
2324
2452
  }
2325
- function checkStringTemplateExpresion(node, mapper) {
2453
+ function checkStringTemplateExpresion(ctx, node) {
2326
2454
  let hasType = false;
2327
2455
  let hasValue = false;
2328
- const spanTypeOrValues = node.spans.map((span) => [span, checkNode(span.expression, mapper)]);
2456
+ const spanTypeOrValues = node.spans.map((span) => [span, checkNode(ctx, span.expression)]);
2329
2457
  for (const [_, typeOrValue] of spanTypeOrValues) {
2330
2458
  if (typeOrValue !== null) {
2331
2459
  if (isValue(typeOrValue)) {
@@ -2538,7 +2666,7 @@ export function createChecker(program, resolver) {
2538
2666
  }
2539
2667
  function checkSourceFile(file) {
2540
2668
  for (const statement of file.statements) {
2541
- checkNode(statement, undefined);
2669
+ checkNode(CheckContext.DEFAULT, statement, undefined);
2542
2670
  }
2543
2671
  }
2544
2672
  /**
@@ -2546,29 +2674,32 @@ export function createChecker(program, resolver) {
2546
2674
  * @param node Node with template parameters
2547
2675
  * @param mapper Type mapper, set if instantiating the template, undefined otherwise.
2548
2676
  */
2549
- function checkTemplateDeclaration(node, mapper) {
2677
+ function checkTemplateDeclaration(ctx, node) {
2550
2678
  // If mapper is undefined it means we are checking the declaration of the template.
2551
- if (mapper === undefined) {
2679
+ if (ctx.mapper === undefined) {
2552
2680
  for (const templateParameter of node.templateParameters) {
2553
- checkTemplateParameterDeclaration(templateParameter, undefined);
2681
+ checkTemplateParameterDeclaration(ctx, templateParameter);
2554
2682
  }
2555
2683
  }
2556
2684
  }
2557
- function checkModel(node, mapper) {
2685
+ function checkModel(ctx, node) {
2558
2686
  if (node.kind === SyntaxKind.ModelStatement) {
2559
- return checkModelStatement(node, mapper);
2687
+ return checkModelStatement(ctx, node);
2560
2688
  }
2561
2689
  else {
2562
- return checkModelExpression(node, mapper);
2690
+ return checkModelExpression(ctx, node);
2563
2691
  }
2564
2692
  }
2565
- function checkModelStatement(node, mapper) {
2693
+ function checkModelStatement(ctx, node) {
2566
2694
  const links = getSymbolLinks(node.symbol);
2567
- if (links.declaredType && mapper === undefined) {
2695
+ if (ctx.mapper === undefined && node.templateParameters.length > 0) {
2696
+ ctx = ctx.withFlags(CheckFlags.InTemplateDeclaration);
2697
+ }
2698
+ if (links.declaredType && ctx.mapper === undefined) {
2568
2699
  // we're not instantiating this model and we've already checked it
2569
2700
  return links.declaredType;
2570
2701
  }
2571
- checkTemplateDeclaration(node, mapper);
2702
+ checkTemplateDeclaration(ctx, node);
2572
2703
  const decorators = [];
2573
2704
  const type = createType({
2574
2705
  kind: "Model",
@@ -2580,7 +2711,7 @@ export function createChecker(program, resolver) {
2580
2711
  sourceModels: [],
2581
2712
  derivedModels: [],
2582
2713
  });
2583
- linkType(links, type, mapper);
2714
+ linkType(ctx, links, type);
2584
2715
  if (node.symbol.members) {
2585
2716
  const members = resolver.getAugmentedSymbolTable(node.symbol.members);
2586
2717
  const propDocs = extractPropDocs(node);
@@ -2591,12 +2722,12 @@ export function createChecker(program, resolver) {
2591
2722
  }
2592
2723
  }
2593
2724
  }
2594
- const isBase = checkModelIs(node, node.is, mapper);
2725
+ const isBase = checkModelIs(ctx, node, node.is);
2595
2726
  ensureResolved([
2596
2727
  isBase,
2597
2728
  ...node.properties
2598
2729
  .filter((x) => x.kind === SyntaxKind.ModelSpreadProperty)
2599
- .map((x) => checkSpreadTarget(node, x.target, mapper)),
2730
+ .map((x) => checkSpreadTarget(ctx, node, x.target)),
2600
2731
  ], type, () => {
2601
2732
  if (isBase) {
2602
2733
  type.sourceModel = isBase;
@@ -2611,7 +2742,7 @@ export function createChecker(program, resolver) {
2611
2742
  sourceProperty: prop,
2612
2743
  model: type,
2613
2744
  });
2614
- linkIndirectMember(node, newProp, mapper);
2745
+ linkIndirectMember(ctx, node, newProp);
2615
2746
  type.properties.set(prop.name, newProp);
2616
2747
  }
2617
2748
  }
@@ -2619,7 +2750,7 @@ export function createChecker(program, resolver) {
2619
2750
  type.baseModel = isBase.baseModel;
2620
2751
  }
2621
2752
  else if (node.extends) {
2622
- type.baseModel = checkClassHeritage(node, node.extends, mapper);
2753
+ type.baseModel = checkClassHeritage(ctx, node, node.extends);
2623
2754
  if (type.baseModel) {
2624
2755
  copyDeprecation(type.baseModel, type);
2625
2756
  }
@@ -2629,14 +2760,14 @@ export function createChecker(program, resolver) {
2629
2760
  }
2630
2761
  // Hold on to the model type that's being defined so that it
2631
2762
  // can be referenced
2632
- if (mapper === undefined) {
2763
+ if (ctx.mapper === undefined) {
2633
2764
  type.namespace?.models.set(type.name, type);
2634
2765
  }
2635
2766
  // Evaluate the properties after
2636
- checkModelProperties(node, type.properties, type, mapper);
2637
- decorators.push(...checkDecorators(type, node, mapper));
2638
- linkMapper(type, mapper);
2639
- finishType(type, { skipDecorators: !shouldRunDecorators(node, mapper) });
2767
+ checkModelProperties(ctx, node, type.properties, type);
2768
+ decorators.push(...checkDecorators(ctx, type, node));
2769
+ linkMapper(type, ctx.mapper);
2770
+ finishType(type, { skipDecorators: ctx.hasFlags(CheckFlags.InTemplateDeclaration) });
2640
2771
  lateBindMemberContainer(type);
2641
2772
  lateBindMembers(type);
2642
2773
  const indexer = getIndexer(program, type);
@@ -2652,34 +2783,21 @@ export function createChecker(program, resolver) {
2652
2783
  });
2653
2784
  return type;
2654
2785
  }
2655
- function shouldRunDecorators(node, mapper) {
2656
- // Node is not a template we should create the type.
2657
- if (node.templateParameters.length === 0) {
2658
- return true;
2659
- }
2660
- // There is no mapper so we shouldn't be instantiating the template.
2661
- if (mapper === undefined) {
2662
- return false;
2663
- }
2664
- // Some of the mapper args are still template parameter so we shouldn't create the type.
2665
- return (!mapper.partial &&
2666
- mapper.args.every((t) => isValue(t) || t.entityKind === "Indeterminate" || t.kind !== "TemplateParameter"));
2667
- }
2668
- function checkModelExpression(node, mapper) {
2786
+ function checkModelExpression(ctx, node) {
2669
2787
  const links = getSymbolLinks(node.symbol);
2670
- if (links.declaredType && mapper === undefined) {
2788
+ if (links.declaredType && ctx.mapper === undefined) {
2671
2789
  // we're not instantiating this model and we've already checked it
2672
2790
  return links.declaredType;
2673
2791
  }
2674
2792
  const type = initModel(node);
2675
2793
  const properties = type.properties;
2676
- linkType(links, type, mapper);
2677
- linkMapper(type, mapper);
2794
+ linkType(ctx, links, type);
2795
+ linkMapper(type, ctx.mapper);
2678
2796
  ensureResolved(node.properties
2679
2797
  .filter((x) => x.kind === SyntaxKind.ModelSpreadProperty)
2680
- .map((x) => checkSpreadTarget(node, x.target, mapper)), type, () => {
2681
- checkModelProperties(node, properties, type, mapper);
2682
- finishType(type);
2798
+ .map((x) => checkSpreadTarget(ctx, node, x.target)), type, () => {
2799
+ checkModelProperties(ctx, node, properties, type);
2800
+ finishType(type, { skipDecorators: ctx.hasFlags(CheckFlags.InTemplateDeclaration) });
2683
2801
  });
2684
2802
  return type;
2685
2803
  }
@@ -2721,18 +2839,18 @@ export function createChecker(program, resolver) {
2721
2839
  : diagnosticTarget,
2722
2840
  }));
2723
2841
  }
2724
- function checkModelProperties(node, properties, parentModel, mapper) {
2842
+ function checkModelProperties(ctx, node, properties, parentModel) {
2725
2843
  let spreadIndexers;
2726
2844
  for (const prop of node.properties) {
2727
2845
  if ("id" in prop) {
2728
- const newProp = checkModelProperty(prop, mapper);
2846
+ const newProp = checkModelProperty(ctx, prop);
2729
2847
  newProp.model = parentModel;
2730
2848
  checkPropertyCompatibleWithModelIndexer(parentModel, newProp, prop);
2731
2849
  defineProperty(properties, newProp);
2732
2850
  }
2733
2851
  else {
2734
2852
  // spread property
2735
- const [newProperties, additionalIndexer] = checkSpreadProperty(node.symbol, prop.target, parentModel, mapper);
2853
+ const [newProperties, additionalIndexer] = checkSpreadProperty(ctx, node.symbol, prop.target, parentModel);
2736
2854
  if (additionalIndexer) {
2737
2855
  if (spreadIndexers) {
2738
2856
  spreadIndexers.push(additionalIndexer);
@@ -2742,7 +2860,7 @@ export function createChecker(program, resolver) {
2742
2860
  }
2743
2861
  }
2744
2862
  for (const newProp of newProperties) {
2745
- linkIndirectMember(node, newProp, mapper);
2863
+ linkIndirectMember(ctx, node, newProp);
2746
2864
  checkPropertyCompatibleWithModelIndexer(parentModel, newProp, prop);
2747
2865
  defineProperty(properties, newProp, prop);
2748
2866
  }
@@ -2758,8 +2876,8 @@ export function createChecker(program, resolver) {
2758
2876
  };
2759
2877
  }
2760
2878
  }
2761
- function checkObjectValue(node, mapper, constraint) {
2762
- const properties = checkObjectLiteralProperties(node, mapper);
2879
+ function checkObjectValue(ctx, node, constraint) {
2880
+ const properties = checkObjectLiteralProperties(ctx, node);
2763
2881
  if (properties === null) {
2764
2882
  return null;
2765
2883
  }
@@ -2801,12 +2919,12 @@ export function createChecker(program, resolver) {
2801
2919
  decorators: [],
2802
2920
  });
2803
2921
  }
2804
- function checkObjectLiteralProperties(node, mapper) {
2922
+ function checkObjectLiteralProperties(ctx, node) {
2805
2923
  const properties = new Map();
2806
2924
  let hasError = false;
2807
2925
  for (const prop of node.properties) {
2808
2926
  if ("id" in prop) {
2809
- const value = getValueForNode(prop.value, mapper);
2927
+ const value = getValueForNode(prop.value, ctx.mapper);
2810
2928
  if (value === null) {
2811
2929
  hasError = true;
2812
2930
  }
@@ -2815,7 +2933,7 @@ export function createChecker(program, resolver) {
2815
2933
  }
2816
2934
  }
2817
2935
  else {
2818
- const targetType = checkObjectSpreadProperty(prop.target, mapper);
2936
+ const targetType = checkObjectSpreadProperty(ctx, prop.target);
2819
2937
  if (targetType) {
2820
2938
  for (const [name, value] of targetType.properties) {
2821
2939
  properties.set(name, { ...value });
@@ -2825,8 +2943,8 @@ export function createChecker(program, resolver) {
2825
2943
  }
2826
2944
  return hasError ? null : properties;
2827
2945
  }
2828
- function checkObjectSpreadProperty(targetNode, mapper) {
2829
- const value = getValueForNode(targetNode, mapper);
2946
+ function checkObjectSpreadProperty(ctx, targetNode) {
2947
+ const value = getValueForNode(targetNode, ctx.mapper);
2830
2948
  if (value === null) {
2831
2949
  return null;
2832
2950
  }
@@ -2836,10 +2954,10 @@ export function createChecker(program, resolver) {
2836
2954
  }
2837
2955
  return value;
2838
2956
  }
2839
- function checkArrayValue(node, mapper, constraint) {
2957
+ function checkArrayValue(ctx, node, constraint) {
2840
2958
  let hasError = false;
2841
2959
  const values = node.values.map((itemNode) => {
2842
- const value = getValueForNode(itemNode, mapper);
2960
+ const value = getValueForNode(itemNode, ctx.mapper);
2843
2961
  if (value === null) {
2844
2962
  hasError = true;
2845
2963
  }
@@ -2990,8 +3108,8 @@ export function createChecker(program, resolver) {
2990
3108
  value: literalType,
2991
3109
  }, literalType);
2992
3110
  }
2993
- function checkCallExpressionTarget(node, mapper) {
2994
- const target = checkTypeReference(node.target, mapper);
3111
+ function checkCallExpressionTarget(ctx, node) {
3112
+ const target = checkTypeReference(ctx, node.target);
2995
3113
  if (target.kind === "Scalar" || target.kind === "ScalarConstructor") {
2996
3114
  return target;
2997
3115
  }
@@ -3032,7 +3150,7 @@ export function createChecker(program, resolver) {
3032
3150
  }
3033
3151
  return copyValue(value, { scalar, type: scalar });
3034
3152
  }
3035
- function createScalarValue(node, mapper, declaration) {
3153
+ function createScalarValue(ctx, node, declaration) {
3036
3154
  let hasError = false;
3037
3155
  const minArgs = declaration.parameters.filter((x) => !x.optional && !x.rest).length ?? 0;
3038
3156
  const maxArgs = declaration.parameters[declaration.parameters.length - 1]?.rest
@@ -3070,7 +3188,10 @@ export function createChecker(program, resolver) {
3070
3188
  for (let i = index; i < node.arguments.length; i++) {
3071
3189
  const argNode = node.arguments[i];
3072
3190
  if (argNode) {
3073
- const arg = getValueForNode(argNode, mapper, { kind: "argument", type: restType });
3191
+ const arg = getValueForNode(argNode, ctx.mapper, {
3192
+ kind: "argument",
3193
+ type: restType,
3194
+ });
3074
3195
  if (arg === null) {
3075
3196
  hasError = true;
3076
3197
  continue;
@@ -3088,7 +3209,7 @@ export function createChecker(program, resolver) {
3088
3209
  }
3089
3210
  const argNode = node.arguments[index];
3090
3211
  if (argNode) {
3091
- const arg = getValueForNode(argNode, mapper, {
3212
+ const arg = getValueForNode(argNode, ctx.mapper, {
3092
3213
  kind: "argument",
3093
3214
  type: parameter.type,
3094
3215
  });
@@ -3118,13 +3239,13 @@ export function createChecker(program, resolver) {
3118
3239
  type: declaration.scalar,
3119
3240
  };
3120
3241
  }
3121
- function checkCallExpression(node, mapper) {
3122
- const target = checkCallExpressionTarget(node, mapper);
3242
+ function checkCallExpression(ctx, node) {
3243
+ const target = checkCallExpressionTarget(ctx, node);
3123
3244
  if (target === null) {
3124
3245
  return null;
3125
3246
  }
3126
3247
  if (target.kind === "ScalarConstructor") {
3127
- return createScalarValue(node, mapper, target);
3248
+ return createScalarValue(ctx, node, target);
3128
3249
  }
3129
3250
  if (relation.areScalarsRelated(target, getStdType("string"))) {
3130
3251
  return checkPrimitiveArg(node, target, "StringValue");
@@ -3144,8 +3265,8 @@ export function createChecker(program, resolver) {
3144
3265
  return null;
3145
3266
  }
3146
3267
  }
3147
- function checkTypeOfExpression(node, mapper) {
3148
- const entity = checkNode(node.target, mapper, undefined);
3268
+ function checkTypeOfExpression(ctx, node) {
3269
+ const entity = checkNode(ctx, node.target, undefined);
3149
3270
  if (entity === null) {
3150
3271
  // Shouldn't need to emit error as we assume null value already emitted error when produced
3151
3272
  return errorType;
@@ -3305,7 +3426,7 @@ export function createChecker(program, resolver) {
3305
3426
  containerMembers.set(member.name, sym);
3306
3427
  }
3307
3428
  }
3308
- function checkClassHeritage(model, heritageRef, mapper) {
3429
+ function checkClassHeritage(ctx, model, heritageRef) {
3309
3430
  if (heritageRef.kind === SyntaxKind.ModelExpression) {
3310
3431
  reportCheckerDiagnostic(createDiagnostic({
3311
3432
  code: "extend-model",
@@ -3326,7 +3447,7 @@ export function createChecker(program, resolver) {
3326
3447
  pendingResolutions.start(modelSymId, ResolutionKind.BaseType);
3327
3448
  const target = resolver.getNodeLinks(heritageRef).resolvedSymbol;
3328
3449
  if (target && pendingResolutions.has(target, ResolutionKind.BaseType)) {
3329
- if (mapper === undefined) {
3450
+ if (ctx.mapper === undefined) {
3330
3451
  reportCheckerDiagnostic(createDiagnostic({
3331
3452
  code: "circular-base-type",
3332
3453
  format: { typeName: target.name },
@@ -3335,7 +3456,7 @@ export function createChecker(program, resolver) {
3335
3456
  }
3336
3457
  return undefined;
3337
3458
  }
3338
- const heritageType = getTypeForNode(heritageRef, mapper);
3459
+ const heritageType = getTypeForNode(heritageRef, ctx);
3339
3460
  pendingResolutions.finish(modelSymId, ResolutionKind.BaseType);
3340
3461
  if (isErrorType(heritageType)) {
3341
3462
  compilerAssert(program.hasError(), "Should already have reported an error.", heritageRef);
@@ -3354,7 +3475,7 @@ export function createChecker(program, resolver) {
3354
3475
  }
3355
3476
  return heritageType;
3356
3477
  }
3357
- function checkModelIs(model, isExpr, mapper) {
3478
+ function checkModelIs(ctx, model, isExpr) {
3358
3479
  if (!isExpr)
3359
3480
  return undefined;
3360
3481
  const modelSymId = getNodeSym(model);
@@ -3369,12 +3490,12 @@ export function createChecker(program, resolver) {
3369
3490
  return undefined;
3370
3491
  }
3371
3492
  else if (isExpr.kind === SyntaxKind.ArrayExpression) {
3372
- isType = checkArrayExpression(isExpr, mapper);
3493
+ isType = checkArrayExpression(ctx, isExpr);
3373
3494
  }
3374
3495
  else if (isExpr.kind === SyntaxKind.TypeReference) {
3375
3496
  const target = resolver.getNodeLinks(isExpr).resolvedSymbol;
3376
3497
  if (target && pendingResolutions.has(target, ResolutionKind.BaseType)) {
3377
- if (mapper === undefined) {
3498
+ if (ctx.mapper === undefined) {
3378
3499
  reportCheckerDiagnostic(createDiagnostic({
3379
3500
  code: "circular-base-type",
3380
3501
  format: { typeName: target.name },
@@ -3383,7 +3504,7 @@ export function createChecker(program, resolver) {
3383
3504
  }
3384
3505
  return undefined;
3385
3506
  }
3386
- isType = getTypeForNode(isExpr, mapper);
3507
+ isType = getTypeForNode(isExpr, ctx);
3387
3508
  }
3388
3509
  else {
3389
3510
  reportCheckerDiagnostic(createDiagnostic({ code: "is-model", target: isExpr }));
@@ -3401,11 +3522,11 @@ export function createChecker(program, resolver) {
3401
3522
  return isType;
3402
3523
  }
3403
3524
  /** Get the type for the spread target */
3404
- function checkSpreadTarget(model, target, mapper) {
3525
+ function checkSpreadTarget(ctx, model, target) {
3405
3526
  const modelSymId = getNodeSym(model);
3406
3527
  const targetSym = resolver.getNodeLinks(target).resolvedSymbol;
3407
3528
  if (targetSym === modelSymId) {
3408
- if (mapper === undefined) {
3529
+ if (ctx.mapper === undefined) {
3409
3530
  reportCheckerDiagnostic(createDiagnostic({
3410
3531
  code: "spread-model",
3411
3532
  messageId: "selfSpread",
@@ -3414,20 +3535,20 @@ export function createChecker(program, resolver) {
3414
3535
  }
3415
3536
  return undefined;
3416
3537
  }
3417
- const type = getTypeForNode(target, mapper);
3538
+ const type = getTypeForNode(target, ctx);
3418
3539
  return type;
3419
3540
  }
3420
- function checkSpreadProperty(parentModelSym, targetNode, parentModel, mapper) {
3421
- const targetType = getTypeForNode(targetNode, mapper);
3541
+ function checkSpreadProperty(ctx, parentModelSym, targetNode, parentModel) {
3542
+ const targetType = getTypeForNode(targetNode, ctx);
3422
3543
  if (targetType.kind === "TemplateParameter" || isErrorType(targetType)) {
3423
3544
  return [[], undefined];
3424
3545
  }
3425
3546
  if (targetType.kind !== "Model") {
3426
- reportCheckerDiagnostic(createDiagnostic({ code: "spread-model", target: targetNode }), mapper);
3547
+ reportCheckerDiagnostic(createDiagnostic({ code: "spread-model", target: targetNode }), ctx.mapper);
3427
3548
  return [[], undefined];
3428
3549
  }
3429
- if (isArrayModelType(program, targetType)) {
3430
- reportCheckerDiagnostic(createDiagnostic({ code: "spread-model", target: targetNode }), mapper);
3550
+ if (isArrayModelType(targetType)) {
3551
+ reportCheckerDiagnostic(createDiagnostic({ code: "spread-model", target: targetNode }), ctx.mapper);
3431
3552
  return [[], undefined];
3432
3553
  }
3433
3554
  parentModel.sourceModels.push({ usage: "spread", model: targetType, node: targetNode });
@@ -3448,8 +3569,8 @@ export function createChecker(program, resolver) {
3448
3569
  * @param member New Property
3449
3570
  * @param mapper Type Mapper.
3450
3571
  */
3451
- function linkIndirectMember(containerNode, member, mapper) {
3452
- if (mapper !== undefined) {
3572
+ function linkIndirectMember(ctx, containerNode, member) {
3573
+ if (ctx.mapper !== undefined) {
3453
3574
  return;
3454
3575
  }
3455
3576
  compilerAssert(typeof member.name === "string", "Cannot link unmapped unions");
@@ -3459,13 +3580,13 @@ export function createChecker(program, resolver) {
3459
3580
  const memberSym = getMemberSymbol(containerNode.symbol, member.name);
3460
3581
  if (memberSym) {
3461
3582
  const links = resolver.getSymbolLinks(memberSym);
3462
- linkMemberType(links, member, mapper);
3583
+ linkMemberType(ctx, links, member);
3463
3584
  }
3464
3585
  }
3465
- function checkModelProperty(prop, mapper) {
3586
+ function checkModelProperty(ctx, prop) {
3466
3587
  const sym = getSymbolForMember(prop);
3467
3588
  const links = getSymbolLinksForMember(prop);
3468
- if (links && links.declaredType && mapper === undefined) {
3589
+ if (links && links.declaredType && ctx.mapper === undefined) {
3469
3590
  return links.declaredType;
3470
3591
  }
3471
3592
  const name = prop.id.sv;
@@ -3477,7 +3598,7 @@ export function createChecker(program, resolver) {
3477
3598
  type: undefined,
3478
3599
  decorators: [],
3479
3600
  });
3480
- if (pendingResolutions.has(sym, ResolutionKind.Type) && mapper === undefined) {
3601
+ if (pendingResolutions.has(sym, ResolutionKind.Type) && ctx.mapper === undefined) {
3481
3602
  reportCheckerDiagnostic(createDiagnostic({
3482
3603
  code: "circular-prop",
3483
3604
  format: { propName: name },
@@ -3487,30 +3608,29 @@ export function createChecker(program, resolver) {
3487
3608
  }
3488
3609
  else {
3489
3610
  pendingResolutions.start(sym, ResolutionKind.Type);
3490
- type.type = getTypeForNode(prop.value, mapper);
3611
+ type.type = getTypeForNode(prop.value, ctx);
3491
3612
  if (prop.default) {
3492
- const defaultValue = checkDefaultValue(prop.default, type.type, mapper);
3613
+ const defaultValue = checkDefaultValue(ctx, prop.default, type.type);
3493
3614
  if (defaultValue !== null) {
3494
3615
  type.defaultValue = defaultValue;
3495
3616
  }
3496
3617
  }
3497
3618
  if (links) {
3498
- linkType(links, type, mapper);
3619
+ linkType(ctx, links, type);
3499
3620
  }
3500
3621
  }
3501
- type.decorators = checkDecorators(type, prop, mapper);
3622
+ type.decorators = checkDecorators(ctx, type, prop);
3502
3623
  const parentTemplate = getParentTemplateNode(prop);
3503
- linkMapper(type, mapper);
3504
- let runDecorators = false;
3505
- if (!parentTemplate || shouldRunDecorators(parentTemplate, mapper)) {
3624
+ linkMapper(type, ctx.mapper);
3625
+ const shouldRunDecorators = !ctx.hasFlags(CheckFlags.InTemplateDeclaration);
3626
+ if (!parentTemplate || shouldRunDecorators) {
3506
3627
  const docComment = docFromCommentForSym.get(sym);
3507
3628
  if (docComment) {
3508
3629
  type.decorators.unshift(createDocFromCommentDecorator("self", docComment));
3509
3630
  }
3510
- runDecorators = true;
3511
3631
  }
3512
3632
  pendingResolutions.finish(sym, ResolutionKind.Type);
3513
- return finishType(type, { skipDecorators: !runDecorators });
3633
+ return finishType(type, { skipDecorators: !shouldRunDecorators });
3514
3634
  }
3515
3635
  function createDocFromCommentDecorator(key, doc) {
3516
3636
  return {
@@ -3521,12 +3641,12 @@ export function createChecker(program, resolver) {
3521
3641
  ],
3522
3642
  };
3523
3643
  }
3524
- function checkDefaultValue(defaultNode, type, mapper) {
3644
+ function checkDefaultValue(ctx, defaultNode, type) {
3525
3645
  if (isErrorType(type)) {
3526
3646
  // if the prop type is an error we don't need to validate again.
3527
3647
  return null;
3528
3648
  }
3529
- const defaultValue = getValueForNode(defaultNode, mapper, {
3649
+ const defaultValue = getValueForNode(defaultNode, ctx.mapper, {
3530
3650
  kind: "assignment",
3531
3651
  type,
3532
3652
  });
@@ -3547,8 +3667,8 @@ export function createChecker(program, resolver) {
3547
3667
  return { ...defaultValue, type };
3548
3668
  }
3549
3669
  }
3550
- function checkDecoratorApplication(targetType, decNode, mapper) {
3551
- const sym = resolveTypeReferenceSym(decNode.target, undefined, true);
3670
+ function checkDecoratorApplication(ctx, targetType, decNode) {
3671
+ const sym = resolveTypeReferenceSym(ctx.withMapper(undefined), decNode.target, true);
3552
3672
  if (!sym) {
3553
3673
  // Error should already have been reported above
3554
3674
  return undefined;
@@ -3566,7 +3686,7 @@ export function createChecker(program, resolver) {
3566
3686
  if (symbolLinks.declaredType === undefined) {
3567
3687
  const decoratorDeclNode = sym.declarations.find((x) => x.kind === SyntaxKind.DecoratorDeclarationStatement);
3568
3688
  if (decoratorDeclNode) {
3569
- checkDecoratorDeclaration(decoratorDeclNode, undefined);
3689
+ checkDecoratorDeclaration(ctx.withMapper(undefined), decoratorDeclNode);
3570
3690
  }
3571
3691
  }
3572
3692
  if (symbolLinks.declaredType) {
@@ -3575,7 +3695,7 @@ export function createChecker(program, resolver) {
3575
3695
  hasError = true;
3576
3696
  }
3577
3697
  }
3578
- const [argsHaveError, args] = checkDecoratorArguments(decNode, mapper, symbolLinks.declaredType);
3698
+ const [argsHaveError, args] = checkDecoratorArguments(ctx, decNode, symbolLinks.declaredType);
3579
3699
  if (hasError || argsHaveError) {
3580
3700
  return undefined;
3581
3701
  }
@@ -3603,13 +3723,13 @@ export function createChecker(program, resolver) {
3603
3723
  }
3604
3724
  return targetValid;
3605
3725
  }
3606
- function checkDecoratorArguments(node, mapper, declaration) {
3726
+ function checkDecoratorArguments(ctx, node, declaration) {
3607
3727
  // if we don't have a declaration we can just return the types or values if
3608
3728
  if (declaration === undefined) {
3609
3729
  return [
3610
3730
  false,
3611
3731
  node.arguments.map((argNode) => {
3612
- let type = checkNode(argNode, mapper) ?? errorType;
3732
+ let type = checkNode(ctx, argNode) ?? errorType;
3613
3733
  if (type.entityKind === "Indeterminate") {
3614
3734
  type = type.type;
3615
3735
  }
@@ -3652,7 +3772,7 @@ export function createChecker(program, resolver) {
3652
3772
  }
3653
3773
  const resolvedArgs = [];
3654
3774
  function resolveArg(argNode, perParamType) {
3655
- const arg = getTypeOrValueForNode(argNode, mapper, {
3775
+ const arg = getTypeOrValueForNode(argNode, ctx.mapper, {
3656
3776
  kind: "argument",
3657
3777
  constraint: perParamType,
3658
3778
  });
@@ -3709,8 +3829,7 @@ export function createChecker(program, resolver) {
3709
3829
  let valueType;
3710
3830
  let type;
3711
3831
  if (constraint.valueType) {
3712
- if (constraint.valueType.kind === "Model" &&
3713
- isArrayModelType(program, constraint.valueType)) {
3832
+ if (constraint.valueType.kind === "Model" && isArrayModelType(constraint.valueType)) {
3714
3833
  valueType = constraint.valueType.indexer.value;
3715
3834
  }
3716
3835
  else {
@@ -3718,7 +3837,7 @@ export function createChecker(program, resolver) {
3718
3837
  }
3719
3838
  }
3720
3839
  if (constraint.type) {
3721
- if (constraint.type.kind === "Model" && isArrayModelType(program, constraint.type)) {
3840
+ if (constraint.type.kind === "Model" && isArrayModelType(constraint.type)) {
3722
3841
  type = constraint.type.indexer.value;
3723
3842
  }
3724
3843
  else {
@@ -3759,11 +3878,11 @@ export function createChecker(program, resolver) {
3759
3878
  }
3760
3879
  return valid;
3761
3880
  }
3762
- function checkAugmentDecorators(sym, targetType, mapper) {
3881
+ function checkAugmentDecorators(ctx, sym, targetType) {
3763
3882
  const augmentDecoratorNodes = resolver.getAugmentDecoratorsForSym(sym);
3764
3883
  const decorators = [];
3765
3884
  for (const decNode of augmentDecoratorNodes) {
3766
- const decorator = checkDecoratorApplication(targetType, decNode, mapper);
3885
+ const decorator = checkDecoratorApplication(ctx, targetType, decNode);
3767
3886
  if (decorator) {
3768
3887
  decorators.unshift(decorator);
3769
3888
  }
@@ -3773,9 +3892,11 @@ export function createChecker(program, resolver) {
3773
3892
  /**
3774
3893
  * Check that augment decorator are targeting valid symbols.
3775
3894
  */
3776
- function checkAugmentDecorator(node) {
3895
+ function checkAugmentDecorator(ctx, node) {
3777
3896
  // This will validate the target type is pointing to a valid ref.
3778
- resolveTypeReferenceSym(node.targetType, undefined, { resolveDeclarationOfTemplate: true });
3897
+ resolveTypeReferenceSym(ctx.withMapper(undefined), node.targetType, {
3898
+ resolveDeclarationOfTemplate: true,
3899
+ });
3779
3900
  const links = resolver.getNodeLinks(node.targetType);
3780
3901
  if (links.isTemplateInstantiation) {
3781
3902
  program.reportDiagnostic(createDiagnostic({
@@ -3811,8 +3932,8 @@ export function createChecker(program, resolver) {
3811
3932
  /**
3812
3933
  * Check that using statements are targeting valid symbols.
3813
3934
  */
3814
- function checkUsings(node) {
3815
- const usedSym = resolveTypeReferenceSym(node.name, undefined);
3935
+ function checkUsings(ctx, node) {
3936
+ const usedSym = resolveTypeReferenceSym(ctx.withMapper(undefined), node.name);
3816
3937
  if (usedSym) {
3817
3938
  if (~usedSym.flags & 256 /* SymbolFlags.Namespace */) {
3818
3939
  reportCheckerDiagnostic(createDiagnostic({ code: "using-invalid-ref", target: node.name }));
@@ -3821,7 +3942,7 @@ export function createChecker(program, resolver) {
3821
3942
  // If this was used to get a type this is invalid, only used for validation.
3822
3943
  return errorType;
3823
3944
  }
3824
- function checkDecorators(targetType, node, mapper) {
3945
+ function checkDecorators(ctx, targetType, node) {
3825
3946
  const sym = isMemberNode(node)
3826
3947
  ? (getSymbolForMember(node) ?? node.symbol)
3827
3948
  : getMergedSymbol(node.symbol);
@@ -3832,7 +3953,7 @@ export function createChecker(program, resolver) {
3832
3953
  ...node.decorators,
3833
3954
  ];
3834
3955
  for (const decNode of decoratorNodes) {
3835
- const decorator = checkDecoratorApplication(targetType, decNode, mapper);
3956
+ const decorator = checkDecoratorApplication(ctx, targetType, decNode);
3836
3957
  if (decorator) {
3837
3958
  decorators.unshift(decorator);
3838
3959
  }
@@ -3855,13 +3976,17 @@ export function createChecker(program, resolver) {
3855
3976
  }
3856
3977
  return decorators;
3857
3978
  }
3858
- function checkScalar(node, mapper) {
3979
+ function checkScalar(ctx, node) {
3859
3980
  const links = getSymbolLinks(node.symbol);
3860
- if (links.declaredType && mapper === undefined) {
3981
+ if (ctx.mapper === undefined && node.templateParameters.length > 0) {
3982
+ // This is a templated declaration and we are not instantiating it, so we need to update the flags.
3983
+ ctx = ctx.withFlags(CheckFlags.InTemplateDeclaration);
3984
+ }
3985
+ if (links.declaredType && ctx.mapper === undefined) {
3861
3986
  // we're not instantiating this model and we've already checked it
3862
3987
  return links.declaredType;
3863
3988
  }
3864
- checkTemplateDeclaration(node, mapper);
3989
+ checkTemplateDeclaration(ctx, node);
3865
3990
  const decorators = [];
3866
3991
  const type = createType({
3867
3992
  kind: "Scalar",
@@ -3872,31 +3997,31 @@ export function createChecker(program, resolver) {
3872
3997
  decorators,
3873
3998
  derivedScalars: [],
3874
3999
  });
3875
- linkType(links, type, mapper);
4000
+ linkType(ctx, links, type);
3876
4001
  if (node.extends) {
3877
- type.baseScalar = checkScalarExtends(node, node.extends, mapper);
4002
+ type.baseScalar = checkScalarExtends(ctx, node, node.extends);
3878
4003
  if (type.baseScalar) {
3879
4004
  copyDeprecation(type.baseScalar, type);
3880
4005
  type.baseScalar.derivedScalars.push(type);
3881
4006
  }
3882
4007
  }
3883
- checkScalarConstructors(type, node, type.constructors, mapper);
3884
- decorators.push(...checkDecorators(type, node, mapper));
3885
- if (mapper === undefined) {
4008
+ checkScalarConstructors(ctx, type, node, type.constructors);
4009
+ decorators.push(...checkDecorators(ctx, type, node));
4010
+ if (ctx.mapper === undefined) {
3886
4011
  type.namespace?.scalars.set(type.name, type);
3887
4012
  }
3888
- linkMapper(type, mapper);
4013
+ linkMapper(type, ctx.mapper);
3889
4014
  if (isInTypeSpecNamespace(type)) {
3890
4015
  stdTypes[type.name] = type;
3891
4016
  }
3892
- return finishType(type, { skipDecorators: !shouldRunDecorators(node, mapper) });
4017
+ return finishType(type, { skipDecorators: ctx.hasFlags(CheckFlags.InTemplateDeclaration) });
3893
4018
  }
3894
- function checkScalarExtends(scalar, extendsRef, mapper) {
4019
+ function checkScalarExtends(ctx, scalar, extendsRef) {
3895
4020
  const symId = getNodeSym(scalar);
3896
4021
  pendingResolutions.start(symId, ResolutionKind.BaseType);
3897
4022
  const target = resolver.getNodeLinks(extendsRef).resolvedSymbol;
3898
4023
  if (target && pendingResolutions.has(target, ResolutionKind.BaseType)) {
3899
- if (mapper === undefined) {
4024
+ if (ctx.mapper === undefined) {
3900
4025
  reportCheckerDiagnostic(createDiagnostic({
3901
4026
  code: "circular-base-type",
3902
4027
  format: { typeName: target.declarations[0].id.sv },
@@ -3905,7 +4030,7 @@ export function createChecker(program, resolver) {
3905
4030
  }
3906
4031
  return undefined;
3907
4032
  }
3908
- const extendsType = getTypeForNode(extendsRef, mapper);
4033
+ const extendsType = getTypeForNode(extendsRef, ctx);
3909
4034
  pendingResolutions.finish(symId, ResolutionKind.BaseType);
3910
4035
  if (isErrorType(extendsType)) {
3911
4036
  compilerAssert(program.hasError(), "Should already have reported an error.", extendsRef);
@@ -3917,19 +4042,19 @@ export function createChecker(program, resolver) {
3917
4042
  }
3918
4043
  return extendsType;
3919
4044
  }
3920
- function checkScalarConstructors(parentScalar, node, constructors, mapper) {
4045
+ function checkScalarConstructors(ctx, parentScalar, node, constructors) {
3921
4046
  if (parentScalar.baseScalar) {
3922
4047
  for (const member of parentScalar.baseScalar.constructors.values()) {
3923
4048
  const newConstructor = cloneTypeForSymbol(getMemberSymbol(node.symbol, member.name), {
3924
4049
  ...member,
3925
4050
  scalar: parentScalar,
3926
4051
  });
3927
- linkIndirectMember(node, newConstructor, mapper);
4052
+ linkIndirectMember(ctx, node, newConstructor);
3928
4053
  constructors.set(member.name, newConstructor);
3929
4054
  }
3930
4055
  }
3931
4056
  for (const member of node.members) {
3932
- const constructor = checkScalarConstructor(member, mapper, parentScalar);
4057
+ const constructor = checkScalarConstructor(ctx, member, parentScalar);
3933
4058
  if (constructors.has(constructor.name)) {
3934
4059
  reportCheckerDiagnostic(createDiagnostic({
3935
4060
  code: "constructor-duplicate",
@@ -3941,10 +4066,10 @@ export function createChecker(program, resolver) {
3941
4066
  constructors.set(constructor.name, constructor);
3942
4067
  }
3943
4068
  }
3944
- function checkScalarConstructor(node, mapper, parentScalar) {
4069
+ function checkScalarConstructor(ctx, node, parentScalar) {
3945
4070
  const name = node.id.sv;
3946
4071
  const links = getSymbolLinksForMember(node);
3947
- if (links && links.declaredType && mapper === undefined) {
4072
+ if (links && links.declaredType && ctx.mapper === undefined) {
3948
4073
  // we're not instantiating this scalar constructor and we've already checked it
3949
4074
  return links.declaredType;
3950
4075
  }
@@ -3953,25 +4078,29 @@ export function createChecker(program, resolver) {
3953
4078
  scalar: parentScalar,
3954
4079
  name,
3955
4080
  node,
3956
- parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, false)),
4081
+ parameters: node.parameters.map((x) => checkFunctionParameter(ctx, x, false)),
3957
4082
  });
3958
- linkMapper(member, mapper);
4083
+ linkMapper(member, ctx.mapper);
3959
4084
  if (links) {
3960
- linkType(links, member, mapper);
4085
+ linkType(ctx, links, member);
3961
4086
  }
3962
4087
  return finishType(member, {
3963
- skipDecorators: !shouldRunDecorators(node.parent, mapper),
4088
+ skipDecorators: ctx.hasFlags(CheckFlags.InTemplateDeclaration),
3964
4089
  });
3965
4090
  }
3966
- function checkAlias(node, mapper) {
4091
+ function checkAlias(ctx, node) {
3967
4092
  const links = getSymbolLinks(node.symbol);
3968
- if (links.declaredType && mapper === undefined) {
4093
+ if (ctx.mapper === undefined && node.templateParameters.length > 0) {
4094
+ // This is a templated declaration and we are not instantiating it, so we need to update the flags.
4095
+ ctx = ctx.withFlags(CheckFlags.InTemplateDeclaration);
4096
+ }
4097
+ if (links.declaredType && ctx.mapper === undefined) {
3969
4098
  return links.declaredType;
3970
4099
  }
3971
- checkTemplateDeclaration(node, mapper);
4100
+ checkTemplateDeclaration(ctx, node);
3972
4101
  const aliasSymId = getNodeSym(node);
3973
4102
  if (pendingResolutions.has(aliasSymId, ResolutionKind.Type)) {
3974
- if (mapper === undefined) {
4103
+ if (ctx.mapper === undefined) {
3975
4104
  reportCheckerDiagnostic(createDiagnostic({
3976
4105
  code: "circular-alias-type",
3977
4106
  format: { typeName: node.id.sv },
@@ -3982,7 +4111,7 @@ export function createChecker(program, resolver) {
3982
4111
  return errorType;
3983
4112
  }
3984
4113
  pendingResolutions.start(aliasSymId, ResolutionKind.Type);
3985
- const type = checkNode(node.value, mapper);
4114
+ const type = checkNode(ctx, node.value);
3986
4115
  if (type === null) {
3987
4116
  links.declaredType = errorType;
3988
4117
  return errorType;
@@ -3992,7 +4121,7 @@ export function createChecker(program, resolver) {
3992
4121
  links.declaredType = errorType;
3993
4122
  return errorType;
3994
4123
  }
3995
- linkType(links, type, mapper);
4124
+ linkType(ctx, links, type);
3996
4125
  pendingResolutions.finish(aliasSymId, ResolutionKind.Type);
3997
4126
  return type;
3998
4127
  }
@@ -4038,7 +4167,7 @@ export function createChecker(program, resolver) {
4038
4167
  return value;
4039
4168
  }
4040
4169
  }
4041
- function checkEnum(node, mapper) {
4170
+ function checkEnum(ctx, node) {
4042
4171
  const links = getSymbolLinks(node.symbol);
4043
4172
  if (!links.type) {
4044
4173
  const enumType = (links.type = createType({
@@ -4051,7 +4180,7 @@ export function createChecker(program, resolver) {
4051
4180
  const memberNames = new Set();
4052
4181
  for (const member of node.members) {
4053
4182
  if (member.kind === SyntaxKind.EnumMember) {
4054
- const memberType = checkEnumMember(member, mapper, enumType);
4183
+ const memberType = checkEnumMember(ctx, member, enumType);
4055
4184
  if (memberNames.has(memberType.name)) {
4056
4185
  reportCheckerDiagnostic(createDiagnostic({
4057
4186
  code: "enum-member-duplicate",
@@ -4064,9 +4193,9 @@ export function createChecker(program, resolver) {
4064
4193
  enumType.members.set(memberType.name, memberType);
4065
4194
  }
4066
4195
  else {
4067
- const members = checkEnumSpreadMember(node.symbol, enumType, member.target, mapper, memberNames);
4196
+ const members = checkEnumSpreadMember(ctx, node.symbol, enumType, member.target, memberNames);
4068
4197
  for (const memberType of members) {
4069
- linkIndirectMember(node, memberType, mapper);
4198
+ linkIndirectMember(ctx, node, memberType);
4070
4199
  enumType.members.set(memberType.name, memberType);
4071
4200
  }
4072
4201
  }
@@ -4074,19 +4203,23 @@ export function createChecker(program, resolver) {
4074
4203
  const namespace = getParentNamespaceType(node);
4075
4204
  enumType.namespace = namespace;
4076
4205
  enumType.namespace?.enums.set(enumType.name, enumType);
4077
- enumType.decorators = checkDecorators(enumType, node, mapper);
4078
- linkMapper(enumType, mapper);
4206
+ enumType.decorators = checkDecorators(ctx, enumType, node);
4207
+ linkMapper(enumType, ctx.mapper);
4079
4208
  finishType(enumType);
4080
4209
  }
4081
4210
  return links.type;
4082
4211
  }
4083
- function checkInterface(node, mapper) {
4212
+ function checkInterface(ctx, node) {
4084
4213
  const links = getSymbolLinks(node.symbol);
4085
- if (links.declaredType && mapper === undefined) {
4214
+ if (ctx.mapper === undefined && node.templateParameters.length > 0) {
4215
+ // This is a templated declaration and we are not instantiating it, so we need to update the flags.
4216
+ ctx = ctx.withFlags(CheckFlags.InTemplateDeclaration);
4217
+ }
4218
+ if (links.declaredType && ctx.mapper === undefined) {
4086
4219
  // we're not instantiating this interface and we've already checked it
4087
4220
  return links.declaredType;
4088
4221
  }
4089
- checkTemplateDeclaration(node, mapper);
4222
+ checkTemplateDeclaration(ctx, node);
4090
4223
  const interfaceType = createType({
4091
4224
  kind: "Interface",
4092
4225
  decorators: [],
@@ -4096,11 +4229,11 @@ export function createChecker(program, resolver) {
4096
4229
  operations: createRekeyableMap(),
4097
4230
  name: node.id.sv,
4098
4231
  });
4099
- linkType(links, interfaceType, mapper);
4100
- interfaceType.decorators = checkDecorators(interfaceType, node, mapper);
4101
- const ownMembers = checkInterfaceMembers(node, mapper, interfaceType);
4232
+ linkType(ctx, links, interfaceType);
4233
+ interfaceType.decorators = checkDecorators(ctx, interfaceType, node);
4234
+ const ownMembers = checkInterfaceMembers(ctx, node, interfaceType);
4102
4235
  for (const extendsNode of node.extends) {
4103
- const extendsType = getTypeForNode(extendsNode, mapper);
4236
+ const extendsType = getTypeForNode(extendsNode, ctx);
4104
4237
  if (extendsType.kind !== "Interface") {
4105
4238
  reportCheckerDiagnostic(createDiagnostic({ code: "extends-interface", target: extendsNode }));
4106
4239
  continue;
@@ -4118,7 +4251,7 @@ export function createChecker(program, resolver) {
4118
4251
  });
4119
4252
  // Don't link it it is overritten
4120
4253
  if (!ownMembers.has(member.name)) {
4121
- linkIndirectMember(node, newMember, mapper);
4254
+ linkIndirectMember(ctx, node, newMember);
4122
4255
  }
4123
4256
  // Clone deprecation information
4124
4257
  copyDeprecation(member, newMember);
@@ -4129,17 +4262,17 @@ export function createChecker(program, resolver) {
4129
4262
  for (const [key, value] of ownMembers) {
4130
4263
  interfaceType.operations.set(key, value);
4131
4264
  }
4132
- linkMapper(interfaceType, mapper);
4133
- if (mapper === undefined) {
4265
+ linkMapper(interfaceType, ctx.mapper);
4266
+ if (ctx.mapper === undefined) {
4134
4267
  interfaceType.namespace?.interfaces.set(interfaceType.name, interfaceType);
4135
4268
  }
4136
4269
  lateBindMemberContainer(interfaceType);
4137
4270
  lateBindMembers(interfaceType);
4138
4271
  return finishType(interfaceType, {
4139
- skipDecorators: !shouldRunDecorators(node, mapper),
4272
+ skipDecorators: ctx.hasFlags(CheckFlags.InTemplateDeclaration),
4140
4273
  });
4141
4274
  }
4142
- function checkInterfaceMembers(node, mapper, interfaceType) {
4275
+ function checkInterfaceMembers(ctx, node, interfaceType) {
4143
4276
  const ownMembers = new Map();
4144
4277
  // Preregister each operation sym links instantiation to make sure there is no race condition when instantiating templated interface
4145
4278
  for (const opNode of node.operations) {
@@ -4150,7 +4283,7 @@ export function createChecker(program, resolver) {
4150
4283
  }
4151
4284
  }
4152
4285
  for (const opNode of node.operations) {
4153
- const opType = checkOperation(opNode, mapper, interfaceType);
4286
+ const opType = checkOperation(ctx, opNode, interfaceType);
4154
4287
  if (ownMembers.has(opType.name)) {
4155
4288
  reportCheckerDiagnostic(createDiagnostic({
4156
4289
  code: "interface-duplicate",
@@ -4163,13 +4296,16 @@ export function createChecker(program, resolver) {
4163
4296
  }
4164
4297
  return ownMembers;
4165
4298
  }
4166
- function checkUnion(node, mapper) {
4299
+ function checkUnion(ctx, node) {
4167
4300
  const links = getSymbolLinks(node.symbol);
4168
- if (links.declaredType && mapper === undefined) {
4301
+ if (ctx.mapper === undefined && node.templateParameters.length > 0) {
4302
+ ctx = ctx.withFlags(CheckFlags.InTemplateDeclaration);
4303
+ }
4304
+ if (links.declaredType && ctx.mapper === undefined) {
4169
4305
  // we're not instantiating this union and we've already checked it
4170
4306
  return links.declaredType;
4171
4307
  }
4172
- checkTemplateDeclaration(node, mapper);
4308
+ checkTemplateDeclaration(ctx, node);
4173
4309
  const variants = createRekeyableMap();
4174
4310
  const unionType = createType({
4175
4311
  kind: "Union",
@@ -4183,20 +4319,22 @@ export function createChecker(program, resolver) {
4183
4319
  },
4184
4320
  expression: false,
4185
4321
  });
4186
- linkType(links, unionType, mapper);
4187
- unionType.decorators = checkDecorators(unionType, node, mapper);
4188
- checkUnionVariants(unionType, node, variants, mapper);
4189
- linkMapper(unionType, mapper);
4190
- if (mapper === undefined) {
4322
+ linkType(ctx, links, unionType);
4323
+ unionType.decorators = checkDecorators(ctx, unionType, node);
4324
+ checkUnionVariants(ctx, unionType, node, variants);
4325
+ linkMapper(unionType, ctx.mapper);
4326
+ if (ctx.mapper === undefined) {
4191
4327
  unionType.namespace?.unions.set(unionType.name, unionType);
4192
4328
  }
4193
4329
  lateBindMemberContainer(unionType);
4194
4330
  lateBindMembers(unionType);
4195
- return finishType(unionType, { skipDecorators: !shouldRunDecorators(node, mapper) });
4331
+ return finishType(unionType, {
4332
+ skipDecorators: ctx.hasFlags(CheckFlags.InTemplateDeclaration),
4333
+ });
4196
4334
  }
4197
- function checkUnionVariants(parentUnion, node, variants, mapper) {
4335
+ function checkUnionVariants(ctx, parentUnion, node, variants) {
4198
4336
  for (const variantNode of node.options) {
4199
- const variantType = checkUnionVariant(variantNode, mapper);
4337
+ const variantType = checkUnionVariant(ctx, variantNode);
4200
4338
  variantType.union = parentUnion;
4201
4339
  if (variants.has(variantType.name)) {
4202
4340
  reportCheckerDiagnostic(createDiagnostic({
@@ -4209,14 +4347,14 @@ export function createChecker(program, resolver) {
4209
4347
  variants.set(variantType.name, variantType);
4210
4348
  }
4211
4349
  }
4212
- function checkUnionVariant(variantNode, mapper) {
4350
+ function checkUnionVariant(ctx, variantNode) {
4213
4351
  const links = getSymbolLinksForMember(variantNode);
4214
- if (links && links.declaredType && mapper === undefined) {
4352
+ if (links && links.declaredType && ctx.mapper === undefined) {
4215
4353
  // we're not instantiating this union variant and we've already checked it
4216
4354
  return links.declaredType;
4217
4355
  }
4218
4356
  const name = variantNode.id ? variantNode.id.sv : Symbol("name");
4219
- const type = getTypeForNode(variantNode.value, mapper);
4357
+ const type = getTypeForNode(variantNode.value, ctx);
4220
4358
  const variantType = createType({
4221
4359
  kind: "UnionVariant",
4222
4360
  name,
@@ -4225,13 +4363,13 @@ export function createChecker(program, resolver) {
4225
4363
  type,
4226
4364
  union: undefined,
4227
4365
  });
4228
- variantType.decorators = checkDecorators(variantType, variantNode, mapper);
4229
- linkMapper(variantType, mapper);
4366
+ variantType.decorators = checkDecorators(ctx, variantType, variantNode);
4367
+ linkMapper(variantType, ctx.mapper);
4230
4368
  if (links) {
4231
- linkType(links, variantType, mapper);
4369
+ linkType(ctx, links, variantType);
4232
4370
  }
4233
4371
  return finishType(variantType, {
4234
- skipDecorators: !shouldRunDecorators(variantNode.parent, mapper),
4372
+ skipDecorators: ctx.hasFlags(CheckFlags.InTemplateDeclaration),
4235
4373
  });
4236
4374
  }
4237
4375
  function isMemberNode(node) {
@@ -4252,7 +4390,7 @@ export function createChecker(program, resolver) {
4252
4390
  const sym = getSymbolForMember(node);
4253
4391
  return sym ? (getSymNode(sym) === node ? getSymbolLinks(sym) : undefined) : undefined;
4254
4392
  }
4255
- function checkEnumMember(node, mapper, parentEnum) {
4393
+ function checkEnumMember(ctx, node, parentEnum) {
4256
4394
  const name = node.id.sv;
4257
4395
  const links = getSymbolLinksForMember(node);
4258
4396
  if (links?.type) {
@@ -4271,12 +4409,12 @@ export function createChecker(program, resolver) {
4271
4409
  if (links) {
4272
4410
  links.type = member;
4273
4411
  }
4274
- member.decorators = checkDecorators(member, node, mapper);
4412
+ member.decorators = checkDecorators(ctx, member, node);
4275
4413
  return finishType(member);
4276
4414
  }
4277
- function checkEnumSpreadMember(parentEnumSym, parentEnum, targetNode, mapper, existingMemberNames) {
4415
+ function checkEnumSpreadMember(ctx, parentEnumSym, parentEnum, targetNode, existingMemberNames) {
4278
4416
  const members = [];
4279
- const targetType = getTypeForNode(targetNode, mapper);
4417
+ const targetType = getTypeForNode(targetNode, ctx);
4280
4418
  if (!isErrorType(targetType)) {
4281
4419
  if (targetType.kind !== "Enum") {
4282
4420
  reportCheckerDiagnostic(createDiagnostic({ code: "spread-enum", target: targetNode }));
@@ -4446,7 +4584,7 @@ export function createChecker(program, resolver) {
4446
4584
  decorators: [],
4447
4585
  });
4448
4586
  getSymbolLinks(sym).type = type;
4449
- type.decorators = checkAugmentDecorators(sym, type, undefined);
4587
+ type.decorators = checkAugmentDecorators(CheckContext.DEFAULT, sym, type);
4450
4588
  return finishType(type);
4451
4589
  }
4452
4590
  function initializeClone(type, additionalProps) {
@@ -4559,7 +4697,7 @@ export function createChecker(program, resolver) {
4559
4697
  if (docComment) {
4560
4698
  clone.decorators.push(createDocFromCommentDecorator("self", docComment));
4561
4699
  }
4562
- for (const dec of checkAugmentDecorators(sym, clone, undefined)) {
4700
+ for (const dec of checkAugmentDecorators(CheckContext.DEFAULT, sym, clone)) {
4563
4701
  clone.decorators.push(dec);
4564
4702
  }
4565
4703
  }
@@ -4960,17 +5098,6 @@ function getDocContent(content) {
4960
5098
  }
4961
5099
  return docs.join("");
4962
5100
  }
4963
- function reportDeprecation(program, target, message, reportFunc) {
4964
- if (program.compilerOptions.ignoreDeprecated !== true) {
4965
- reportFunc(createDiagnostic({
4966
- code: "deprecated",
4967
- format: {
4968
- message,
4969
- },
4970
- target,
4971
- }));
4972
- }
4973
- }
4974
5101
  function applyDecoratorToType(program, decApp, target) {
4975
5102
  compilerAssert("decorators" in target, "Cannot apply decorator to non-decoratable type", target);
4976
5103
  for (const arg of decApp.args) {
@@ -4983,7 +5110,7 @@ function applyDecoratorToType(program, decApp, target) {
4983
5110
  if (decApp.definition) {
4984
5111
  const deprecation = getDeprecationDetails(program, decApp.definition);
4985
5112
  if (deprecation !== undefined) {
4986
- reportDeprecation(program, decApp.node ?? target, deprecation.message, program.reportDiagnostic);
5113
+ reportDeprecated(program, deprecation.message, decApp.node ?? target);
4987
5114
  }
4988
5115
  }
4989
5116
  // peel `fn` off to avoid setting `this`.