@typespec/compiler 1.10.0-dev.0 → 1.10.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 (137) hide show
  1. package/dist/generated-defs/TypeSpec.Prototypes.ts-test.js +1 -1
  2. package/dist/generated-defs/TypeSpec.Prototypes.ts-test.js.map +1 -1
  3. package/dist/generated-defs/TypeSpec.ts-test.js +1 -1
  4. package/dist/generated-defs/TypeSpec.ts-test.js.map +1 -1
  5. package/dist/manifest.js +2 -2
  6. package/dist/src/core/binder.d.ts.map +1 -1
  7. package/dist/src/core/binder.js +33 -19
  8. package/dist/src/core/binder.js.map +1 -1
  9. package/dist/src/core/checker.d.ts.map +1 -1
  10. package/dist/src/core/checker.js +594 -67
  11. package/dist/src/core/checker.js.map +1 -1
  12. package/dist/src/core/cli/actions/info/emitter-options.d.ts +40 -0
  13. package/dist/src/core/cli/actions/info/emitter-options.d.ts.map +1 -0
  14. package/dist/src/core/cli/actions/info/emitter-options.js +345 -0
  15. package/dist/src/core/cli/actions/info/emitter-options.js.map +1 -0
  16. package/dist/src/core/cli/actions/info.d.ts +5 -2
  17. package/dist/src/core/cli/actions/info.d.ts.map +1 -1
  18. package/dist/src/core/cli/actions/info.js +6 -2
  19. package/dist/src/core/cli/actions/info.js.map +1 -1
  20. package/dist/src/core/cli/cli.js +43 -4
  21. package/dist/src/core/cli/cli.js.map +1 -1
  22. package/dist/src/core/helpers/string-template-utils.d.ts.map +1 -1
  23. package/dist/src/core/helpers/string-template-utils.js +7 -4
  24. package/dist/src/core/helpers/string-template-utils.js.map +1 -1
  25. package/dist/src/core/helpers/syntax-utils.d.ts.map +1 -1
  26. package/dist/src/core/helpers/syntax-utils.js +11 -3
  27. package/dist/src/core/helpers/syntax-utils.js.map +1 -1
  28. package/dist/src/core/helpers/type-name-utils.d.ts.map +1 -1
  29. package/dist/src/core/helpers/type-name-utils.js +13 -0
  30. package/dist/src/core/helpers/type-name-utils.js.map +1 -1
  31. package/dist/src/core/js-marshaller.d.ts +4 -2
  32. package/dist/src/core/js-marshaller.d.ts.map +1 -1
  33. package/dist/src/core/js-marshaller.js +96 -6
  34. package/dist/src/core/js-marshaller.js.map +1 -1
  35. package/dist/src/core/messages.d.ts +123 -32
  36. package/dist/src/core/messages.d.ts.map +1 -1
  37. package/dist/src/core/messages.js +29 -6
  38. package/dist/src/core/messages.js.map +1 -1
  39. package/dist/src/core/modifiers.d.ts +14 -0
  40. package/dist/src/core/modifiers.d.ts.map +1 -0
  41. package/dist/src/core/modifiers.js +166 -0
  42. package/dist/src/core/modifiers.js.map +1 -0
  43. package/dist/src/core/module-host.d.ts +5 -0
  44. package/dist/src/core/module-host.d.ts.map +1 -0
  45. package/dist/src/core/module-host.js +12 -0
  46. package/dist/src/core/module-host.js.map +1 -0
  47. package/dist/src/core/name-resolver.d.ts.map +1 -1
  48. package/dist/src/core/name-resolver.js +32 -0
  49. package/dist/src/core/name-resolver.js.map +1 -1
  50. package/dist/src/core/parser.d.ts.map +1 -1
  51. package/dist/src/core/parser.js +154 -101
  52. package/dist/src/core/parser.js.map +1 -1
  53. package/dist/src/core/program.d.ts.map +1 -1
  54. package/dist/src/core/program.js +5 -11
  55. package/dist/src/core/program.js.map +1 -1
  56. package/dist/src/core/scanner.d.ts +48 -48
  57. package/dist/src/core/scanner.d.ts.map +1 -1
  58. package/dist/src/core/scanner.js +55 -56
  59. package/dist/src/core/scanner.js.map +1 -1
  60. package/dist/src/core/semantic-walker.d.ts +3 -3
  61. package/dist/src/core/semantic-walker.d.ts.map +1 -1
  62. package/dist/src/core/semantic-walker.js +63 -44
  63. package/dist/src/core/semantic-walker.js.map +1 -1
  64. package/dist/src/core/source-loader.d.ts.map +1 -1
  65. package/dist/src/core/source-loader.js +4 -11
  66. package/dist/src/core/source-loader.js.map +1 -1
  67. package/dist/src/core/type-relation-checker.d.ts.map +1 -1
  68. package/dist/src/core/type-relation-checker.js +157 -10
  69. package/dist/src/core/type-relation-checker.js.map +1 -1
  70. package/dist/src/core/types.d.ts +215 -32
  71. package/dist/src/core/types.d.ts.map +1 -1
  72. package/dist/src/core/types.js +2 -0
  73. package/dist/src/core/types.js.map +1 -1
  74. package/dist/src/experimental/mutators.js +3 -3
  75. package/dist/src/experimental/mutators.js.map +1 -1
  76. package/dist/src/experimental/typekit/index.d.ts.map +1 -1
  77. package/dist/src/experimental/typekit/index.js.map +1 -1
  78. package/dist/src/formatter/print/printer.d.ts +2 -2
  79. package/dist/src/formatter/print/printer.d.ts.map +1 -1
  80. package/dist/src/formatter/print/printer.js +55 -5
  81. package/dist/src/formatter/print/printer.js.map +1 -1
  82. package/dist/src/index.d.ts +3 -2
  83. package/dist/src/index.d.ts.map +1 -1
  84. package/dist/src/index.js +2 -1
  85. package/dist/src/index.js.map +1 -1
  86. package/dist/src/lib/examples.d.ts +10 -3
  87. package/dist/src/lib/examples.d.ts.map +1 -1
  88. package/dist/src/lib/examples.js +22 -7
  89. package/dist/src/lib/examples.js.map +1 -1
  90. package/dist/src/server/compile-service.d.ts.map +1 -1
  91. package/dist/src/server/compile-service.js +12 -6
  92. package/dist/src/server/compile-service.js.map +1 -1
  93. package/dist/src/server/completion.js +1 -0
  94. package/dist/src/server/completion.js.map +1 -1
  95. package/dist/src/server/constants.d.ts +0 -5
  96. package/dist/src/server/constants.d.ts.map +1 -1
  97. package/dist/src/server/constants.js +0 -5
  98. package/dist/src/server/constants.js.map +1 -1
  99. package/dist/src/server/debug.d.ts +12 -0
  100. package/dist/src/server/debug.d.ts.map +1 -0
  101. package/dist/src/server/debug.js +49 -0
  102. package/dist/src/server/debug.js.map +1 -0
  103. package/dist/src/server/entrypoint-resolver.d.ts.map +1 -1
  104. package/dist/src/server/entrypoint-resolver.js +7 -4
  105. package/dist/src/server/entrypoint-resolver.js.map +1 -1
  106. package/dist/src/server/server-compile-manager.d.ts.map +1 -1
  107. package/dist/src/server/server-compile-manager.js +4 -7
  108. package/dist/src/server/server-compile-manager.js.map +1 -1
  109. package/dist/src/server/tmlanguage.d.ts +1 -1
  110. package/dist/src/server/tmlanguage.d.ts.map +1 -1
  111. package/dist/src/server/tmlanguage.js +39 -29
  112. package/dist/src/server/tmlanguage.js.map +1 -1
  113. package/dist/src/server/type-signature.js +19 -0
  114. package/dist/src/server/type-signature.js.map +1 -1
  115. package/dist/src/server/update-manager.d.ts.map +1 -1
  116. package/dist/src/server/update-manager.js +7 -8
  117. package/dist/src/server/update-manager.js.map +1 -1
  118. package/dist/src/utils/fs-utils.d.ts.map +1 -1
  119. package/dist/src/utils/fs-utils.js +1 -1
  120. package/dist/src/utils/fs-utils.js.map +1 -1
  121. package/dist/typespec.tmLanguage +103 -53
  122. package/lib/prototypes.tsp +2 -1
  123. package/package.json +13 -14
  124. package/templates/__snapshots__/emitter-ts/eslint.config.js +10 -1
  125. package/templates/__snapshots__/emitter-ts/package.json +1 -2
  126. package/templates/__snapshots__/emitter-ts/test/test-host.ts +7 -34
  127. package/templates/__snapshots__/library-ts/eslint.config.js +10 -1
  128. package/templates/__snapshots__/library-ts/package.json +1 -2
  129. package/templates/__snapshots__/library-ts/test/decorators.test.ts +18 -23
  130. package/templates/__snapshots__/library-ts/test/test-host.ts +5 -15
  131. package/templates/emitter-ts/eslint.config.js +10 -1
  132. package/templates/emitter-ts/package.json +1 -2
  133. package/templates/emitter-ts/test/test-host.ts.mu +7 -34
  134. package/templates/library-ts/eslint.config.js +10 -1
  135. package/templates/library-ts/package.json +1 -2
  136. package/templates/library-ts/test/decorators.test.ts.mu +18 -23
  137. package/templates/library-ts/test/test-host.ts.mu +5 -15
@@ -7,13 +7,15 @@ 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, reportDeprecated } from "./diagnostics.js";
10
+ import { compilerAssert, createDiagnosticCollector, ignoreDiagnostics, reportDeprecated, } from "./diagnostics.js";
11
11
  import { validateInheritanceDiscriminatedUnions } from "./helpers/discriminator-utils.js";
12
+ import { getLocationContext } from "./helpers/location-context.js";
12
13
  import { explainStringTemplateNotSerializable } from "./helpers/string-template-utils.js";
13
14
  import { typeReferenceToString } from "./helpers/syntax-utils.js";
14
15
  import { getEntityName, getTypeName } from "./helpers/type-name-utils.js";
15
- import { marshallTypeForJS } from "./js-marshaller.js";
16
+ import { marshalTypeForJs, unmarshalJsToValue } from "./js-marshaller.js";
16
17
  import { createDiagnostic } from "./messages.js";
18
+ import { checkModifiers } from "./modifiers.js";
17
19
  import { Numeric } from "./numeric.js";
18
20
  import { exprIsBareIdentifier, getFirstAncestor, getIdentifierContext, hasParseError, visitChildren, } from "./parser.js";
19
21
  import { createTypeRelationChecker } from "./type-relation-checker.js";
@@ -175,6 +177,7 @@ export function createChecker(program, resolver) {
175
177
  nullType,
176
178
  anyType: unknownType,
177
179
  voidType,
180
+ unknownType,
178
181
  typePrototype,
179
182
  createType,
180
183
  createAndFinishType,
@@ -228,6 +231,16 @@ export function createChecker(program, resolver) {
228
231
  declarations: [],
229
232
  node: undefined, // TODO: is this correct?
230
233
  });
234
+ const internalDecorators = [
235
+ typespecNamespaceBinding.exports?.get("@indexer"),
236
+ typespecNamespaceBinding.exports?.get("@docFromComment"),
237
+ typespecNamespaceBinding.exports?.get("Prototypes")?.exports?.get("@getter"),
238
+ ];
239
+ for (const decorator of internalDecorators) {
240
+ if (decorator) {
241
+ mutate(decorator).flags |= 8388608 /* SymbolFlags.Internal */;
242
+ }
243
+ }
231
244
  // Until we have an `unit` type for `null`
232
245
  mutate(resolver.symbols.null).type = nullType;
233
246
  getSymbolLinks(resolver.symbols.null).type = nullType;
@@ -346,7 +359,7 @@ export function createChecker(program, resolver) {
346
359
  function getValueForNode(node, mapperOrContext, constraint) {
347
360
  const ctx = CheckContext.from(mapperOrContext);
348
361
  const initial = checkNode(ctx, node, constraint);
349
- if (initial === null) {
362
+ if (initial === null || initial === errorType) {
350
363
  return null;
351
364
  }
352
365
  let entity;
@@ -360,6 +373,8 @@ export function createChecker(program, resolver) {
360
373
  return null;
361
374
  }
362
375
  if (isValue(entity)) {
376
+ if (entity.valueKind === "Function")
377
+ return entity;
363
378
  return constraint ? inferScalarsFromConstraints(entity, constraint.type) : entity;
364
379
  }
365
380
  // If a template parameter that can be a value is used in a template declaration then we allow it but we return null because we don't have an actual value.
@@ -420,9 +435,8 @@ export function createChecker(program, resolver) {
420
435
  case "UnionVariant":
421
436
  return getValueFromIndeterminate(type.type, constraint, node);
422
437
  case "Intrinsic":
423
- switch (type.name) {
424
- case "null":
425
- return checkNullValue(type, constraint, node);
438
+ if (type.name === "null") {
439
+ return checkNullValue(type, constraint, node);
426
440
  }
427
441
  return type;
428
442
  default:
@@ -477,8 +491,8 @@ export function createChecker(program, resolver) {
477
491
  * For nodes that can be both type or values(e.g. string), the value will be returned if the constraint expect a value of that type even if the constrain also allows the type.
478
492
  * This means that if the constraint is `string | valueof string` passing `"abc"` will send the value `"abc"` and not the type `"abc"`.
479
493
  */
480
- function getTypeOrValueForNode(node, mapper, constraint) {
481
- const ctx = CheckContext.from(mapper);
494
+ function getTypeOrValueForNode(node, contextOrMapper, constraint) {
495
+ const ctx = CheckContext.from(contextOrMapper);
482
496
  const valueConstraint = extractValueOfConstraints(constraint);
483
497
  const entity = checkNode(ctx, node, valueConstraint);
484
498
  if (entity === null) {
@@ -507,6 +521,12 @@ export function createChecker(program, resolver) {
507
521
  reportCheckerDiagnostics(valueDiagnostics);
508
522
  return result;
509
523
  }
524
+ else {
525
+ const canBeType = constraint?.constraint.type !== undefined;
526
+ // If the node _must_ resolve to a value, we will return it unconstrained, so that we will at least produce
527
+ // a value. If it _can_ be a type, we already failed the value constraint, so we return the type as is.
528
+ return canBeType ? entity.type : getValueFromIndeterminate(entity.type, undefined, node);
529
+ }
510
530
  }
511
531
  return entity.type;
512
532
  }
@@ -571,6 +591,8 @@ export function createChecker(program, resolver) {
571
591
  return checkDecoratorDeclaration(ctx, node);
572
592
  case SyntaxKind.FunctionDeclarationStatement:
573
593
  return checkFunctionDeclaration(ctx, node);
594
+ case SyntaxKind.FunctionTypeExpression:
595
+ return checkFunctionTypeExpression(ctx, node);
574
596
  case SyntaxKind.TypeReference:
575
597
  return checkTypeOrValueReference(ctx, node);
576
598
  case SyntaxKind.TemplateArgument:
@@ -711,6 +733,7 @@ export function createChecker(program, resolver) {
711
733
  * @param node Node.
712
734
  * @param mapper Type mapper for template instantiation context.
713
735
  * @param instantiateTemplate If templated type should be instantiated if they haven't yet.
736
+ * @param allowFunctions If functions are allowed as types.
714
737
  * @returns Resolved type.
715
738
  */
716
739
  function checkTypeReference(ctx, node, instantiateTemplate = true) {
@@ -726,6 +749,7 @@ export function createChecker(program, resolver) {
726
749
  * @param node Node.
727
750
  * @param mapper Type mapper for template instantiation context.
728
751
  * @param instantiateTemplate If templated type should be instantiated if they haven't yet.
752
+ * @param allowFunctions If functions are allowed as types.
729
753
  * @returns Resolved type.
730
754
  */
731
755
  function checkTypeOrValueReference(ctx, node, instantiateTemplate = true) {
@@ -953,6 +977,7 @@ export function createChecker(program, resolver) {
953
977
  * @param node Node
954
978
  * @param mapper Type mapper for template instantiation context.
955
979
  * @param instantiateTemplates If a templated type should be instantiated if not yet @default true
980
+ * @param allowFunctions If functions are allowed as types. @default false
956
981
  * @returns resolved type.
957
982
  */
958
983
  function checkTypeReferenceSymbol(ctx, sym, node, instantiateTemplates = true) {
@@ -983,8 +1008,7 @@ export function createChecker(program, resolver) {
983
1008
  return errorType;
984
1009
  }
985
1010
  if (sym.flags & 2048 /* SymbolFlags.Function */) {
986
- reportCheckerDiagnostic(createDiagnostic({ code: "invalid-type-ref", messageId: "function", target: sym }));
987
- return errorType;
1011
+ return getValueForNode(sym.declarations[0], ctx);
988
1012
  }
989
1013
  const argumentNodes = node.kind === SyntaxKind.TypeReference ? node.arguments : [];
990
1014
  const symbolLinks = getSymbolLinks(sym);
@@ -1141,7 +1165,7 @@ export function createChecker(program, resolver) {
1141
1165
  function checkDeclaredType(ctx, sym, node) {
1142
1166
  return getTypeForTypeOrIndeterminate(checkDeclaredTypeOrIndeterminate(ctx, sym, node));
1143
1167
  }
1144
- function getOrInstantiateTemplate(ctx, templateNode, params, args, source, parentMapper, instantiateTempalates = true) {
1168
+ function getOrInstantiateTemplate(ctx, templateNode, params, args, source, parentMapper, instantiateTemplates = true) {
1145
1169
  const symbolLinks = templateNode.kind === SyntaxKind.OperationStatement &&
1146
1170
  templateNode.parent.kind === SyntaxKind.InterfaceStatement
1147
1171
  ? getSymbolLinksForMember(templateNode)
@@ -1161,7 +1185,7 @@ export function createChecker(program, resolver) {
1161
1185
  if (cached) {
1162
1186
  return cached;
1163
1187
  }
1164
- if (instantiateTempalates) {
1188
+ if (instantiateTemplates) {
1165
1189
  return instantiateTemplate(ctx.withMapper(mapper), symbolLinks.instantiations, templateNode, params);
1166
1190
  }
1167
1191
  else {
@@ -1331,12 +1355,10 @@ export function createChecker(program, resolver) {
1331
1355
  // we're not instantiating this operation and we've already checked it
1332
1356
  return links.declaredType;
1333
1357
  }
1358
+ checkModifiers(program, node);
1334
1359
  const namespace = getParentNamespaceType(node);
1335
1360
  compilerAssert(namespace, `Decorator ${node.id.sv} should have resolved a namespace or found the global namespace.`);
1336
1361
  const name = node.id.sv;
1337
- if (!(node.modifierFlags & 2 /* ModifierFlags.Extern */)) {
1338
- reportCheckerDiagnostic(createDiagnostic({ code: "decorator-extern", target: node }));
1339
- }
1340
1362
  const implementation = symbol.value;
1341
1363
  if (implementation === undefined) {
1342
1364
  reportCheckerDiagnostic(createDiagnostic({ code: "missing-implementation", target: node }));
@@ -1355,8 +1377,67 @@ export function createChecker(program, resolver) {
1355
1377
  return decoratorType;
1356
1378
  }
1357
1379
  function checkFunctionDeclaration(ctx, node) {
1358
- reportCheckerDiagnostic(createDiagnostic({ code: "function-unsupported", target: node }));
1359
- return errorType;
1380
+ const mergedSymbol = getMergedSymbol(node.symbol);
1381
+ const links = getSymbolLinks(mergedSymbol);
1382
+ if (links.value !== undefined) {
1383
+ return links.value;
1384
+ }
1385
+ checkModifiers(program, node);
1386
+ reportCheckerDiagnostic(createDiagnostic({
1387
+ code: "experimental-feature",
1388
+ messageId: "functionDeclarations",
1389
+ target: node,
1390
+ }));
1391
+ const namespace = getParentNamespaceType(node);
1392
+ compilerAssert(namespace, `Function ${node.id.sv} should have resolved a declared namespace or the global namespace.`);
1393
+ const name = node.id.sv;
1394
+ const implementation = mergedSymbol.value;
1395
+ if (implementation === undefined) {
1396
+ reportCheckerDiagnostic(createDiagnostic({ code: "missing-implementation", target: node }));
1397
+ }
1398
+ const parameters = node.parameters.map((x) => checkFunctionParameter(ctx, x, true));
1399
+ const returnType = node.returnType
1400
+ ? getParamConstraintEntityForNode(ctx, node.returnType)
1401
+ : {
1402
+ entityKind: "MixedParameterConstraint",
1403
+ type: unknownType,
1404
+ };
1405
+ const functionValue = createValue({
1406
+ entityKind: "Value",
1407
+ valueKind: "Function",
1408
+ name,
1409
+ type: createAndFinishType({
1410
+ kind: "FunctionType",
1411
+ parameters,
1412
+ returnType,
1413
+ }),
1414
+ parameters,
1415
+ returnType,
1416
+ namespace,
1417
+ node,
1418
+ implementation: implementation ??
1419
+ Object.assign(() => getDefaultFunctionResult(returnType), {
1420
+ isDefaultFunctionImplementation: true,
1421
+ }),
1422
+ }, unknownType);
1423
+ namespace.functionDeclarations.set(name, functionValue);
1424
+ links.value = functionValue;
1425
+ return functionValue;
1426
+ }
1427
+ function checkFunctionTypeExpression(ctx, node) {
1428
+ const parameters = node.parameters.map((param) => checkFunctionParameter(ctx, param, true));
1429
+ const returnType = node.returnType
1430
+ ? getParamConstraintEntityForNode(ctx, node.returnType)
1431
+ : {
1432
+ entityKind: "MixedParameterConstraint",
1433
+ type: unknownType,
1434
+ };
1435
+ return createAndFinishType({
1436
+ kind: "FunctionType",
1437
+ node,
1438
+ parameters,
1439
+ returnType,
1440
+ });
1360
1441
  }
1361
1442
  function checkFunctionParameter(ctx, node, mixed) {
1362
1443
  const links = getSymbolLinks(node.symbol);
@@ -1512,6 +1593,7 @@ export function createChecker(program, resolver) {
1512
1593
  type = initializeTypeForNamespace(node);
1513
1594
  }
1514
1595
  if (node.kind === SyntaxKind.NamespaceStatement) {
1596
+ checkModifiers(program, node);
1515
1597
  if (isArray(node.statements)) {
1516
1598
  node.statements.forEach((x) => checkNode(ctx, x));
1517
1599
  }
@@ -1619,6 +1701,9 @@ export function createChecker(program, resolver) {
1619
1701
  return links.declaredType;
1620
1702
  }
1621
1703
  }
1704
+ if (ctx.mapper === undefined) {
1705
+ checkModifiers(program, node);
1706
+ }
1622
1707
  if (ctx.mapper === undefined && inInterface) {
1623
1708
  compilerAssert(parentInterface, "Operation in interface should already have been checked.", node.parent);
1624
1709
  }
@@ -1979,7 +2064,7 @@ export function createChecker(program, resolver) {
1979
2064
  return undefined;
1980
2065
  }
1981
2066
  const ctorType = checkCallExpressionTarget(CheckContext.DEFAULT, callExpNode);
1982
- if (ctorType?.kind !== "ScalarConstructor") {
2067
+ if (ctorType?.entityKind !== "Type" || ctorType?.kind !== "ScalarConstructor") {
1983
2068
  return undefined;
1984
2069
  }
1985
2070
  const argIndex = callExpNode.arguments.findIndex((n) => n === argNode);
@@ -2209,12 +2294,15 @@ export function createChecker(program, resolver) {
2209
2294
  case IdentifierKind.Decorator:
2210
2295
  // Only return decorators and namespaces when completing decorator
2211
2296
  return !!(sym.flags & (512 /* SymbolFlags.Decorator */ | 256 /* SymbolFlags.Namespace */));
2297
+ case IdentifierKind.Function:
2298
+ // Only return functions and namespaces when completing function calls
2299
+ return !!(sym.flags & (2048 /* SymbolFlags.Function */ | 256 /* SymbolFlags.Namespace */));
2212
2300
  case IdentifierKind.Using:
2213
2301
  // Only return namespaces when completing using
2214
2302
  return !!(sym.flags & 256 /* SymbolFlags.Namespace */);
2215
2303
  case IdentifierKind.TypeReference:
2216
- // Do not return functions or decorators when completing types
2217
- return !(sym.flags & (2048 /* SymbolFlags.Function */ | 512 /* SymbolFlags.Decorator */));
2304
+ // Do not return decorators when completing types
2305
+ return !(sym.flags & 512 /* SymbolFlags.Decorator */);
2218
2306
  case IdentifierKind.TemplateArgument:
2219
2307
  return !!(sym.flags & 1024 /* SymbolFlags.TemplateParameter */);
2220
2308
  default:
@@ -2239,6 +2327,7 @@ export function createChecker(program, resolver) {
2239
2327
  referenceSymCache.has(node)) {
2240
2328
  return referenceSymCache.get(node);
2241
2329
  }
2330
+ resolvedOptions.locationContext ??= getLocationContext(program, node);
2242
2331
  const sym = resolveTypeReferenceSymInternal(ctx, node, resolvedOptions);
2243
2332
  if (!resolvedOptions.resolveDeclarationOfTemplate) {
2244
2333
  referenceSymCache.set(node, sym);
@@ -2271,8 +2360,9 @@ export function createChecker(program, resolver) {
2271
2360
  reportAmbiguousIdentifier(node, links.ambiguousSymbols);
2272
2361
  }
2273
2362
  }
2274
- const sym = links.resolvedSymbol;
2275
- return sym?.symbolSource ?? sym;
2363
+ const sym = links.resolvedSymbol?.symbolSource ?? links.resolvedSymbol;
2364
+ checkSymbolAccess(options.locationContext, node, sym);
2365
+ return sym;
2276
2366
  }
2277
2367
  else if (node.kind === SyntaxKind.MemberExpression) {
2278
2368
  let base = resolveTypeReferenceSym(ctx, node.base, {
@@ -2284,22 +2374,42 @@ export function createChecker(program, resolver) {
2284
2374
  }
2285
2375
  // when resolving a type reference based on an alias, unwrap the alias.
2286
2376
  if (base.flags & 128 /* SymbolFlags.Alias */) {
2287
- const aliasedSym = getAliasedSymbol(ctx, base);
2288
- if (!aliasedSym) {
2289
- reportCheckerDiagnostic(createDiagnostic({
2290
- code: "invalid-ref",
2291
- messageId: "node",
2292
- format: {
2293
- id: node.id.sv,
2294
- nodeName: base.declarations[0]
2295
- ? SyntaxKind[base.declarations[0].kind]
2296
- : "Unknown node",
2297
- },
2298
- target: node,
2299
- }));
2300
- return undefined;
2377
+ if (!options.resolveDeclarationOfTemplate && isTemplatedNode(getSymNode(base))) {
2378
+ // This is a bare identifier reference to a templated alias, so we need to actually check this type.
2379
+ const ty = checkTypeReferenceSymbol(ctx.withMapper(undefined), base, node.base,
2380
+ /* instantiateTemplates */ true);
2381
+ base = lateBindContainer(ty, base);
2382
+ if (base?.members) {
2383
+ switch (ty.kind) {
2384
+ case "Model":
2385
+ case "Union":
2386
+ case "Interface":
2387
+ case "Enum":
2388
+ case "Scalar":
2389
+ lateBindMembers(ty);
2390
+ }
2391
+ }
2392
+ if (!base)
2393
+ return undefined;
2394
+ }
2395
+ else {
2396
+ const aliasedSym = getAliasedSymbol(ctx, base);
2397
+ if (!aliasedSym) {
2398
+ reportCheckerDiagnostic(createDiagnostic({
2399
+ code: "invalid-ref",
2400
+ messageId: "node",
2401
+ format: {
2402
+ id: node.id.sv,
2403
+ nodeName: base.declarations[0]
2404
+ ? SyntaxKind[base.declarations[0].kind]
2405
+ : "Unknown node",
2406
+ },
2407
+ target: node,
2408
+ }));
2409
+ return undefined;
2410
+ }
2411
+ base = aliasedSym;
2301
2412
  }
2302
- base = aliasedSym;
2303
2413
  }
2304
2414
  else if (!options.resolveDeclarationOfTemplate && isTemplatedNode(getSymNode(base))) {
2305
2415
  const baseSym = getContainerTemplateSymbol(ctx, base, node.base);
@@ -2308,10 +2418,47 @@ export function createChecker(program, resolver) {
2308
2418
  }
2309
2419
  base = baseSym;
2310
2420
  }
2311
- return resolveMemberInContainer(base, node, options);
2421
+ const sym = resolveMemberInContainer(base, node, options);
2422
+ checkSymbolAccess(options.locationContext, node, sym);
2423
+ return sym;
2312
2424
  }
2313
2425
  compilerAssert(false, `Unknown type reference kind "${SyntaxKind[node.kind]}"`, node);
2314
2426
  }
2427
+ function checkSymbolAccess(sourceLocation, node, symbol) {
2428
+ if (!symbol)
2429
+ return;
2430
+ const isInternalDeclaration = (symbol.flags & (8388608 /* SymbolFlags.Internal */ | 1048576 /* SymbolFlags.Declaration */)) ===
2431
+ (8388608 /* SymbolFlags.Internal */ | 1048576 /* SymbolFlags.Declaration */);
2432
+ if (isInternalDeclaration) {
2433
+ // The source location can access internal declaration symbols if:
2434
+ // 1. The source location is synthetic.
2435
+ // 2. The source location is in the compiler standard library.
2436
+ // 3. SOME declaration of the target symbol meets the following:
2437
+ // 1. The source location is in the user project, and the symbol is also declared in the user project.
2438
+ // 2. The source location is in a library, and the symbol is also in the same library.
2439
+ if (sourceLocation.type === "synthetic" || sourceLocation.type === "compiler") {
2440
+ return;
2441
+ }
2442
+ const isDeclaredInCompatibleLocation = symbol.declarations.some((decl) => {
2443
+ const declLocation = getLocationContext(program, decl);
2444
+ if (declLocation.type !== sourceLocation.type)
2445
+ return false;
2446
+ // Both are project
2447
+ if (declLocation.type === "project")
2448
+ return true;
2449
+ // Both are library, use reference equality to check if they are the same library.
2450
+ return declLocation === sourceLocation;
2451
+ });
2452
+ if (isDeclaredInCompatibleLocation)
2453
+ return;
2454
+ reportCheckerDiagnostic(createDiagnostic({
2455
+ code: "invalid-ref",
2456
+ messageId: "internal",
2457
+ format: { id: symbol.name },
2458
+ target: node,
2459
+ }));
2460
+ }
2461
+ }
2315
2462
  function reportAmbiguousIdentifier(node, symbols) {
2316
2463
  const duplicateNames = symbols.map((s) => getFullyQualifiedSymbolName(s, { useGlobalPrefixAtTopLevel: true }));
2317
2464
  program.reportDiagnostic(createDiagnostic({
@@ -2699,6 +2846,9 @@ export function createChecker(program, resolver) {
2699
2846
  // we're not instantiating this model and we've already checked it
2700
2847
  return links.declaredType;
2701
2848
  }
2849
+ if (ctx.mapper === undefined) {
2850
+ checkModifiers(program, node);
2851
+ }
2702
2852
  checkTemplateDeclaration(ctx, node);
2703
2853
  const decorators = [];
2704
2854
  const type = createType({
@@ -3109,17 +3259,68 @@ export function createChecker(program, resolver) {
3109
3259
  }, literalType);
3110
3260
  }
3111
3261
  function checkCallExpressionTarget(ctx, node) {
3112
- const target = checkTypeReference(ctx, node.target);
3113
- if (target.kind === "Scalar" || target.kind === "ScalarConstructor") {
3114
- return target;
3262
+ const target = checkTypeOrValueReference(ctx, node.target);
3263
+ if (target.entityKind === "Type") {
3264
+ if (target.kind === "Scalar" || target.kind === "ScalarConstructor") {
3265
+ return target;
3266
+ }
3267
+ else if (target.kind === "TemplateParameter") {
3268
+ const callable = target.constraint && constraintIsCallable(target.constraint);
3269
+ if (!callable) {
3270
+ reportCheckerDiagnostic(createDiagnostic({
3271
+ code: "non-callable",
3272
+ messageId: "templateParameter",
3273
+ format: {
3274
+ name: target.node.id.sv,
3275
+ constraint: target.constraint
3276
+ ? getEntityName(target.constraint, { printable: true })
3277
+ : "unknown",
3278
+ },
3279
+ target: node.target,
3280
+ }));
3281
+ }
3282
+ return null;
3283
+ }
3115
3284
  }
3116
- else {
3285
+ else if (target.entityKind === "Value") {
3286
+ if (target.valueKind === "Function") {
3287
+ return target;
3288
+ }
3289
+ }
3290
+ const kind = target.entityKind === "Type"
3291
+ ? target.kind
3292
+ : target.entityKind === "Indeterminate"
3293
+ ? target.type.kind
3294
+ : target.valueKind;
3295
+ if (!isErrorType(target)) {
3117
3296
  reportCheckerDiagnostic(createDiagnostic({
3118
3297
  code: "non-callable",
3119
- format: { type: target.kind },
3298
+ format: { type: kind },
3120
3299
  target: node.target,
3121
3300
  }));
3122
- return null;
3301
+ }
3302
+ return null;
3303
+ function constraintIsCallable(constraint) {
3304
+ compilerAssert(constraint.type || constraint.valueType, "Expected constraint to have type or value type");
3305
+ let callable = true;
3306
+ if (constraint.type) {
3307
+ callable &&= typeIsCallable(constraint.type);
3308
+ }
3309
+ if (constraint.valueType) {
3310
+ callable &&= constraint.valueType.kind === "FunctionType";
3311
+ }
3312
+ return callable;
3313
+ }
3314
+ function typeIsCallable(type) {
3315
+ switch (type.kind) {
3316
+ case "Scalar":
3317
+ case "ScalarConstructor":
3318
+ return true;
3319
+ case "Union":
3320
+ return [...type.variants.values()].every(typeIsCallable);
3321
+ default:
3322
+ return false;
3323
+ }
3123
3324
  }
3124
3325
  }
3125
3326
  /** Check the arguments of the call expression are a single value of the given syntax. */
@@ -3244,9 +3445,13 @@ export function createChecker(program, resolver) {
3244
3445
  if (target === null) {
3245
3446
  return null;
3246
3447
  }
3247
- if (target.kind === "ScalarConstructor") {
3448
+ if (target.entityKind === "Type" && target.kind === "ScalarConstructor") {
3248
3449
  return createScalarValue(ctx, node, target);
3249
3450
  }
3451
+ else if (target.entityKind === "Value" && target.valueKind === "Function") {
3452
+ return checkFunctionCall(ctx, node, target);
3453
+ }
3454
+ compilerAssert(target.entityKind === "Type", "Expected type entity");
3250
3455
  if (relation.areScalarsRelated(target, getStdType("string"))) {
3251
3456
  return checkPrimitiveArg(node, target, "StringValue");
3252
3457
  }
@@ -3265,6 +3470,264 @@ export function createChecker(program, resolver) {
3265
3470
  return null;
3266
3471
  }
3267
3472
  }
3473
+ function checkFunctionCall(ctx, node, target) {
3474
+ const [satisfied, resolvedArgs] = checkFunctionCallArguments(ctx, node.arguments, target);
3475
+ const canCall = satisfied &&
3476
+ !ctx.hasFlags(CheckFlags.InTemplateDeclaration) &&
3477
+ !target.implementation.isDefaultFunctionImplementation;
3478
+ const fnCtx = createFunctionContext(program, node);
3479
+ if (!canCall) {
3480
+ return getDefaultFunctionResult(target.returnType);
3481
+ }
3482
+ const functionReturn = target.implementation(fnCtx, ...resolvedArgs);
3483
+ const returnIsEntity = typeof functionReturn === "object" &&
3484
+ functionReturn !== null &&
3485
+ "entityKind" in functionReturn &&
3486
+ (functionReturn.entityKind === "Type" ||
3487
+ functionReturn.entityKind === "Value" ||
3488
+ functionReturn.entityKind === "Indeterminate");
3489
+ // special case for when the return value is `undefined` and the return type is `void` or `valueof void`.
3490
+ if (functionReturn === undefined && isVoidReturn(target.returnType)) {
3491
+ return voidType;
3492
+ }
3493
+ const unmarshaled = returnIsEntity
3494
+ ? functionReturn
3495
+ : unmarshalJsToValue(program, functionReturn, function onInvalid(value) {
3496
+ let valueSummary = String(value);
3497
+ if (valueSummary.length > 30) {
3498
+ valueSummary = valueSummary.slice(0, 27) + "...";
3499
+ }
3500
+ reportCheckerDiagnostic(createDiagnostic({
3501
+ code: "function-return",
3502
+ messageId: "invalid-value",
3503
+ format: { value: valueSummary },
3504
+ target: node,
3505
+ }));
3506
+ });
3507
+ let result = unmarshaled;
3508
+ if (satisfied && result !== null)
3509
+ result = checkFunctionReturn(target, result, node);
3510
+ return result;
3511
+ }
3512
+ function isVoidReturn(constraint) {
3513
+ if (constraint.valueType) {
3514
+ return false;
3515
+ }
3516
+ if (constraint.type) {
3517
+ if (!isVoidType(constraint.type))
3518
+ return false;
3519
+ }
3520
+ return true;
3521
+ function isVoidType(type) {
3522
+ return type.kind === "Intrinsic" && type.name === "void";
3523
+ }
3524
+ }
3525
+ /**
3526
+ * Produces the default function result when a function call cannot be completed.
3527
+ *
3528
+ * This produces `null` if the function has a value type constraint but no type constraint, `errorType`
3529
+ * otherwise (if the function _could_ return a Type).
3530
+ *
3531
+ * @param constraint - The function return constraint.
3532
+ * @returns
3533
+ */
3534
+ function getDefaultFunctionResult(constraint) {
3535
+ if (constraint.valueType) {
3536
+ // If the function _can_ return a value, we will just return null. This is a bit of a hack, but it's the best fallback
3537
+ // for a function that could return a type or value, since returning a type would cause type-in-value errors.
3538
+ return null;
3539
+ }
3540
+ else {
3541
+ compilerAssert(constraint.type, "Expected function to have a return type when it did not have a value type constraint");
3542
+ // If for some reason we cannot evaluate the call, we will return the type constraint itself as a fallback.
3543
+ // This is the strongest thing we can do in the context of an error or a template declaration, since the result
3544
+ // of the function call must be assignable to the constraint, and by the transitive property if the constraint
3545
+ // is assignable in the context of evaluation, so will be the result of any valid evaluation of the implementation.
3546
+ // Technically, this isn't exactly ideal, since it could prevent function calls that return subtypes of the constraint
3547
+ // from assigning if the _result_ would be assignable. However, we have other cases where we check constraints in
3548
+ // templates to try to ensure that any instance will validate. We may need to revisit this in the future, but for
3549
+ // now, I am choosing strictness in the face of uncertainty.
3550
+ return constraint.type;
3551
+ }
3552
+ }
3553
+ function checkFunctionCallArguments(ctx, args, target) {
3554
+ let satisfied = true;
3555
+ const minArgs = target.parameters.filter((p) => !p.optional && !p.rest).length;
3556
+ const maxArgs = target.parameters[target.parameters.length - 1]?.rest
3557
+ ? undefined
3558
+ : target.parameters.length;
3559
+ if (args.length < minArgs) {
3560
+ reportCheckerDiagnostic(createDiagnostic({
3561
+ code: "invalid-argument-count",
3562
+ messageId: "atLeast",
3563
+ format: { actual: args.length.toString(), expected: minArgs.toString() },
3564
+ target: target.node,
3565
+ }));
3566
+ return [false, []];
3567
+ }
3568
+ else if (maxArgs !== undefined && args.length > maxArgs) {
3569
+ reportCheckerDiagnostic(createDiagnostic({
3570
+ code: "invalid-argument-count",
3571
+ format: { actual: args.length.toString(), expected: maxArgs.toString() },
3572
+ target: target.node,
3573
+ }));
3574
+ // This error doesn't actually prevent us from checking the arguments and evaluating the function.
3575
+ }
3576
+ const collector = createDiagnosticCollector();
3577
+ const resolvedArgs = [];
3578
+ let idx = 0;
3579
+ for (const param of target.parameters) {
3580
+ if (param.rest) {
3581
+ const constraint = extractRestParamConstraint(param.type);
3582
+ if (!constraint) {
3583
+ satisfied = false;
3584
+ continue;
3585
+ }
3586
+ const restArgExpressions = args.slice(idx);
3587
+ const restArgs = restArgExpressions.map((arg) => getTypeOrValueForNode(arg, ctx, { kind: "argument", constraint }));
3588
+ if (restArgs.some((x) => x === null)) {
3589
+ satisfied = false;
3590
+ continue;
3591
+ }
3592
+ resolvedArgs.push(...restArgs.map((v, idx) => v !== null && isValue(v) ? marshalTypeForJs(v, undefined) : v));
3593
+ }
3594
+ else {
3595
+ const arg = args[idx++];
3596
+ if (!arg) {
3597
+ if (param.optional) {
3598
+ resolvedArgs.push(undefined);
3599
+ continue;
3600
+ }
3601
+ else {
3602
+ // No need to report a diagnostic here because we already reported one for
3603
+ // invalid argument counts above.
3604
+ satisfied = false;
3605
+ continue;
3606
+ }
3607
+ }
3608
+ // Normal param
3609
+ const checkedArg = getTypeOrValueForNode(arg, ctx, {
3610
+ kind: "argument",
3611
+ constraint: param.type,
3612
+ });
3613
+ if (!checkedArg) {
3614
+ satisfied = false;
3615
+ continue;
3616
+ }
3617
+ const resolved = collector.pipe(checkEntityAssignableToConstraint(checkedArg, param.type, arg));
3618
+ satisfied &&= !!resolved;
3619
+ resolvedArgs.push(resolved
3620
+ ? isValue(resolved)
3621
+ ? marshalTypeForJs(resolved, undefined)
3622
+ : resolved
3623
+ : undefined);
3624
+ }
3625
+ }
3626
+ reportCheckerDiagnostics(collector.diagnostics);
3627
+ return [satisfied, resolvedArgs];
3628
+ }
3629
+ function checkFunctionReturn(target, result, diagnosticTarget) {
3630
+ const [checked, diagnostics] = checkEntityAssignableToConstraint(result, target.returnType, diagnosticTarget);
3631
+ if (diagnostics.length > 0) {
3632
+ reportCheckerDiagnostic(createDiagnostic({
3633
+ code: "function-return",
3634
+ messageId: "unassignable",
3635
+ format: {
3636
+ name: getEntityName(target, { printable: true }),
3637
+ entityKind: result.entityKind.toLowerCase(),
3638
+ return: getEntityName(result, { printable: true }),
3639
+ type: getEntityName(target.returnType, { printable: true }),
3640
+ },
3641
+ target: diagnosticTarget,
3642
+ }));
3643
+ }
3644
+ return checked;
3645
+ }
3646
+ function checkEntityAssignableToConstraint(entity, constraint, diagnosticTarget) {
3647
+ const constraintIsValue = !!constraint.valueType;
3648
+ const constraintIsType = !!constraint.type;
3649
+ const collector = createDiagnosticCollector();
3650
+ switch (true) {
3651
+ case constraintIsValue && constraintIsType: {
3652
+ const tried = tryAssignValue();
3653
+ if (tried[0] !== null || entity.entityKind === "Value") {
3654
+ // Succeeded as value or is a value
3655
+ return tried;
3656
+ }
3657
+ // Now we are guaranteed a type.
3658
+ const typeEntity = entity.entityKind === "Indeterminate" ? entity.type : entity;
3659
+ const assignable = collector.pipe(relation.isTypeAssignableTo(typeEntity, constraint.type, diagnosticTarget));
3660
+ return collector.wrap(assignable ? typeEntity : null);
3661
+ }
3662
+ case constraintIsValue: {
3663
+ const normed = collector.pipe(normalizeValue(entity, constraint, diagnosticTarget));
3664
+ // Error should have been reported in normalizeValue
3665
+ if (!normed)
3666
+ return collector.wrap(null);
3667
+ const assignable = collector.pipe(relation.isValueOfType(normed, constraint.valueType, diagnosticTarget));
3668
+ return collector.wrap(assignable ? normed : null);
3669
+ }
3670
+ case constraintIsType: {
3671
+ if (entity.entityKind === "Indeterminate")
3672
+ entity = entity.type;
3673
+ if (entity.entityKind !== "Type") {
3674
+ collector.add(createDiagnostic({
3675
+ code: "value-in-type",
3676
+ format: { name: getTypeName(entity.type) },
3677
+ target: diagnosticTarget,
3678
+ }));
3679
+ return collector.wrap(null);
3680
+ }
3681
+ const assignable = collector.pipe(relation.isTypeAssignableTo(entity, constraint.type, diagnosticTarget));
3682
+ return collector.wrap(assignable ? entity : null);
3683
+ }
3684
+ default: {
3685
+ compilerAssert(false, "Expected at least one of type or value constraint to be defined.");
3686
+ }
3687
+ }
3688
+ function tryAssignValue() {
3689
+ const collector = createDiagnosticCollector();
3690
+ const normed = collector.pipe(normalizeValue(entity, constraint, diagnosticTarget));
3691
+ const assignable = normed
3692
+ ? collector.pipe(relation.isValueOfType(normed, constraint.valueType, diagnosticTarget))
3693
+ : false;
3694
+ return collector.wrap(assignable ? normed : null);
3695
+ }
3696
+ }
3697
+ function normalizeValue(entity, constraint, diagnosticTarget) {
3698
+ if (entity.entityKind === "Value")
3699
+ return [entity, []];
3700
+ if (entity.entityKind === "Indeterminate") {
3701
+ // Coerce to a value
3702
+ const coerced = getValueFromIndeterminate(entity.type, constraint.type && { kind: "argument", type: constraint.type }, entity.type.node);
3703
+ if (coerced?.entityKind !== "Value") {
3704
+ return [
3705
+ null,
3706
+ [
3707
+ createDiagnostic({
3708
+ code: "expect-value",
3709
+ format: { name: getTypeName(entity.type) },
3710
+ target: diagnosticTarget,
3711
+ }),
3712
+ ],
3713
+ ];
3714
+ }
3715
+ return [coerced, []];
3716
+ }
3717
+ if (entity.entityKind === "Type") {
3718
+ return [
3719
+ null,
3720
+ [
3721
+ createDiagnostic({
3722
+ code: "expect-value",
3723
+ format: { name: getTypeName(entity) },
3724
+ target: diagnosticTarget,
3725
+ }),
3726
+ ],
3727
+ ];
3728
+ }
3729
+ compilerAssert(false, `Unreachable: unexpected entity kind '${entity.entityKind}'`);
3730
+ }
3268
3731
  function checkTypeOfExpression(ctx, node) {
3269
3732
  const entity = checkNode(ctx, node.target, undefined);
3270
3733
  if (entity === null) {
@@ -3646,7 +4109,7 @@ export function createChecker(program, resolver) {
3646
4109
  // if the prop type is an error we don't need to validate again.
3647
4110
  return null;
3648
4111
  }
3649
- const defaultValue = getValueForNode(defaultNode, ctx.mapper, {
4112
+ const defaultValue = getValueForNode(defaultNode, ctx, {
3650
4113
  kind: "assignment",
3651
4114
  type,
3652
4115
  });
@@ -3772,20 +4235,23 @@ export function createChecker(program, resolver) {
3772
4235
  }
3773
4236
  const resolvedArgs = [];
3774
4237
  function resolveArg(argNode, perParamType) {
3775
- const arg = getTypeOrValueForNode(argNode, ctx.mapper, {
4238
+ const arg = getTypeOrValueForNode(argNode, ctx, {
3776
4239
  kind: "argument",
3777
4240
  constraint: perParamType,
3778
4241
  });
3779
4242
  if (arg !== null &&
3780
4243
  !(isType(arg) && isErrorType(arg)) &&
3781
4244
  checkArgumentAssignable(arg, perParamType, argNode)) {
4245
+ const [valid, jsValue] = resolveArgumentJsValue(arg, extractValueOfConstraints({
4246
+ kind: "argument",
4247
+ constraint: perParamType,
4248
+ }), argNode);
4249
+ if (!valid)
4250
+ return undefined;
3782
4251
  return {
3783
4252
  value: arg,
3784
4253
  node: argNode,
3785
- jsValue: resolveDecoratorArgJsValue(arg, extractValueOfConstraints({
3786
- kind: "argument",
3787
- constraint: perParamType,
3788
- })),
4254
+ jsValue,
3789
4255
  };
3790
4256
  }
3791
4257
  else {
@@ -3853,16 +4319,17 @@ export function createChecker(program, resolver) {
3853
4319
  function getIndexType(type) {
3854
4320
  return type.kind === "Model" ? type.indexer?.value : undefined;
3855
4321
  }
3856
- function resolveDecoratorArgJsValue(value, valueConstraint) {
4322
+ function resolveArgumentJsValue(value, valueConstraint, diagnosticTarget) {
3857
4323
  if (valueConstraint !== undefined) {
3858
4324
  if (isValue(value)) {
3859
- return marshallTypeForJS(value, valueConstraint.type);
4325
+ const unmarshaled = marshalTypeForJs(value, valueConstraint.type);
4326
+ return [true, unmarshaled];
3860
4327
  }
3861
4328
  else {
3862
- return value;
4329
+ return [true, value];
3863
4330
  }
3864
4331
  }
3865
- return value;
4332
+ return [true, value];
3866
4333
  }
3867
4334
  function checkArgumentAssignable(argumentType, parameterType, diagnosticTarget) {
3868
4335
  const [valid] = relation.isTypeAssignableTo(argumentType, parameterType, diagnosticTarget);
@@ -3986,6 +4453,9 @@ export function createChecker(program, resolver) {
3986
4453
  // we're not instantiating this model and we've already checked it
3987
4454
  return links.declaredType;
3988
4455
  }
4456
+ if (ctx.mapper === undefined) {
4457
+ checkModifiers(program, node);
4458
+ }
3989
4459
  checkTemplateDeclaration(ctx, node);
3990
4460
  const decorators = [];
3991
4461
  const type = createType({
@@ -4097,6 +4567,9 @@ export function createChecker(program, resolver) {
4097
4567
  if (links.declaredType && ctx.mapper === undefined) {
4098
4568
  return links.declaredType;
4099
4569
  }
4570
+ if (ctx.mapper === undefined) {
4571
+ checkModifiers(program, node);
4572
+ }
4100
4573
  checkTemplateDeclaration(ctx, node);
4101
4574
  const aliasSymId = getNodeSym(node);
4102
4575
  if (pendingResolutions.has(aliasSymId, ResolutionKind.Type)) {
@@ -4130,6 +4603,7 @@ export function createChecker(program, resolver) {
4130
4603
  if (links.value !== undefined) {
4131
4604
  return links.value;
4132
4605
  }
4606
+ checkModifiers(program, node);
4133
4607
  const type = node.type ? getTypeForNode(node.type, undefined) : undefined;
4134
4608
  if (pendingResolutions.has(node.symbol, ResolutionKind.Value)) {
4135
4609
  reportCheckerDiagnostic(createDiagnostic({
@@ -4164,12 +4638,14 @@ export function createChecker(program, resolver) {
4164
4638
  case "EnumValue":
4165
4639
  case "NullValue":
4166
4640
  case "ScalarValue":
4641
+ case "Function":
4167
4642
  return value;
4168
4643
  }
4169
4644
  }
4170
4645
  function checkEnum(ctx, node) {
4171
4646
  const links = getSymbolLinks(node.symbol);
4172
4647
  if (!links.type) {
4648
+ checkModifiers(program, node);
4173
4649
  const enumType = (links.type = createType({
4174
4650
  kind: "Enum",
4175
4651
  name: node.id.sv,
@@ -4219,6 +4695,9 @@ export function createChecker(program, resolver) {
4219
4695
  // we're not instantiating this interface and we've already checked it
4220
4696
  return links.declaredType;
4221
4697
  }
4698
+ if (ctx.mapper === undefined) {
4699
+ checkModifiers(program, node);
4700
+ }
4222
4701
  checkTemplateDeclaration(ctx, node);
4223
4702
  const interfaceType = createType({
4224
4703
  kind: "Interface",
@@ -4305,6 +4784,9 @@ export function createChecker(program, resolver) {
4305
4784
  // we're not instantiating this union and we've already checked it
4306
4785
  return links.declaredType;
4307
4786
  }
4787
+ if (ctx.mapper === undefined) {
4788
+ checkModifiers(program, node);
4789
+ }
4308
4790
  checkTemplateDeclaration(ctx, node);
4309
4791
  const variants = createRekeyableMap();
4310
4792
  const unionType = createType({
@@ -5134,25 +5616,70 @@ function applyDecoratorToType(program, decApp, target) {
5134
5616
  }
5135
5617
  }
5136
5618
  }
5137
- function createDecoratorContext(program, decApp) {
5138
- function createPassThruContext(program, decApp) {
5139
- return {
5140
- program,
5141
- decoratorTarget: decApp.node,
5142
- getArgumentTarget: () => decApp.node,
5143
- call: (decorator, target, ...args) => {
5144
- return decorator(createPassThruContext(program, decApp), target, ...args);
5145
- },
5146
- };
5147
- }
5619
+ function createPassThruContexts(program, target) {
5620
+ const decCtx = {
5621
+ program,
5622
+ decoratorTarget: target,
5623
+ getArgumentTarget: () => target,
5624
+ call: (decorator, target, ...args) => {
5625
+ return decCtx.callDecorator(decorator, target, ...args);
5626
+ },
5627
+ callDecorator(decorator, target, ...args) {
5628
+ return decorator(decCtx, target, ...args);
5629
+ },
5630
+ callFunction(fn, ...args) {
5631
+ return fn(fnCtx, ...args);
5632
+ },
5633
+ };
5634
+ const fnCtx = {
5635
+ program,
5636
+ functionCallTarget: target,
5637
+ getArgumentTarget: () => target,
5638
+ callFunction(fn, ...args) {
5639
+ return fn(fnCtx, ...args);
5640
+ },
5641
+ callDecorator(decorator, target, ...args) {
5642
+ return decorator(decCtx, target, ...args);
5643
+ },
5644
+ };
5148
5645
  return {
5646
+ decorator: decCtx,
5647
+ function: fnCtx,
5648
+ };
5649
+ }
5650
+ function createDecoratorContext(program, decApp) {
5651
+ const passthrough = createPassThruContexts(program, decApp.node);
5652
+ const decCtx = {
5149
5653
  program,
5150
5654
  decoratorTarget: decApp.node,
5151
5655
  getArgumentTarget: (index) => {
5152
5656
  return decApp.args[index]?.node;
5153
5657
  },
5154
5658
  call: (decorator, target, ...args) => {
5155
- return decorator(createPassThruContext(program, decApp), target, ...args);
5659
+ return decCtx.callDecorator(decorator, target, ...args);
5660
+ },
5661
+ callDecorator: (decorator, target, ...args) => {
5662
+ return decorator(passthrough.decorator, target, ...args);
5663
+ },
5664
+ callFunction(fn, ...args) {
5665
+ return fn(passthrough.function, ...args);
5666
+ },
5667
+ };
5668
+ return decCtx;
5669
+ }
5670
+ function createFunctionContext(program, fnCall) {
5671
+ const passthrough = createPassThruContexts(program, fnCall);
5672
+ return {
5673
+ program,
5674
+ functionCallTarget: fnCall,
5675
+ getArgumentTarget: (index) => {
5676
+ return fnCall.arguments[index];
5677
+ },
5678
+ callDecorator(decorator, target, ...args) {
5679
+ return decorator(passthrough.decorator, target, ...args);
5680
+ },
5681
+ callFunction(fn, ...args) {
5682
+ return fn(passthrough.function, ...args);
5156
5683
  },
5157
5684
  };
5158
5685
  }