@angular/core 20.1.2 → 20.2.0-next.1

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 (69) hide show
  1. package/api.d.d.ts +1 -1
  2. package/chrome_dev_tools_performance.d.d.ts +1 -1
  3. package/discovery.d.d.ts +1 -1
  4. package/event_dispatcher.d.d.ts +1 -1
  5. package/fesm2022/attribute.mjs +1 -1
  6. package/fesm2022/attribute.mjs.map +1 -1
  7. package/fesm2022/core.mjs +2 -2
  8. package/fesm2022/core.mjs.map +1 -1
  9. package/fesm2022/debug_node.mjs +2 -2
  10. package/fesm2022/debug_node.mjs.map +1 -1
  11. package/fesm2022/not_found.mjs +1 -1
  12. package/fesm2022/not_found.mjs.map +1 -1
  13. package/fesm2022/primitives/di.mjs +1 -1
  14. package/fesm2022/primitives/di.mjs.map +1 -1
  15. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  16. package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
  17. package/fesm2022/primitives/signals.mjs +1 -1
  18. package/fesm2022/primitives/signals.mjs.map +1 -1
  19. package/fesm2022/resource.mjs +1 -1
  20. package/fesm2022/resource.mjs.map +1 -1
  21. package/fesm2022/root_effect_scheduler.mjs +1 -1
  22. package/fesm2022/root_effect_scheduler.mjs.map +1 -1
  23. package/fesm2022/rxjs-interop.mjs +1 -1
  24. package/fesm2022/rxjs-interop.mjs.map +1 -1
  25. package/fesm2022/signal.mjs +1 -1
  26. package/fesm2022/signal.mjs.map +1 -1
  27. package/fesm2022/testing.mjs +1 -1
  28. package/fesm2022/testing.mjs.map +1 -1
  29. package/fesm2022/untracked.mjs +1 -1
  30. package/fesm2022/untracked.mjs.map +1 -1
  31. package/fesm2022/weak_ref.mjs +1 -1
  32. package/fesm2022/weak_ref.mjs.map +1 -1
  33. package/graph.d.d.ts +1 -1
  34. package/index.d.ts +1 -1
  35. package/package.json +2 -2
  36. package/primitives/di/index.d.ts +1 -1
  37. package/primitives/event-dispatch/index.d.ts +1 -1
  38. package/primitives/signals/index.d.ts +1 -1
  39. package/rxjs-interop/index.d.ts +1 -1
  40. package/schematics/bundles/{apply_import_manager-4lhgojXS.cjs → apply_import_manager-ceekZYTK.cjs} +3 -3
  41. package/schematics/bundles/{checker-B0RMVBjs.cjs → checker-BVY3FNBy.cjs} +517 -327
  42. package/schematics/bundles/cleanup-unused-imports.cjs +5 -5
  43. package/schematics/bundles/{compiler_host-D9M-RwqC.cjs → compiler_host-DRAgYPzr.cjs} +2 -2
  44. package/schematics/bundles/control-flow-migration.cjs +3 -3
  45. package/schematics/bundles/document-core.cjs +5 -5
  46. package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
  47. package/schematics/bundles/{index-BIFHM-Gi.cjs → index-B7rvD9dh.cjs} +13 -13
  48. package/schematics/bundles/{index-B1wVLvRR.cjs → index-DkKydW5H.cjs} +4 -4
  49. package/schematics/bundles/inject-flags.cjs +5 -5
  50. package/schematics/bundles/inject-migration.cjs +3 -3
  51. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  52. package/schematics/bundles/{migrate_ts_type_references-DEjd_J_s.cjs → migrate_ts_type_references-BRFh6uWT.cjs} +5 -5
  53. package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
  54. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  55. package/schematics/bundles/output-migration.cjs +6 -6
  56. package/schematics/bundles/{project_paths-B-mniue6.cjs → project_paths-zgvnBQD8.cjs} +3 -3
  57. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +1 -1
  58. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  59. package/schematics/bundles/route-lazy-loading.cjs +3 -3
  60. package/schematics/bundles/self-closing-tags-migration.cjs +4 -4
  61. package/schematics/bundles/signal-input-migration.cjs +7 -7
  62. package/schematics/bundles/signal-queries-migration.cjs +7 -7
  63. package/schematics/bundles/signals.cjs +7 -7
  64. package/schematics/bundles/standalone-migration.cjs +4 -4
  65. package/schematics/bundles/symbol-VPWguRxr.cjs +1 -1
  66. package/schematics/bundles/test-bed-get.cjs +4 -4
  67. package/signal.d.d.ts +1 -1
  68. package/testing/index.d.ts +1 -1
  69. package/weak_ref.d.d.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v20.1.2
3
+ * @license Angular v20.2.0-next.1
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -31494,7 +31494,7 @@ function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMap
31494
31494
  declarations.push(...decl.directives.map((dir) => convertDirectiveDeclarationToMetadata(dir)));
31495
31495
  decl.pipes && declarations.push(...convertPipeMapToMetadata(decl.pipes));
31496
31496
  }
31497
- const hasDirectiveDependencies = declarations.some(({ kind }) => kind === exports.R3TemplateDependencyKind.Directive || kind === exports.R3TemplateDependencyKind.NgModule);
31497
+ const hasDirectiveDependencies = declarations.every(({ kind }) => kind === exports.R3TemplateDependencyKind.Directive || kind === exports.R3TemplateDependencyKind.NgModule);
31498
31498
  return {
31499
31499
  ...convertDeclareDirectiveFacadeToMetadata(decl, typeSourceSpan),
31500
31500
  template,
@@ -32271,7 +32271,7 @@ function isAttrNode(ast) {
32271
32271
  * @description
32272
32272
  * Entry point for all public APIs of the compiler package.
32273
32273
  */
32274
- new Version('20.1.2');
32274
+ new Version('20.2.0-next.1');
32275
32275
 
32276
32276
  //////////////////////////////////////
32277
32277
  // THIS FILE HAS GLOBAL SIDE EFFECT //
@@ -33291,7 +33291,7 @@ class NodeJSPathManipulation {
33291
33291
  // G3-ESM-MARKER: G3 uses CommonJS, but externally everything in ESM.
33292
33292
  // CommonJS/ESM interop for determining the current file name and containing dir.
33293
33293
  const isCommonJS = typeof __filename !== 'undefined';
33294
- const currentFileUrl = isCommonJS ? null : (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('checker-B0RMVBjs.cjs', document.baseURI).href));
33294
+ const currentFileUrl = isCommonJS ? null : (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('checker-BVY3FNBy.cjs', document.baseURI).href));
33295
33295
  // Note, when this code loads in the browser, `url` may be an empty `{}` due to the Closure shims.
33296
33296
  const currentFileName = isCommonJS
33297
33297
  ? __filename
@@ -36711,75 +36711,83 @@ exports.PerfPhase = void 0;
36711
36711
  * Time spent computing template type-checking diagnostics.
36712
36712
  */
36713
36713
  PerfPhase[PerfPhase["TtcDiagnostics"] = 14] = "TtcDiagnostics";
36714
+ /**
36715
+ * Time spent computing template type-checking suggestion diagnostics.
36716
+ */
36717
+ PerfPhase[PerfPhase["TtcSuggestionDiagnostics"] = 15] = "TtcSuggestionDiagnostics";
36714
36718
  /**
36715
36719
  * Time spent getting a `Symbol` from the `TemplateTypeChecker`.
36716
36720
  */
36717
- PerfPhase[PerfPhase["TtcSymbol"] = 15] = "TtcSymbol";
36721
+ PerfPhase[PerfPhase["TtcSymbol"] = 16] = "TtcSymbol";
36718
36722
  /**
36719
36723
  * Time spent by the Angular Language Service calculating a "get references" or a renaming
36720
36724
  * operation.
36721
36725
  */
36722
- PerfPhase[PerfPhase["LsReferencesAndRenames"] = 16] = "LsReferencesAndRenames";
36726
+ PerfPhase[PerfPhase["LsReferencesAndRenames"] = 17] = "LsReferencesAndRenames";
36723
36727
  /**
36724
36728
  * Time spent by the Angular Language Service calculating a "quick info" operation.
36725
36729
  */
36726
- PerfPhase[PerfPhase["LsQuickInfo"] = 17] = "LsQuickInfo";
36730
+ PerfPhase[PerfPhase["LsQuickInfo"] = 18] = "LsQuickInfo";
36727
36731
  /**
36728
36732
  * Time spent by the Angular Language Service calculating a "get type definition" or "get
36729
36733
  * definition" operation.
36730
36734
  */
36731
- PerfPhase[PerfPhase["LsDefinition"] = 18] = "LsDefinition";
36735
+ PerfPhase[PerfPhase["LsDefinition"] = 19] = "LsDefinition";
36732
36736
  /**
36733
36737
  * Time spent by the Angular Language Service calculating a "get completions" (AKA autocomplete)
36734
36738
  * operation.
36735
36739
  */
36736
- PerfPhase[PerfPhase["LsCompletions"] = 19] = "LsCompletions";
36740
+ PerfPhase[PerfPhase["LsCompletions"] = 20] = "LsCompletions";
36737
36741
  /**
36738
36742
  * Time spent by the Angular Language Service calculating a "view template typecheck block"
36739
36743
  * operation.
36740
36744
  */
36741
- PerfPhase[PerfPhase["LsTcb"] = 20] = "LsTcb";
36745
+ PerfPhase[PerfPhase["LsTcb"] = 21] = "LsTcb";
36742
36746
  /**
36743
36747
  * Time spent by the Angular Language Service calculating diagnostics.
36744
36748
  */
36745
- PerfPhase[PerfPhase["LsDiagnostics"] = 21] = "LsDiagnostics";
36749
+ PerfPhase[PerfPhase["LsDiagnostics"] = 22] = "LsDiagnostics";
36750
+ /**
36751
+ * Time spent by the Angular Language Service calculating suggestion diagnostics.
36752
+ */
36753
+ PerfPhase[PerfPhase["LsSuggestionDiagnostics"] = 23] = "LsSuggestionDiagnostics";
36746
36754
  /**
36747
36755
  * Time spent by the Angular Language Service calculating a "get component locations for template"
36748
36756
  * operation.
36749
36757
  */
36750
- PerfPhase[PerfPhase["LsComponentLocations"] = 22] = "LsComponentLocations";
36758
+ PerfPhase[PerfPhase["LsComponentLocations"] = 24] = "LsComponentLocations";
36751
36759
  /**
36752
36760
  * Time spent by the Angular Language Service calculating signature help.
36753
36761
  */
36754
- PerfPhase[PerfPhase["LsSignatureHelp"] = 23] = "LsSignatureHelp";
36762
+ PerfPhase[PerfPhase["LsSignatureHelp"] = 25] = "LsSignatureHelp";
36755
36763
  /**
36756
36764
  * Time spent by the Angular Language Service calculating outlining spans.
36757
36765
  */
36758
- PerfPhase[PerfPhase["OutliningSpans"] = 24] = "OutliningSpans";
36766
+ PerfPhase[PerfPhase["OutliningSpans"] = 26] = "OutliningSpans";
36759
36767
  /**
36760
36768
  * Time spent by the Angular Language Service calculating code fixes.
36761
36769
  */
36762
- PerfPhase[PerfPhase["LsCodeFixes"] = 25] = "LsCodeFixes";
36770
+ PerfPhase[PerfPhase["LsCodeFixes"] = 27] = "LsCodeFixes";
36763
36771
  /**
36764
36772
  * Time spent by the Angular Language Service to fix all detected same type errors.
36765
36773
  */
36766
- PerfPhase[PerfPhase["LsCodeFixesAll"] = 26] = "LsCodeFixesAll";
36774
+ PerfPhase[PerfPhase["LsCodeFixesAll"] = 28] = "LsCodeFixesAll";
36767
36775
  /**
36768
36776
  * Time spent computing possible Angular refactorings.
36769
36777
  */
36770
- PerfPhase[PerfPhase["LSComputeApplicableRefactorings"] = 27] = "LSComputeApplicableRefactorings";
36778
+ PerfPhase[PerfPhase["LSComputeApplicableRefactorings"] = 29] = "LSComputeApplicableRefactorings";
36771
36779
  /**
36772
36780
  * Time spent computing changes for applying a given refactoring.
36773
36781
  */
36774
- PerfPhase[PerfPhase["LSApplyRefactoring"] = 28] = "LSApplyRefactoring";
36782
+ PerfPhase[PerfPhase["LSApplyRefactoring"] = 30] = "LSApplyRefactoring";
36775
36783
  /**
36776
36784
  * Time spent by the Angular Language Service calculating semantic classifications.
36777
36785
  */
36778
- PerfPhase[PerfPhase["LSSemanticClassification"] = 29] = "LSSemanticClassification";
36786
+ PerfPhase[PerfPhase["LSSemanticClassification"] = 31] = "LSSemanticClassification";
36779
36787
  /**
36780
36788
  * Tracks the number of `PerfPhase`s, and must appear at the end of the list.
36781
36789
  */
36782
- PerfPhase[PerfPhase["LAST"] = 30] = "LAST";
36790
+ PerfPhase[PerfPhase["LAST"] = 32] = "LAST";
36783
36791
  })(exports.PerfPhase || (exports.PerfPhase = {}));
36784
36792
  /**
36785
36793
  * Represents some occurrence during compilation, and is tracked with a counter.
@@ -40318,6 +40326,314 @@ function extractHostBindingResources(nodes) {
40318
40326
  return result;
40319
40327
  }
40320
40328
 
40329
+ const parseSpanComment = /^(\d+),(\d+)$/;
40330
+ /**
40331
+ * Reads the trailing comments and finds the first match which is a span comment (i.e. 4,10) on a
40332
+ * node and returns it as an `AbsoluteSourceSpan`.
40333
+ *
40334
+ * Will return `null` if no trailing comments on the node match the expected form of a source span.
40335
+ */
40336
+ function readSpanComment(node, sourceFile = node.getSourceFile()) {
40337
+ return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
40338
+ if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
40339
+ return null;
40340
+ }
40341
+ const commentText = sourceFile.text.substring(pos + 2, end - 2);
40342
+ const match = commentText.match(parseSpanComment);
40343
+ if (match === null) {
40344
+ return null;
40345
+ }
40346
+ return new AbsoluteSourceSpan(+match[1], +match[2]);
40347
+ }) || null);
40348
+ }
40349
+ /** Used to identify what type the comment is. */
40350
+ var CommentTriviaType;
40351
+ (function (CommentTriviaType) {
40352
+ CommentTriviaType["DIAGNOSTIC"] = "D";
40353
+ CommentTriviaType["EXPRESSION_TYPE_IDENTIFIER"] = "T";
40354
+ })(CommentTriviaType || (CommentTriviaType = {}));
40355
+ /** Identifies what the TCB expression is for (for example, a directive declaration). */
40356
+ var ExpressionIdentifier;
40357
+ (function (ExpressionIdentifier) {
40358
+ ExpressionIdentifier["DIRECTIVE"] = "DIR";
40359
+ ExpressionIdentifier["COMPONENT_COMPLETION"] = "COMPCOMP";
40360
+ ExpressionIdentifier["EVENT_PARAMETER"] = "EP";
40361
+ ExpressionIdentifier["VARIABLE_AS_EXPRESSION"] = "VAE";
40362
+ })(ExpressionIdentifier || (ExpressionIdentifier = {}));
40363
+ /** Tags the node with the given expression identifier. */
40364
+ function addExpressionIdentifier(node, identifier) {
40365
+ ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `${CommentTriviaType.EXPRESSION_TYPE_IDENTIFIER}:${identifier}`,
40366
+ /* hasTrailingNewLine */ false);
40367
+ }
40368
+ const IGNORE_FOR_DIAGNOSTICS_MARKER = `${CommentTriviaType.DIAGNOSTIC}:ignore`;
40369
+ /**
40370
+ * Tag the `ts.Node` with an indication that any errors arising from the evaluation of the node
40371
+ * should be ignored.
40372
+ */
40373
+ function markIgnoreDiagnostics(node) {
40374
+ ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, IGNORE_FOR_DIAGNOSTICS_MARKER,
40375
+ /* hasTrailingNewLine */ false);
40376
+ }
40377
+ /** Returns true if the node has a marker that indicates diagnostics errors should be ignored. */
40378
+ function hasIgnoreForDiagnosticsMarker(node, sourceFile) {
40379
+ return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
40380
+ if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
40381
+ return null;
40382
+ }
40383
+ const commentText = sourceFile.text.substring(pos + 2, end - 2);
40384
+ return commentText === IGNORE_FOR_DIAGNOSTICS_MARKER;
40385
+ }) === true);
40386
+ }
40387
+ function makeRecursiveVisitor(visitor) {
40388
+ function recursiveVisitor(node) {
40389
+ const res = visitor(node);
40390
+ return res !== null ? res : node.forEachChild(recursiveVisitor);
40391
+ }
40392
+ return recursiveVisitor;
40393
+ }
40394
+ function getSpanFromOptions(opts) {
40395
+ let withSpan = null;
40396
+ if (opts.withSpan !== undefined) {
40397
+ if (opts.withSpan instanceof AbsoluteSourceSpan) {
40398
+ withSpan = opts.withSpan;
40399
+ }
40400
+ else {
40401
+ withSpan = { start: opts.withSpan.start.offset, end: opts.withSpan.end.offset };
40402
+ }
40403
+ }
40404
+ return withSpan;
40405
+ }
40406
+ /**
40407
+ * Given a `ts.Node` with finds the first node whose matching the criteria specified
40408
+ * by the `FindOptions`.
40409
+ *
40410
+ * Returns `null` when no `ts.Node` matches the given conditions.
40411
+ */
40412
+ function findFirstMatchingNode(tcb, opts) {
40413
+ const withSpan = getSpanFromOptions(opts);
40414
+ const withExpressionIdentifier = opts.withExpressionIdentifier;
40415
+ const sf = tcb.getSourceFile();
40416
+ const visitor = makeRecursiveVisitor((node) => {
40417
+ if (!opts.filter(node)) {
40418
+ return null;
40419
+ }
40420
+ if (withSpan !== null) {
40421
+ const comment = readSpanComment(node, sf);
40422
+ if (comment === null || withSpan.start !== comment.start || withSpan.end !== comment.end) {
40423
+ return null;
40424
+ }
40425
+ }
40426
+ if (withExpressionIdentifier !== undefined &&
40427
+ !hasExpressionIdentifier(sf, node, withExpressionIdentifier)) {
40428
+ return null;
40429
+ }
40430
+ return node;
40431
+ });
40432
+ return tcb.forEachChild(visitor) ?? null;
40433
+ }
40434
+ /**
40435
+ * Given a `ts.Node` with source span comments, finds the first node whose source span comment
40436
+ * matches the given `sourceSpan`. Additionally, the `filter` function allows matching only
40437
+ * `ts.Nodes` of a given type, which provides the ability to select only matches of a given type
40438
+ * when there may be more than one.
40439
+ *
40440
+ * Returns `null` when no `ts.Node` matches the given conditions.
40441
+ */
40442
+ function findAllMatchingNodes(tcb, opts) {
40443
+ const withSpan = getSpanFromOptions(opts);
40444
+ const withExpressionIdentifier = opts.withExpressionIdentifier;
40445
+ const results = [];
40446
+ const stack = [tcb];
40447
+ const sf = tcb.getSourceFile();
40448
+ while (stack.length > 0) {
40449
+ const node = stack.pop();
40450
+ if (!opts.filter(node)) {
40451
+ stack.push(...node.getChildren());
40452
+ continue;
40453
+ }
40454
+ if (withSpan !== null) {
40455
+ const comment = readSpanComment(node, sf);
40456
+ if (comment === null || withSpan.start !== comment.start || withSpan.end !== comment.end) {
40457
+ stack.push(...node.getChildren());
40458
+ continue;
40459
+ }
40460
+ }
40461
+ if (withExpressionIdentifier !== undefined &&
40462
+ !hasExpressionIdentifier(sf, node, withExpressionIdentifier)) {
40463
+ continue;
40464
+ }
40465
+ results.push(node);
40466
+ }
40467
+ return results;
40468
+ }
40469
+ function hasExpressionIdentifier(sourceFile, node, identifier) {
40470
+ return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
40471
+ if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
40472
+ return false;
40473
+ }
40474
+ const commentText = sourceFile.text.substring(pos + 2, end - 2);
40475
+ return commentText === `${CommentTriviaType.EXPRESSION_TYPE_IDENTIFIER}:${identifier}`;
40476
+ }) || false);
40477
+ }
40478
+
40479
+ /**
40480
+ * A `Set` of `ts.SyntaxKind`s of `ts.Expression` which are safe to wrap in a `ts.AsExpression`
40481
+ * without needing to be wrapped in parentheses.
40482
+ *
40483
+ * For example, `foo.bar()` is a `ts.CallExpression`, and can be safely cast to `any` with
40484
+ * `foo.bar() as any`. however, `foo !== bar` is a `ts.BinaryExpression`, and attempting to cast
40485
+ * without the parentheses yields the expression `foo !== bar as any`. This is semantically
40486
+ * equivalent to `foo !== (bar as any)`, which is not what was intended. Thus,
40487
+ * `ts.BinaryExpression`s need to be wrapped in parentheses before casting.
40488
+ */
40489
+ //
40490
+ let SAFE_TO_CAST_WITHOUT_PARENS = null;
40491
+ function tsCastToAny(expr) {
40492
+ if (SAFE_TO_CAST_WITHOUT_PARENS === null) {
40493
+ SAFE_TO_CAST_WITHOUT_PARENS = new Set([
40494
+ // Expressions which are already parenthesized can be cast without further wrapping.
40495
+ ts.SyntaxKind.ParenthesizedExpression,
40496
+ // Expressions which form a single lexical unit leave no room for precedence issues with the cast.
40497
+ ts.SyntaxKind.Identifier,
40498
+ ts.SyntaxKind.CallExpression,
40499
+ ts.SyntaxKind.NonNullExpression,
40500
+ ts.SyntaxKind.ElementAccessExpression,
40501
+ ts.SyntaxKind.PropertyAccessExpression,
40502
+ ts.SyntaxKind.ArrayLiteralExpression,
40503
+ ts.SyntaxKind.ObjectLiteralExpression,
40504
+ // The same goes for various literals.
40505
+ ts.SyntaxKind.StringLiteral,
40506
+ ts.SyntaxKind.NumericLiteral,
40507
+ ts.SyntaxKind.TrueKeyword,
40508
+ ts.SyntaxKind.FalseKeyword,
40509
+ ts.SyntaxKind.NullKeyword,
40510
+ ts.SyntaxKind.UndefinedKeyword,
40511
+ ]);
40512
+ }
40513
+ // Wrap `expr` in parentheses if needed (see `SAFE_TO_CAST_WITHOUT_PARENS` above).
40514
+ if (!SAFE_TO_CAST_WITHOUT_PARENS.has(expr.kind)) {
40515
+ expr = ts.factory.createParenthesizedExpression(expr);
40516
+ }
40517
+ // The outer expression is always wrapped in parentheses.
40518
+ return ts.factory.createParenthesizedExpression(ts.factory.createAsExpression(expr, ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)));
40519
+ }
40520
+ /**
40521
+ * Create an expression which instantiates an element by its HTML tagName.
40522
+ *
40523
+ * Thanks to narrowing of `document.createElement()`, this expression will have its type inferred
40524
+ * based on the tag name, including for custom elements that have appropriate .d.ts definitions.
40525
+ */
40526
+ function tsCreateElement(...tagNames) {
40527
+ const createElement = ts.factory.createPropertyAccessExpression(
40528
+ /* expression */ ts.factory.createIdentifier('document'), 'createElement');
40529
+ let arg;
40530
+ if (tagNames.length === 1) {
40531
+ // If there's only one tag name, we can pass it in directly.
40532
+ arg = ts.factory.createStringLiteral(tagNames[0]);
40533
+ }
40534
+ else {
40535
+ // If there's more than one name, we have to generate a union of all the tag names. To do so,
40536
+ // create an expression in the form of `null! as 'tag-1' | 'tag-2' | 'tag-3'`. This allows
40537
+ // TypeScript to infer the type as a union of the differnet tags.
40538
+ const assertedNullExpression = ts.factory.createNonNullExpression(ts.factory.createNull());
40539
+ const type = ts.factory.createUnionTypeNode(tagNames.map((tag) => ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(tag))));
40540
+ arg = ts.factory.createAsExpression(assertedNullExpression, type);
40541
+ }
40542
+ return ts.factory.createCallExpression(
40543
+ /* expression */ createElement,
40544
+ /* typeArguments */ undefined,
40545
+ /* argumentsArray */ [arg]);
40546
+ }
40547
+ /**
40548
+ * Create a `ts.VariableStatement` which declares a variable without explicit initialization.
40549
+ *
40550
+ * The initializer `null!` is used to bypass strict variable initialization checks.
40551
+ *
40552
+ * Unlike with `tsCreateVariable`, the type of the variable is explicitly specified.
40553
+ */
40554
+ function tsDeclareVariable(id, type) {
40555
+ // When we create a variable like `var _t1: boolean = null!`, TypeScript actually infers `_t1`
40556
+ // to be `never`, instead of a `boolean`. To work around it, we cast the value
40557
+ // in the initializer, e.g. `var _t1 = null! as boolean;`.
40558
+ addExpressionIdentifier(type, ExpressionIdentifier.VARIABLE_AS_EXPRESSION);
40559
+ const initializer = ts.factory.createAsExpression(ts.factory.createNonNullExpression(ts.factory.createNull()), type);
40560
+ const decl = ts.factory.createVariableDeclaration(
40561
+ /* name */ id,
40562
+ /* exclamationToken */ undefined,
40563
+ /* type */ undefined,
40564
+ /* initializer */ initializer);
40565
+ return ts.factory.createVariableStatement(
40566
+ /* modifiers */ undefined,
40567
+ /* declarationList */ [decl]);
40568
+ }
40569
+ /**
40570
+ * Creates a `ts.TypeQueryNode` for a coerced input.
40571
+ *
40572
+ * For example: `typeof MatInput.ngAcceptInputType_value`, where MatInput is `typeName` and `value`
40573
+ * is the `coercedInputName`.
40574
+ *
40575
+ * @param typeName The `EntityName` of the Directive where the static coerced input is defined.
40576
+ * @param coercedInputName The field name of the coerced input.
40577
+ */
40578
+ function tsCreateTypeQueryForCoercedInput(typeName, coercedInputName) {
40579
+ return ts.factory.createTypeQueryNode(ts.factory.createQualifiedName(typeName, `ngAcceptInputType_${coercedInputName}`));
40580
+ }
40581
+ /**
40582
+ * Create a `ts.VariableStatement` that initializes a variable with a given expression.
40583
+ *
40584
+ * Unlike with `tsDeclareVariable`, the type of the variable is inferred from the initializer
40585
+ * expression.
40586
+ */
40587
+ function tsCreateVariable(id, initializer, flags = null) {
40588
+ const decl = ts.factory.createVariableDeclaration(
40589
+ /* name */ id,
40590
+ /* exclamationToken */ undefined,
40591
+ /* type */ undefined,
40592
+ /* initializer */ initializer);
40593
+ return ts.factory.createVariableStatement(
40594
+ /* modifiers */ undefined,
40595
+ /* declarationList */ flags === null
40596
+ ? [decl]
40597
+ : ts.factory.createVariableDeclarationList([decl], flags));
40598
+ }
40599
+ /**
40600
+ * Construct a `ts.CallExpression` that calls a method on a receiver.
40601
+ */
40602
+ function tsCallMethod(receiver, methodName, args = []) {
40603
+ const methodAccess = ts.factory.createPropertyAccessExpression(receiver, methodName);
40604
+ return ts.factory.createCallExpression(
40605
+ /* expression */ methodAccess,
40606
+ /* typeArguments */ undefined,
40607
+ /* argumentsArray */ args);
40608
+ }
40609
+ function isAccessExpression(node) {
40610
+ return ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node);
40611
+ }
40612
+ /**
40613
+ * Creates a TypeScript node representing a numeric value.
40614
+ */
40615
+ function tsNumericExpression(value) {
40616
+ // As of TypeScript 5.3 negative numbers are represented as `prefixUnaryOperator` and passing a
40617
+ // negative number (even as a string) into `createNumericLiteral` will result in an error.
40618
+ if (value < 0) {
40619
+ const operand = ts.factory.createNumericLiteral(Math.abs(value));
40620
+ return ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, operand);
40621
+ }
40622
+ return ts.factory.createNumericLiteral(value);
40623
+ }
40624
+ /**
40625
+ * Check if a node represents a directive declaration in a TypeCheck Block.
40626
+ * Directive declarations can be either:
40627
+ * - var _t1: TestDir /*T:D*\/ = null! as TestDir;
40628
+ * - var _t1 /*T:D*\/ = _ctor1({});
40629
+ */
40630
+ function isDirectiveDeclaration(node) {
40631
+ const sourceFile = node.getSourceFile();
40632
+ return ((ts.isTypeNode(node) || ts.isIdentifier(node)) &&
40633
+ ts.isVariableDeclaration(node.parent) &&
40634
+ hasExpressionIdentifier(sourceFile, node, ExpressionIdentifier.DIRECTIVE));
40635
+ }
40636
+
40321
40637
  const NgOriginalFile = Symbol('NgOriginalFile');
40322
40638
  exports.UpdateMode = void 0;
40323
40639
  (function (UpdateMode) {
@@ -40506,12 +40822,13 @@ exports.SymbolKind = void 0;
40506
40822
 
40507
40823
  /**
40508
40824
  * Constructs a `ts.Diagnostic` for a given `ParseSourceSpan` within a template.
40825
+ *
40826
+ * @param deprecatedDiagInfo Optional information about deprecation and related messages.
40509
40827
  */
40510
- function makeTemplateDiagnostic(id, mapping, span, category, code, messageText, relatedMessages) {
40828
+ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText, relatedMessages, deprecatedDiagInfo) {
40511
40829
  if (mapping.type === 'direct') {
40512
- let relatedInformation = undefined;
40830
+ let relatedInformation = [];
40513
40831
  if (relatedMessages !== undefined) {
40514
- relatedInformation = [];
40515
40832
  for (const relatedMessage of relatedMessages) {
40516
40833
  relatedInformation.push({
40517
40834
  category: ts.DiagnosticCategory.Message,
@@ -40523,6 +40840,9 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
40523
40840
  });
40524
40841
  }
40525
40842
  }
40843
+ if (deprecatedDiagInfo !== undefined) {
40844
+ relatedInformation.push(...(deprecatedDiagInfo.relatedMessages ?? []));
40845
+ }
40526
40846
  // For direct mappings, the error is shown inline as ngtsc was able to pinpoint a string
40527
40847
  // constant within the `@Component` decorator for the template. This allows us to map the error
40528
40848
  // directly into the bytes of the source file.
@@ -40537,6 +40857,7 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
40537
40857
  start: span.start.offset,
40538
40858
  length: span.end.offset - span.start.offset,
40539
40859
  relatedInformation,
40860
+ reportsDeprecated: deprecatedDiagInfo?.reportsDeprecated,
40540
40861
  };
40541
40862
  }
40542
40863
  else if (mapping.type === 'indirect' || mapping.type === 'external') {
@@ -40581,6 +40902,7 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
40581
40902
  start: mapping.node.getStart(),
40582
40903
  length: mapping.node.getEnd() - mapping.node.getStart(),
40583
40904
  relatedInformation,
40905
+ reportsDeprecated: deprecatedDiagInfo?.reportsDeprecated,
40584
40906
  };
40585
40907
  }
40586
40908
  let typeForMessage;
@@ -40596,6 +40918,9 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
40596
40918
  else {
40597
40919
  typeForMessage = 'Error';
40598
40920
  }
40921
+ if (deprecatedDiagInfo !== undefined) {
40922
+ relatedInformation.push(...(deprecatedDiagInfo.relatedMessages ?? []));
40923
+ }
40599
40924
  relatedInformation.push({
40600
40925
  category: ts.DiagnosticCategory.Message,
40601
40926
  code: 0,
@@ -40618,6 +40943,7 @@ function makeTemplateDiagnostic(id, mapping, span, category, code, messageText,
40618
40943
  length: span.end.offset - span.start.offset,
40619
40944
  // Show a secondary message indicating the component whose template contains the error.
40620
40945
  relatedInformation,
40946
+ reportsDeprecated: deprecatedDiagInfo?.reportsDeprecated,
40621
40947
  };
40622
40948
  }
40623
40949
  else {
@@ -40650,156 +40976,6 @@ function getTypeCheckId$1(clazz) {
40650
40976
  return sf[TYPE_CHECK_ID_MAP].get(clazz);
40651
40977
  }
40652
40978
 
40653
- const parseSpanComment = /^(\d+),(\d+)$/;
40654
- /**
40655
- * Reads the trailing comments and finds the first match which is a span comment (i.e. 4,10) on a
40656
- * node and returns it as an `AbsoluteSourceSpan`.
40657
- *
40658
- * Will return `null` if no trailing comments on the node match the expected form of a source span.
40659
- */
40660
- function readSpanComment(node, sourceFile = node.getSourceFile()) {
40661
- return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
40662
- if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
40663
- return null;
40664
- }
40665
- const commentText = sourceFile.text.substring(pos + 2, end - 2);
40666
- const match = commentText.match(parseSpanComment);
40667
- if (match === null) {
40668
- return null;
40669
- }
40670
- return new AbsoluteSourceSpan(+match[1], +match[2]);
40671
- }) || null);
40672
- }
40673
- /** Used to identify what type the comment is. */
40674
- var CommentTriviaType;
40675
- (function (CommentTriviaType) {
40676
- CommentTriviaType["DIAGNOSTIC"] = "D";
40677
- CommentTriviaType["EXPRESSION_TYPE_IDENTIFIER"] = "T";
40678
- })(CommentTriviaType || (CommentTriviaType = {}));
40679
- /** Identifies what the TCB expression is for (for example, a directive declaration). */
40680
- var ExpressionIdentifier;
40681
- (function (ExpressionIdentifier) {
40682
- ExpressionIdentifier["DIRECTIVE"] = "DIR";
40683
- ExpressionIdentifier["COMPONENT_COMPLETION"] = "COMPCOMP";
40684
- ExpressionIdentifier["EVENT_PARAMETER"] = "EP";
40685
- ExpressionIdentifier["VARIABLE_AS_EXPRESSION"] = "VAE";
40686
- })(ExpressionIdentifier || (ExpressionIdentifier = {}));
40687
- /** Tags the node with the given expression identifier. */
40688
- function addExpressionIdentifier(node, identifier) {
40689
- ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `${CommentTriviaType.EXPRESSION_TYPE_IDENTIFIER}:${identifier}`,
40690
- /* hasTrailingNewLine */ false);
40691
- }
40692
- const IGNORE_FOR_DIAGNOSTICS_MARKER = `${CommentTriviaType.DIAGNOSTIC}:ignore`;
40693
- /**
40694
- * Tag the `ts.Node` with an indication that any errors arising from the evaluation of the node
40695
- * should be ignored.
40696
- */
40697
- function markIgnoreDiagnostics(node) {
40698
- ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, IGNORE_FOR_DIAGNOSTICS_MARKER,
40699
- /* hasTrailingNewLine */ false);
40700
- }
40701
- /** Returns true if the node has a marker that indicates diagnostics errors should be ignored. */
40702
- function hasIgnoreForDiagnosticsMarker(node, sourceFile) {
40703
- return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
40704
- if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
40705
- return null;
40706
- }
40707
- const commentText = sourceFile.text.substring(pos + 2, end - 2);
40708
- return commentText === IGNORE_FOR_DIAGNOSTICS_MARKER;
40709
- }) === true);
40710
- }
40711
- function makeRecursiveVisitor(visitor) {
40712
- function recursiveVisitor(node) {
40713
- const res = visitor(node);
40714
- return res !== null ? res : node.forEachChild(recursiveVisitor);
40715
- }
40716
- return recursiveVisitor;
40717
- }
40718
- function getSpanFromOptions(opts) {
40719
- let withSpan = null;
40720
- if (opts.withSpan !== undefined) {
40721
- if (opts.withSpan instanceof AbsoluteSourceSpan) {
40722
- withSpan = opts.withSpan;
40723
- }
40724
- else {
40725
- withSpan = { start: opts.withSpan.start.offset, end: opts.withSpan.end.offset };
40726
- }
40727
- }
40728
- return withSpan;
40729
- }
40730
- /**
40731
- * Given a `ts.Node` with finds the first node whose matching the criteria specified
40732
- * by the `FindOptions`.
40733
- *
40734
- * Returns `null` when no `ts.Node` matches the given conditions.
40735
- */
40736
- function findFirstMatchingNode(tcb, opts) {
40737
- const withSpan = getSpanFromOptions(opts);
40738
- const withExpressionIdentifier = opts.withExpressionIdentifier;
40739
- const sf = tcb.getSourceFile();
40740
- const visitor = makeRecursiveVisitor((node) => {
40741
- if (!opts.filter(node)) {
40742
- return null;
40743
- }
40744
- if (withSpan !== null) {
40745
- const comment = readSpanComment(node, sf);
40746
- if (comment === null || withSpan.start !== comment.start || withSpan.end !== comment.end) {
40747
- return null;
40748
- }
40749
- }
40750
- if (withExpressionIdentifier !== undefined &&
40751
- !hasExpressionIdentifier(sf, node, withExpressionIdentifier)) {
40752
- return null;
40753
- }
40754
- return node;
40755
- });
40756
- return tcb.forEachChild(visitor) ?? null;
40757
- }
40758
- /**
40759
- * Given a `ts.Node` with source span comments, finds the first node whose source span comment
40760
- * matches the given `sourceSpan`. Additionally, the `filter` function allows matching only
40761
- * `ts.Nodes` of a given type, which provides the ability to select only matches of a given type
40762
- * when there may be more than one.
40763
- *
40764
- * Returns `null` when no `ts.Node` matches the given conditions.
40765
- */
40766
- function findAllMatchingNodes(tcb, opts) {
40767
- const withSpan = getSpanFromOptions(opts);
40768
- const withExpressionIdentifier = opts.withExpressionIdentifier;
40769
- const results = [];
40770
- const stack = [tcb];
40771
- const sf = tcb.getSourceFile();
40772
- while (stack.length > 0) {
40773
- const node = stack.pop();
40774
- if (!opts.filter(node)) {
40775
- stack.push(...node.getChildren());
40776
- continue;
40777
- }
40778
- if (withSpan !== null) {
40779
- const comment = readSpanComment(node, sf);
40780
- if (comment === null || withSpan.start !== comment.start || withSpan.end !== comment.end) {
40781
- stack.push(...node.getChildren());
40782
- continue;
40783
- }
40784
- }
40785
- if (withExpressionIdentifier !== undefined &&
40786
- !hasExpressionIdentifier(sf, node, withExpressionIdentifier)) {
40787
- continue;
40788
- }
40789
- results.push(node);
40790
- }
40791
- return results;
40792
- }
40793
- function hasExpressionIdentifier(sourceFile, node, identifier) {
40794
- return (ts.forEachTrailingCommentRange(sourceFile.text, node.getEnd(), (pos, end, kind) => {
40795
- if (kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
40796
- return false;
40797
- }
40798
- const commentText = sourceFile.text.substring(pos + 2, end - 2);
40799
- return commentText === `${CommentTriviaType.EXPRESSION_TYPE_IDENTIFIER}:${identifier}`;
40800
- }) || false);
40801
- }
40802
-
40803
40979
  /**
40804
40980
  * Powers autocompletion for a specific component.
40805
40981
  *
@@ -42516,152 +42692,6 @@ class ReferenceEmitEnvironment {
42516
42692
  }
42517
42693
  }
42518
42694
 
42519
- /**
42520
- * A `Set` of `ts.SyntaxKind`s of `ts.Expression` which are safe to wrap in a `ts.AsExpression`
42521
- * without needing to be wrapped in parentheses.
42522
- *
42523
- * For example, `foo.bar()` is a `ts.CallExpression`, and can be safely cast to `any` with
42524
- * `foo.bar() as any`. however, `foo !== bar` is a `ts.BinaryExpression`, and attempting to cast
42525
- * without the parentheses yields the expression `foo !== bar as any`. This is semantically
42526
- * equivalent to `foo !== (bar as any)`, which is not what was intended. Thus,
42527
- * `ts.BinaryExpression`s need to be wrapped in parentheses before casting.
42528
- */
42529
- //
42530
- let SAFE_TO_CAST_WITHOUT_PARENS = null;
42531
- function tsCastToAny(expr) {
42532
- if (SAFE_TO_CAST_WITHOUT_PARENS === null) {
42533
- SAFE_TO_CAST_WITHOUT_PARENS = new Set([
42534
- // Expressions which are already parenthesized can be cast without further wrapping.
42535
- ts.SyntaxKind.ParenthesizedExpression,
42536
- // Expressions which form a single lexical unit leave no room for precedence issues with the cast.
42537
- ts.SyntaxKind.Identifier,
42538
- ts.SyntaxKind.CallExpression,
42539
- ts.SyntaxKind.NonNullExpression,
42540
- ts.SyntaxKind.ElementAccessExpression,
42541
- ts.SyntaxKind.PropertyAccessExpression,
42542
- ts.SyntaxKind.ArrayLiteralExpression,
42543
- ts.SyntaxKind.ObjectLiteralExpression,
42544
- // The same goes for various literals.
42545
- ts.SyntaxKind.StringLiteral,
42546
- ts.SyntaxKind.NumericLiteral,
42547
- ts.SyntaxKind.TrueKeyword,
42548
- ts.SyntaxKind.FalseKeyword,
42549
- ts.SyntaxKind.NullKeyword,
42550
- ts.SyntaxKind.UndefinedKeyword,
42551
- ]);
42552
- }
42553
- // Wrap `expr` in parentheses if needed (see `SAFE_TO_CAST_WITHOUT_PARENS` above).
42554
- if (!SAFE_TO_CAST_WITHOUT_PARENS.has(expr.kind)) {
42555
- expr = ts.factory.createParenthesizedExpression(expr);
42556
- }
42557
- // The outer expression is always wrapped in parentheses.
42558
- return ts.factory.createParenthesizedExpression(ts.factory.createAsExpression(expr, ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)));
42559
- }
42560
- /**
42561
- * Create an expression which instantiates an element by its HTML tagName.
42562
- *
42563
- * Thanks to narrowing of `document.createElement()`, this expression will have its type inferred
42564
- * based on the tag name, including for custom elements that have appropriate .d.ts definitions.
42565
- */
42566
- function tsCreateElement(...tagNames) {
42567
- const createElement = ts.factory.createPropertyAccessExpression(
42568
- /* expression */ ts.factory.createIdentifier('document'), 'createElement');
42569
- let arg;
42570
- if (tagNames.length === 1) {
42571
- // If there's only one tag name, we can pass it in directly.
42572
- arg = ts.factory.createStringLiteral(tagNames[0]);
42573
- }
42574
- else {
42575
- // If there's more than one name, we have to generate a union of all the tag names. To do so,
42576
- // create an expression in the form of `null! as 'tag-1' | 'tag-2' | 'tag-3'`. This allows
42577
- // TypeScript to infer the type as a union of the differnet tags.
42578
- const assertedNullExpression = ts.factory.createNonNullExpression(ts.factory.createNull());
42579
- const type = ts.factory.createUnionTypeNode(tagNames.map((tag) => ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(tag))));
42580
- arg = ts.factory.createAsExpression(assertedNullExpression, type);
42581
- }
42582
- return ts.factory.createCallExpression(
42583
- /* expression */ createElement,
42584
- /* typeArguments */ undefined,
42585
- /* argumentsArray */ [arg]);
42586
- }
42587
- /**
42588
- * Create a `ts.VariableStatement` which declares a variable without explicit initialization.
42589
- *
42590
- * The initializer `null!` is used to bypass strict variable initialization checks.
42591
- *
42592
- * Unlike with `tsCreateVariable`, the type of the variable is explicitly specified.
42593
- */
42594
- function tsDeclareVariable(id, type) {
42595
- // When we create a variable like `var _t1: boolean = null!`, TypeScript actually infers `_t1`
42596
- // to be `never`, instead of a `boolean`. To work around it, we cast the value
42597
- // in the initializer, e.g. `var _t1 = null! as boolean;`.
42598
- addExpressionIdentifier(type, ExpressionIdentifier.VARIABLE_AS_EXPRESSION);
42599
- const initializer = ts.factory.createAsExpression(ts.factory.createNonNullExpression(ts.factory.createNull()), type);
42600
- const decl = ts.factory.createVariableDeclaration(
42601
- /* name */ id,
42602
- /* exclamationToken */ undefined,
42603
- /* type */ undefined,
42604
- /* initializer */ initializer);
42605
- return ts.factory.createVariableStatement(
42606
- /* modifiers */ undefined,
42607
- /* declarationList */ [decl]);
42608
- }
42609
- /**
42610
- * Creates a `ts.TypeQueryNode` for a coerced input.
42611
- *
42612
- * For example: `typeof MatInput.ngAcceptInputType_value`, where MatInput is `typeName` and `value`
42613
- * is the `coercedInputName`.
42614
- *
42615
- * @param typeName The `EntityName` of the Directive where the static coerced input is defined.
42616
- * @param coercedInputName The field name of the coerced input.
42617
- */
42618
- function tsCreateTypeQueryForCoercedInput(typeName, coercedInputName) {
42619
- return ts.factory.createTypeQueryNode(ts.factory.createQualifiedName(typeName, `ngAcceptInputType_${coercedInputName}`));
42620
- }
42621
- /**
42622
- * Create a `ts.VariableStatement` that initializes a variable with a given expression.
42623
- *
42624
- * Unlike with `tsDeclareVariable`, the type of the variable is inferred from the initializer
42625
- * expression.
42626
- */
42627
- function tsCreateVariable(id, initializer, flags = null) {
42628
- const decl = ts.factory.createVariableDeclaration(
42629
- /* name */ id,
42630
- /* exclamationToken */ undefined,
42631
- /* type */ undefined,
42632
- /* initializer */ initializer);
42633
- return ts.factory.createVariableStatement(
42634
- /* modifiers */ undefined,
42635
- /* declarationList */ flags === null
42636
- ? [decl]
42637
- : ts.factory.createVariableDeclarationList([decl], flags));
42638
- }
42639
- /**
42640
- * Construct a `ts.CallExpression` that calls a method on a receiver.
42641
- */
42642
- function tsCallMethod(receiver, methodName, args = []) {
42643
- const methodAccess = ts.factory.createPropertyAccessExpression(receiver, methodName);
42644
- return ts.factory.createCallExpression(
42645
- /* expression */ methodAccess,
42646
- /* typeArguments */ undefined,
42647
- /* argumentsArray */ args);
42648
- }
42649
- function isAccessExpression(node) {
42650
- return ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node);
42651
- }
42652
- /**
42653
- * Creates a TypeScript node representing a numeric value.
42654
- */
42655
- function tsNumericExpression(value) {
42656
- // As of TypeScript 5.3 negative numbers are represented as `prefixUnaryOperator` and passing a
42657
- // negative number (even as a string) into `createNumericLiteral` will result in an error.
42658
- if (value < 0) {
42659
- const operand = ts.factory.createNumericLiteral(Math.abs(value));
42660
- return ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, operand);
42661
- }
42662
- return ts.factory.createNumericLiteral(value);
42663
- }
42664
-
42665
42695
  /**
42666
42696
  * See `TypeEmitter` for more information on the emitting process.
42667
42697
  */
@@ -44036,7 +44066,12 @@ function translateDiagnostic(diagnostic, resolver) {
44036
44066
  return null;
44037
44067
  }
44038
44068
  const { sourceLocation, sourceMapping: templateSourceMapping, span } = fullMapping;
44039
- return makeTemplateDiagnostic(sourceLocation.id, templateSourceMapping, span, diagnostic.category, diagnostic.code, diagnostic.messageText);
44069
+ return makeTemplateDiagnostic(sourceLocation.id, templateSourceMapping, span, diagnostic.category, diagnostic.code, diagnostic.messageText, undefined, diagnostic.reportsDeprecated !== undefined
44070
+ ? {
44071
+ reportsDeprecated: diagnostic.reportsDeprecated,
44072
+ relatedMessages: diagnostic.relatedInformation,
44073
+ }
44074
+ : undefined);
44040
44075
  }
44041
44076
 
44042
44077
  /**
@@ -48086,13 +48121,6 @@ class SymbolBuilder {
48086
48121
  }
48087
48122
  getDirectivesOfNode(templateNode) {
48088
48123
  const elementSourceSpan = templateNode.startSourceSpan ?? templateNode.sourceSpan;
48089
- const tcbSourceFile = this.typeCheckBlock.getSourceFile();
48090
- // directives could be either:
48091
- // - var _t1: TestDir /*T:D*/ = null! as TestDir;
48092
- // - var _t1 /*T:D*/ = _ctor1({});
48093
- const isDirectiveDeclaration = (node) => (ts.isTypeNode(node) || ts.isIdentifier(node)) &&
48094
- ts.isVariableDeclaration(node.parent) &&
48095
- hasExpressionIdentifier(tcbSourceFile, node, ExpressionIdentifier.DIRECTIVE);
48096
48124
  const nodes = findAllMatchingNodes(this.typeCheckBlock, {
48097
48125
  withSpan: elementSourceSpan,
48098
48126
  filter: isDirectiveDeclaration,
@@ -48956,6 +48984,29 @@ class TemplateTypeCheckerImpl {
48956
48984
  return diagnostics.filter((diag) => diag !== null);
48957
48985
  });
48958
48986
  }
48987
+ getSuggestionDiagnosticsForFile(sf, tsLs, optimizeFor) {
48988
+ switch (optimizeFor) {
48989
+ case exports.OptimizeFor.WholeProgram:
48990
+ this.ensureAllShimsForAllFiles();
48991
+ break;
48992
+ case exports.OptimizeFor.SingleFile:
48993
+ this.ensureAllShimsForOneFile(sf);
48994
+ break;
48995
+ }
48996
+ return this.perf.inPhase(exports.PerfPhase.TtcSuggestionDiagnostics, () => {
48997
+ const sfPath = absoluteFromSourceFile(sf);
48998
+ const fileRecord = this.state.get(sfPath);
48999
+ const diagnostics = [];
49000
+ const program = this.programDriver.getProgram();
49001
+ if (fileRecord.hasInlines) {
49002
+ diagnostics.push(...getDeprecatedSuggestionDiagnostics(tsLs, program, sfPath, fileRecord, this));
49003
+ }
49004
+ for (const [shimPath] of fileRecord.shimData) {
49005
+ diagnostics.push(...getDeprecatedSuggestionDiagnostics(tsLs, program, shimPath, fileRecord, this));
49006
+ }
49007
+ return diagnostics.filter((diag) => diag !== null);
49008
+ });
49009
+ }
48959
49010
  getDiagnosticsForComponent(component) {
48960
49011
  this.ensureShimForComponent(component);
48961
49012
  return this.perf.inPhase(exports.PerfPhase.TtcDiagnostics, () => {
@@ -48987,6 +49038,27 @@ class TemplateTypeCheckerImpl {
48987
49038
  return diagnostics.filter((diag) => diag !== null && diag.typeCheckId === id);
48988
49039
  });
48989
49040
  }
49041
+ getSuggestionDiagnosticsForComponent(component, tsLs) {
49042
+ this.ensureShimForComponent(component);
49043
+ return this.perf.inPhase(exports.PerfPhase.TtcSuggestionDiagnostics, () => {
49044
+ const sf = component.getSourceFile();
49045
+ const sfPath = absoluteFromSourceFile(sf);
49046
+ const shimPath = TypeCheckShimGenerator.shimFor(sfPath);
49047
+ const fileRecord = this.getFileData(sfPath);
49048
+ if (!fileRecord.shimData.has(shimPath)) {
49049
+ return [];
49050
+ }
49051
+ const templateId = fileRecord.sourceManager.getTypeCheckId(component);
49052
+ const shimRecord = fileRecord.shimData.get(shimPath);
49053
+ const diagnostics = [];
49054
+ const program = this.programDriver.getProgram();
49055
+ if (shimRecord.hasInlines) {
49056
+ diagnostics.push(...getDeprecatedSuggestionDiagnostics(tsLs, program, sfPath, fileRecord, this));
49057
+ }
49058
+ diagnostics.push(...getDeprecatedSuggestionDiagnostics(tsLs, program, shimPath, fileRecord, this));
49059
+ return diagnostics.filter((diag) => diag !== null && diag.typeCheckId === templateId);
49060
+ });
49061
+ }
48990
49062
  getTypeCheckBlock(component) {
48991
49063
  return this.getLatestComponentState(component).tcb;
48992
49064
  }
@@ -49810,6 +49882,124 @@ function getClassDeclFromSymbol(symbol, checker) {
49810
49882
  }
49811
49883
  return null;
49812
49884
  }
49885
+ /**
49886
+ * Returns the diagnostics that report deprecated symbols in the given TypeScript language service.
49887
+ *
49888
+ * There are two logins here:
49889
+ *
49890
+ * 1. For input properties, function calls, and so on, the diagnostics reported in the TypeScript
49891
+ * Language Service can be directly transformed into template diagnostics.
49892
+ * 2. For the element tag deprecation, we need to manually connect the TCB node to the template node
49893
+ * and generate the template diagnostics.
49894
+ */
49895
+ function getDeprecatedSuggestionDiagnostics(tsLs, program, path, fileRecord, templateTypeChecker) {
49896
+ const sourceFile = program.getSourceFile(path);
49897
+ if (sourceFile === undefined) {
49898
+ return [];
49899
+ }
49900
+ const tsDiags = tsLs.getSuggestionDiagnostics(path).filter(isDeprecatedDiagnostics);
49901
+ const commonTemplateDiags = tsDiags.map((diag) => {
49902
+ return convertDiagnostic(diag, fileRecord.sourceManager);
49903
+ });
49904
+ const elementTagDiags = getTheElementTagDeprecatedSuggestionDiagnostics(path, program, fileRecord, tsDiags, templateTypeChecker);
49905
+ return [...commonTemplateDiags, ...elementTagDiags];
49906
+ }
49907
+ /**
49908
+ * Connect the TCB node to the template node and generate the template diagnostics.
49909
+ *
49910
+ * How to generate the template diagnostics:
49911
+ *
49912
+ * 1. For each diagnostic, find the TCB node that is reported.
49913
+ * 2. Build a map called `nodeToDiag` that the key is the type node and value is the diagnostic.
49914
+ * For example:
49915
+ * ```
49916
+ * var _t1 = null! as TestDir;
49917
+ * ^^^^^^^------ This is diagnostic node that is reported by the ts.
49918
+ * ```
49919
+ * The key is the class component of TestDir.
49920
+ * 3. Find the all directive nodes in the TCB.
49921
+ * For example:
49922
+ * In the above example, the directive node is `_t1`, get the type of `_t1` which is the
49923
+ * class component of `TestDir`. Check if there is a diagnostic in the `nodeToDiag` map
49924
+ * that matches the class component of `TestDir`.
49925
+ * If there is a match, it means that the diagnostic is reported for the directive node
49926
+ * 4. Generate the template diagnostic and return the template diagnostics.
49927
+ */
49928
+ function getTheElementTagDeprecatedSuggestionDiagnostics(shimPath, program, fileRecord, diags, templateTypeChecker) {
49929
+ const sourceFile = program.getSourceFile(shimPath);
49930
+ if (sourceFile === undefined) {
49931
+ return [];
49932
+ }
49933
+ const typeChecker = program.getTypeChecker();
49934
+ const nodeToDiag = new Map();
49935
+ for (const tsDiag of diags) {
49936
+ const diagNode = getTokenAtPosition(sourceFile, tsDiag.start);
49937
+ const nodeType = typeChecker.getTypeAtLocation(diagNode);
49938
+ const nodeSymbolDeclarations = nodeType.symbol.declarations;
49939
+ const decl = nodeSymbolDeclarations !== undefined && nodeSymbolDeclarations.length > 0
49940
+ ? nodeSymbolDeclarations[0]
49941
+ : undefined;
49942
+ if (decl === undefined || !ts.isClassDeclaration(decl)) {
49943
+ continue;
49944
+ }
49945
+ const directiveForDiagnostic = templateTypeChecker.getDirectiveMetadata(decl);
49946
+ // For now, we only report deprecations for components. This is because
49947
+ // directive spans apply to the entire element, so it would cause the deprecation to
49948
+ // appear as a deprecation for the element rather than whatever the selector (likely an attribute)
49949
+ // is for the directive. Technically components have this issue as well but nearly
49950
+ // all component selectors are element selectors.
49951
+ if (directiveForDiagnostic === null || !directiveForDiagnostic.isComponent) {
49952
+ continue;
49953
+ }
49954
+ nodeToDiag.set(decl, tsDiag);
49955
+ }
49956
+ const directiveNodesInTcb = findAllMatchingNodes(sourceFile, {
49957
+ filter: isDirectiveDeclaration,
49958
+ });
49959
+ const templateDiagnostics = [];
49960
+ for (const directive of directiveNodesInTcb) {
49961
+ const directiveType = typeChecker.getTypeAtLocation(directive);
49962
+ const directiveSymbolDeclarations = directiveType.symbol.declarations;
49963
+ const decl = directiveSymbolDeclarations !== undefined && directiveSymbolDeclarations.length > 0
49964
+ ? directiveSymbolDeclarations[0]
49965
+ : undefined;
49966
+ if (decl === undefined) {
49967
+ continue;
49968
+ }
49969
+ if (!ts.isClassDeclaration(decl)) {
49970
+ continue;
49971
+ }
49972
+ const diagnostic = nodeToDiag.get(decl);
49973
+ if (diagnostic === undefined) {
49974
+ continue;
49975
+ }
49976
+ const fullMapping = getSourceMapping(diagnostic.file, directive.getStart(), fileRecord.sourceManager,
49977
+ /**
49978
+ * Don't set to true, the deprecated diagnostics will be ignored if this is a diagnostics request.
49979
+ * Only the deprecated diagnostics will be reported here.
49980
+ */
49981
+ // For example:
49982
+ // var _t2 /*T:DIR*/ /*87,104*/ = _ctor1({ "name": ("") /*96,103*/ }) /*D:ignore*/;
49983
+ // At the end of the statement, there is a comment `/*D:ignore*/` which means that this diagnostic
49984
+ // should be ignored in diagnostics request.
49985
+ /*isDiagnosticsRequest*/ false);
49986
+ if (fullMapping === null) {
49987
+ continue;
49988
+ }
49989
+ const { sourceLocation, sourceMapping: templateSourceMapping, span } = fullMapping;
49990
+ const templateDiagnostic = makeTemplateDiagnostic(sourceLocation.id, templateSourceMapping, span, diagnostic.category, diagnostic.code, diagnostic.messageText, undefined, diagnostic.reportsDeprecated !== undefined
49991
+ ? {
49992
+ reportsDeprecated: diagnostic.reportsDeprecated,
49993
+ relatedMessages: diagnostic.relatedInformation,
49994
+ }
49995
+ : undefined);
49996
+ templateDiagnostics.push(templateDiagnostic);
49997
+ }
49998
+ return templateDiagnostics;
49999
+ }
50000
+ function isDeprecatedDiagnostics(diag) {
50001
+ return diag.reportsDeprecated !== undefined;
50002
+ }
49813
50003
 
49814
50004
  exports.AST = AST;
49815
50005
  exports.ASTWithSource = ASTWithSource;