@angular/core 19.0.0-next.10 → 19.0.0-next.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/fesm2022/core.mjs +13205 -11798
  2. package/fesm2022/core.mjs.map +1 -1
  3. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  4. package/fesm2022/primitives/signals.mjs +8 -6
  5. package/fesm2022/primitives/signals.mjs.map +1 -1
  6. package/fesm2022/rxjs-interop.mjs +72 -4
  7. package/fesm2022/rxjs-interop.mjs.map +1 -1
  8. package/fesm2022/testing.mjs +4 -4
  9. package/index.d.ts +527 -51
  10. package/package.json +1 -1
  11. package/primitives/event-dispatch/index.d.ts +1 -1
  12. package/primitives/signals/index.d.ts +3 -1
  13. package/rxjs-interop/index.d.ts +32 -1
  14. package/schematics/bundles/{checker-77660732.js → checker-51c08a1b.js} +112 -97
  15. package/schematics/bundles/{compiler_host-81f430d9.js → compiler_host-d7f120f0.js} +2 -2
  16. package/schematics/bundles/control-flow-migration.js +3 -3
  17. package/schematics/bundles/explicit-standalone-flag.js +6 -4
  18. package/schematics/bundles/imports-4ac08251.js +1 -1
  19. package/schematics/bundles/{group_replacements-1f48eff7.js → index-f7b283e6.js} +247 -1649
  20. package/schematics/bundles/inject-migration.js +7 -6
  21. package/schematics/bundles/leading_space-d190b83b.js +1 -1
  22. package/schematics/bundles/migrate_ts_type_references-b2b55f62.js +1448 -0
  23. package/schematics/bundles/{nodes-0e7d45ca.js → ng_decorators-4579dec6.js} +1 -14
  24. package/schematics/bundles/nodes-a535b2be.js +27 -0
  25. package/schematics/bundles/output-migration.js +7295 -0
  26. package/schematics/bundles/pending-tasks.js +3 -3
  27. package/schematics/bundles/{program-1413936a.js → program-6e6520d8.js} +40 -18
  28. package/schematics/bundles/project_tsconfig_paths-e9ccccbf.js +1 -1
  29. package/schematics/bundles/provide-initializer.js +190 -0
  30. package/schematics/bundles/route-lazy-loading.js +3 -3
  31. package/schematics/bundles/signal-input-migration.js +73 -60
  32. package/schematics/bundles/signal-queries-migration.js +119 -90
  33. package/schematics/bundles/signals.js +54 -0
  34. package/schematics/bundles/standalone-migration.js +12 -11
  35. package/schematics/collection.json +11 -0
  36. package/schematics/migrations.json +7 -1
  37. package/schematics/ng-generate/output-migration/schema.json +19 -0
  38. package/schematics/ng-generate/signals/schema.json +65 -0
  39. package/testing/index.d.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-next.10
3
+ * @license Angular v19.0.0-next.11
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -10,19 +10,20 @@ Object.defineProperty(exports, '__esModule', { value: true });
10
10
 
11
11
  var schematics = require('@angular-devkit/schematics');
12
12
  var project_tsconfig_paths = require('./project_tsconfig_paths-e9ccccbf.js');
13
- var group_replacements = require('./group_replacements-1f48eff7.js');
13
+ var index = require('./index-f7b283e6.js');
14
14
  require('os');
15
15
  var ts = require('typescript');
16
- var checker = require('./checker-77660732.js');
17
- var program = require('./program-1413936a.js');
16
+ var checker = require('./checker-51c08a1b.js');
17
+ var program = require('./program-6e6520d8.js');
18
18
  var assert = require('assert');
19
19
  require('path');
20
+ var migrate_ts_type_references = require('./migrate_ts_type_references-b2b55f62.js');
20
21
  require('@angular-devkit/core');
21
- require('./leading_space-d190b83b.js');
22
22
  require('node:path/posix');
23
23
  require('fs');
24
24
  require('module');
25
25
  require('url');
26
+ require('./leading_space-d190b83b.js');
26
27
 
27
28
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
28
29
 
@@ -37,7 +38,7 @@ function migrateHostBindings(host, references, info) {
37
38
  const seenReferences = new WeakMap();
38
39
  for (const reference of references) {
39
40
  // This pass only deals with host binding references.
40
- if (!group_replacements.isHostBindingReference(reference)) {
41
+ if (!index.isHostBindingReference(reference)) {
41
42
  continue;
42
43
  }
43
44
  // Skip references to incompatible inputs.
@@ -61,7 +62,7 @@ function migrateHostBindings(host, references, info) {
61
62
  const appendText = reference.from.isObjectShorthandExpression
62
63
  ? `: ${reference.from.read.name}()`
63
64
  : `()`;
64
- host.replacements.push(new group_replacements.Replacement(group_replacements.projectFile(bindingField.getSourceFile(), info), new group_replacements.TextUpdate({ position: readEndPos, end: readEndPos, toInsert: appendText })));
65
+ host.replacements.push(new index.Replacement(index.projectFile(bindingField.getSourceFile(), info), new index.TextUpdate({ position: readEndPos, end: readEndPos, toInsert: appendText })));
65
66
  }
66
67
  }
67
68
 
@@ -73,7 +74,7 @@ function migrateTemplateReferences(host, references) {
73
74
  const seenFileReferences = new Set();
74
75
  for (const reference of references) {
75
76
  // This pass only deals with HTML template references.
76
- if (!group_replacements.isTemplateReference(reference)) {
77
+ if (!index.isTemplateReference(reference)) {
77
78
  continue;
78
79
  }
79
80
  // Skip references to incompatible inputs.
@@ -90,7 +91,7 @@ function migrateTemplateReferences(host, references) {
90
91
  const appendText = reference.from.isObjectShorthandExpression
91
92
  ? `: ${reference.from.read.name}()`
92
93
  : `()`;
93
- host.replacements.push(new group_replacements.Replacement(reference.from.templateFile, new group_replacements.TextUpdate({
94
+ host.replacements.push(new index.Replacement(reference.from.templateFile, new index.TextUpdate({
94
95
  position: reference.from.read.sourceSpan.end,
95
96
  end: reference.from.read.sourceSpan.end,
96
97
  toInsert: appendText,
@@ -138,7 +139,7 @@ function extractQueryListType(node) {
138
139
  * --> read stays
139
140
  * --> emitDistinctChangesOnly is gone!
140
141
  */
141
- function computeReplacementsToMigrateQuery(node, metadata, importManager, info, printer) {
142
+ function computeReplacementsToMigrateQuery(node, metadata, importManager, info, printer, options, checker$1) {
142
143
  const sf = node.getSourceFile();
143
144
  let newQueryFn = importManager.addImport({
144
145
  requestedFile: sf,
@@ -172,36 +173,56 @@ function computeReplacementsToMigrateQuery(node, metadata, importManager, info,
172
173
  if (optionProperties.length > 0) {
173
174
  args.push(ts__default["default"].factory.createObjectLiteralExpression(optionProperties));
174
175
  }
175
- // TODO: Can we consult, based on references and non-null assertions?
176
- const isIndicatedAsRequired = node.exclamationToken !== undefined;
177
- // If the query is required already via some indicators, and this is a "single"
178
- // query, use the available `.required` method.
179
- if (isIndicatedAsRequired && metadata.queryInfo.first) {
176
+ const strictNullChecksEnabled = options.strict === true || options.strictNullChecks === true;
177
+ const strictPropertyInitialization = options.strict === true || options.strictPropertyInitialization === true;
178
+ let isRequired = node.exclamationToken !== undefined;
179
+ // If we come across an application with strict null checks enabled, but strict
180
+ // property initialization is disabled, there are two options:
181
+ // - Either the query is already typed to include `undefined` explicitly,
182
+ // in which case an option query makes sense.
183
+ // - OR, the query is not typed to include `undefined`. In which case, the query
184
+ // should be marked as required to not break the app. The user-code throughout
185
+ // the application (given strict null checks) already assumes non-nullable!
186
+ if (strictNullChecksEnabled &&
187
+ !strictPropertyInitialization &&
188
+ node.initializer === undefined &&
189
+ node.questionToken === undefined &&
190
+ type !== undefined &&
191
+ !checker$1.isTypeAssignableTo(checker$1.getUndefinedType(), checker$1.getTypeFromTypeNode(type))) {
192
+ isRequired = true;
193
+ }
194
+ if (isRequired && metadata.queryInfo.first) {
195
+ // If the query is required already via some indicators, and this is a "single"
196
+ // query, use the available `.required` method.
180
197
  newQueryFn = ts__default["default"].factory.createPropertyAccessExpression(newQueryFn, 'required');
181
198
  }
182
199
  // If this query is still nullable (i.e. not required), attempt to remove
183
200
  // explicit `undefined` types if possible.
184
- if (!isIndicatedAsRequired && type !== undefined && ts__default["default"].isUnionTypeNode(type)) {
185
- type = group_replacements.removeFromUnionIfPossible(type, (v) => v.kind !== ts__default["default"].SyntaxKind.UndefinedKeyword);
201
+ if (!isRequired && type !== undefined && ts__default["default"].isUnionTypeNode(type)) {
202
+ type = migrate_ts_type_references.removeFromUnionIfPossible(type, (v) => v.kind !== ts__default["default"].SyntaxKind.UndefinedKeyword);
186
203
  }
187
- const locatorType = Array.isArray(metadata.queryInfo.predicate)
204
+ let locatorType = Array.isArray(metadata.queryInfo.predicate)
188
205
  ? null
189
206
  : metadata.queryInfo.predicate.expression;
190
- const readType = metadata.queryInfo.read ?? locatorType;
191
- // If the type and the read type are matching, we can rely on the TS generic
192
- // signature rather than repeating e.g. `viewChild<Button>(Button)`.
207
+ let resolvedReadType = metadata.queryInfo.read ?? locatorType;
208
+ // If the original property type and the read type are matching, we can rely
209
+ // on the TS inference, instead of repeating types, like in `viewChild<Button>(Button)`.
193
210
  if (type !== undefined &&
194
- readType instanceof checker.WrappedNodeExpr &&
195
- ts__default["default"].isIdentifier(readType.node) &&
211
+ resolvedReadType instanceof checker.WrappedNodeExpr &&
212
+ ts__default["default"].isIdentifier(resolvedReadType.node) &&
196
213
  ts__default["default"].isTypeReferenceNode(type) &&
197
214
  ts__default["default"].isIdentifier(type.typeName) &&
198
- type.typeName.text === readType.node.text) {
199
- type = undefined;
200
- }
201
- const call = ts__default["default"].factory.createCallExpression(newQueryFn, type ? [type] : undefined, args);
215
+ type.typeName.text === resolvedReadType.node.text) {
216
+ locatorType = null;
217
+ }
218
+ const call = ts__default["default"].factory.createCallExpression(newQueryFn,
219
+ // If there is no resolved `ReadT` (e.g. string predicate), we use the
220
+ // original type explicitly as generic. Otherwise, query API is smart
221
+ // enough to always infer.
222
+ resolvedReadType === null && type !== undefined ? [type] : undefined, args);
202
223
  const updated = ts__default["default"].factory.createPropertyDeclaration([ts__default["default"].factory.createModifier(ts__default["default"].SyntaxKind.ReadonlyKeyword)], node.name, undefined, undefined, call);
203
224
  return [
204
- new group_replacements.Replacement(group_replacements.projectFile(node.getSourceFile(), info), new group_replacements.TextUpdate({
225
+ new index.Replacement(index.projectFile(node.getSourceFile(), info), new index.TextUpdate({
205
226
  position: node.getStart(),
206
227
  end: node.getEnd(),
207
228
  toInsert: printer.printNode(ts__default["default"].EmitHint.Unspecified, updated, sf),
@@ -242,7 +263,7 @@ function getUniqueIDForClassProperty(property, info) {
242
263
  if (property.name === undefined) {
243
264
  return null;
244
265
  }
245
- const id = group_replacements.projectFile(property.getSourceFile(), info).id.replace(/\.d\.ts$/, '.ts');
266
+ const id = index.projectFile(property.getSourceFile(), info).id.replace(/\.d\.ts$/, '.ts');
246
267
  // Note: If a class is nested, there could be an ID clash.
247
268
  // This is highly unlikely though, and this is not a problem because
248
269
  // in such cases, there is even less chance there are any references to
@@ -305,6 +326,7 @@ function extractSourceQueryDefinition(node, reflector, evaluator, info) {
305
326
  args: decorator.args ?? [],
306
327
  queryInfo,
307
328
  node: node,
329
+ fieldDecorators: decorators,
308
330
  };
309
331
  }
310
332
 
@@ -320,13 +342,13 @@ function markFieldIncompatibleInMetadata(data, id, reason) {
320
342
  existing.fieldReason = reason;
321
343
  }
322
344
  else {
323
- existing.fieldReason = group_replacements.pickFieldIncompatibility({ reason, context: null }, { reason: existing.fieldReason, context: null }).reason;
345
+ existing.fieldReason = migrate_ts_type_references.pickFieldIncompatibility({ reason, context: null }, { reason: existing.fieldReason, context: null }).reason;
324
346
  }
325
347
  }
326
348
  function filterBestEffortIncompatibilities(knownQueries) {
327
349
  for (const query of Object.values(knownQueries.globalMetadata.problematicQueries)) {
328
350
  if (query.fieldReason !== null &&
329
- !group_replacements.nonIgnorableFieldIncompatibilities.includes(query.fieldReason)) {
351
+ !migrate_ts_type_references.nonIgnorableFieldIncompatibilities.includes(query.fieldReason)) {
330
352
  query.fieldReason = null;
331
353
  }
332
354
  }
@@ -362,12 +384,12 @@ class KnownQueries {
362
384
  });
363
385
  this.knownQueryIDs.set(id, { key: id, node: queryField });
364
386
  const descriptor = { key: id, node: queryField };
365
- const file = group_replacements.projectFile(queryField.getSourceFile(), this.info);
387
+ const file = index.projectFile(queryField.getSourceFile(), this.info);
366
388
  if (this.config.shouldMigrateQuery !== undefined &&
367
389
  !this.config.shouldMigrateQuery(descriptor, file)) {
368
390
  this.markFieldIncompatible(descriptor, {
369
391
  context: null,
370
- reason: group_replacements.FieldIncompatibilityReason.SkippedViaConfigFilter,
392
+ reason: migrate_ts_type_references.FieldIncompatibilityReason.SkippedViaConfigFilter,
371
393
  });
372
394
  }
373
395
  }
@@ -398,27 +420,27 @@ class KnownQueries {
398
420
  if (this.isFieldIncompatible(parent) && !this.isFieldIncompatible(derived)) {
399
421
  this.markFieldIncompatible(derived, {
400
422
  context: null,
401
- reason: group_replacements.FieldIncompatibilityReason.ParentIsIncompatible,
423
+ reason: migrate_ts_type_references.FieldIncompatibilityReason.ParentIsIncompatible,
402
424
  });
403
425
  return;
404
426
  }
405
427
  if (this.isFieldIncompatible(derived) && !this.isFieldIncompatible(parent)) {
406
428
  this.markFieldIncompatible(parent, {
407
429
  context: null,
408
- reason: group_replacements.FieldIncompatibilityReason.DerivedIsIncompatible,
430
+ reason: migrate_ts_type_references.FieldIncompatibilityReason.DerivedIsIncompatible,
409
431
  });
410
432
  }
411
433
  }
412
434
  captureUnknownDerivedField(field) {
413
435
  this.markFieldIncompatible(field, {
414
436
  context: null,
415
- reason: group_replacements.FieldIncompatibilityReason.OverriddenByDerivedClass,
437
+ reason: migrate_ts_type_references.FieldIncompatibilityReason.OverriddenByDerivedClass,
416
438
  });
417
439
  }
418
440
  captureUnknownParentField(field) {
419
441
  this.markFieldIncompatible(field, {
420
442
  context: null,
421
- reason: group_replacements.FieldIncompatibilityReason.TypeConflictWithBaseClass,
443
+ reason: migrate_ts_type_references.FieldIncompatibilityReason.TypeConflictWithBaseClass,
422
444
  });
423
445
  }
424
446
  getIncompatibilityForField(descriptor) {
@@ -437,13 +459,13 @@ class KnownQueries {
437
459
  getIncompatibilityTextForField(field) {
438
460
  const incompatibilityInfo = this.globalMetadata.problematicQueries[field.key];
439
461
  if (incompatibilityInfo.fieldReason !== null) {
440
- return group_replacements.getMessageForFieldIncompatibility(incompatibilityInfo.fieldReason, {
462
+ return migrate_ts_type_references.getMessageForFieldIncompatibility(incompatibilityInfo.fieldReason, {
441
463
  single: 'query',
442
464
  plural: 'queries',
443
465
  });
444
466
  }
445
467
  if (incompatibilityInfo.classReason !== null) {
446
- return group_replacements.getMessageForClassIncompatibility(incompatibilityInfo.classReason, {
468
+ return migrate_ts_type_references.getMessageForClassIncompatibility(incompatibilityInfo.classReason, {
447
469
  single: 'query',
448
470
  plural: 'queries',
449
471
  });
@@ -476,7 +498,7 @@ function queryFunctionNameToDecorator(name) {
476
498
  * E.g. whether `<my-read>.toArray` is detected.
477
499
  */
478
500
  function checkTsReferenceAccessesField(ref, fieldName) {
479
- const accessNode = group_replacements.traverseAccess(ref.from.node);
501
+ const accessNode = index.traverseAccess(ref.from.node);
480
502
  // Check if the reference is part of a property access.
481
503
  if (!ts__default["default"].isPropertyAccessExpression(accessNode.parent) ||
482
504
  !ts__default["default"].isIdentifier(accessNode.parent.name)) {
@@ -545,7 +567,7 @@ function checkNonTsReferenceCallsField(ref, fieldName) {
545
567
  }
546
568
 
547
569
  function removeQueryListToArrayCall(ref, info, globalMetadata, knownQueries, replacements) {
548
- if (!group_replacements.isHostBindingReference(ref) && !group_replacements.isTemplateReference(ref) && !group_replacements.isTsReference(ref)) {
570
+ if (!index.isHostBindingReference(ref) && !index.isTemplateReference(ref) && !index.isTsReference(ref)) {
549
571
  return;
550
572
  }
551
573
  if (knownQueries.isFieldIncompatible(ref.target)) {
@@ -555,13 +577,13 @@ function removeQueryListToArrayCall(ref, info, globalMetadata, knownQueries, rep
555
577
  return;
556
578
  }
557
579
  // TS references.
558
- if (group_replacements.isTsReference(ref)) {
580
+ if (index.isTsReference(ref)) {
559
581
  const toArrayCallExpr = checkTsReferenceCallsField(ref, 'toArray');
560
582
  if (toArrayCallExpr === null) {
561
583
  return;
562
584
  }
563
585
  const toArrayExpr = toArrayCallExpr.expression;
564
- replacements.push(new group_replacements.Replacement(group_replacements.projectFile(toArrayExpr.getSourceFile(), info), new group_replacements.TextUpdate({
586
+ replacements.push(new index.Replacement(index.projectFile(toArrayExpr.getSourceFile(), info), new index.TextUpdate({
565
587
  // Delete from expression end to call end. E.g. `.toArray(<..>)`.
566
588
  position: toArrayExpr.expression.getEnd(),
567
589
  end: toArrayCallExpr.getEnd(),
@@ -574,9 +596,9 @@ function removeQueryListToArrayCall(ref, info, globalMetadata, knownQueries, rep
574
596
  if (callExpr === null) {
575
597
  return;
576
598
  }
577
- const file = group_replacements.isHostBindingReference(ref) ? ref.from.file : ref.from.templateFile;
578
- const offset = group_replacements.isHostBindingReference(ref) ? ref.from.hostPropertyNode.getStart() + 1 : 0;
579
- replacements.push(new group_replacements.Replacement(file, new group_replacements.TextUpdate({
599
+ const file = index.isHostBindingReference(ref) ? ref.from.file : ref.from.templateFile;
600
+ const offset = index.isHostBindingReference(ref) ? ref.from.hostPropertyNode.getStart() + 1 : 0;
601
+ replacements.push(new index.Replacement(file, new index.TextUpdate({
580
602
  // Delete from expression end to call end. E.g. `.toArray(<..>)`.
581
603
  position: offset + callExpr.receiver.receiver.sourceSpan.end,
582
604
  end: offset + callExpr.sourceSpan.end,
@@ -585,7 +607,7 @@ function removeQueryListToArrayCall(ref, info, globalMetadata, knownQueries, rep
585
607
  }
586
608
 
587
609
  function replaceQueryListGetCall(ref, info, globalMetadata, knownQueries, replacements) {
588
- if (!group_replacements.isHostBindingReference(ref) && !group_replacements.isTemplateReference(ref) && !group_replacements.isTsReference(ref)) {
610
+ if (!index.isHostBindingReference(ref) && !index.isTemplateReference(ref) && !index.isTsReference(ref)) {
589
611
  return;
590
612
  }
591
613
  if (knownQueries.isFieldIncompatible(ref.target)) {
@@ -594,13 +616,13 @@ function replaceQueryListGetCall(ref, info, globalMetadata, knownQueries, replac
594
616
  if (!globalMetadata.knownQueryFields[ref.target.key]?.isMulti) {
595
617
  return;
596
618
  }
597
- if (group_replacements.isTsReference(ref)) {
619
+ if (index.isTsReference(ref)) {
598
620
  const getCallExpr = checkTsReferenceCallsField(ref, 'get');
599
621
  if (getCallExpr === null) {
600
622
  return;
601
623
  }
602
624
  const getExpr = getCallExpr.expression;
603
- replacements.push(new group_replacements.Replacement(group_replacements.projectFile(getExpr.getSourceFile(), info), new group_replacements.TextUpdate({
625
+ replacements.push(new index.Replacement(index.projectFile(getExpr.getSourceFile(), info), new index.TextUpdate({
604
626
  position: getExpr.name.getStart(),
605
627
  end: getExpr.name.getEnd(),
606
628
  toInsert: 'at',
@@ -612,9 +634,9 @@ function replaceQueryListGetCall(ref, info, globalMetadata, knownQueries, replac
612
634
  if (callExpr === null) {
613
635
  return;
614
636
  }
615
- const file = group_replacements.isHostBindingReference(ref) ? ref.from.file : ref.from.templateFile;
616
- const offset = group_replacements.isHostBindingReference(ref) ? ref.from.hostPropertyNode.getStart() + 1 : 0;
617
- replacements.push(new group_replacements.Replacement(file, new group_replacements.TextUpdate({
637
+ const file = index.isHostBindingReference(ref) ? ref.from.file : ref.from.templateFile;
638
+ const offset = index.isHostBindingReference(ref) ? ref.from.hostPropertyNode.getStart() + 1 : 0;
639
+ replacements.push(new index.Replacement(file, new index.TextUpdate({
618
640
  position: offset + callExpr.receiver.nameSpan.start,
619
641
  end: offset + callExpr.receiver.nameSpan.end,
620
642
  toInsert: 'at',
@@ -630,7 +652,7 @@ const problematicQueryListMethods = [
630
652
  'destroy',
631
653
  ];
632
654
  function checkForIncompatibleQueryListAccesses(ref, result) {
633
- if (group_replacements.isTsReference(ref)) {
655
+ if (index.isTsReference(ref)) {
634
656
  for (const problematicFn of problematicQueryListMethods) {
635
657
  const access = checkTsReferenceAccessesField(ref, problematicFn);
636
658
  if (access !== null) {
@@ -639,7 +661,7 @@ function checkForIncompatibleQueryListAccesses(ref, result) {
639
661
  }
640
662
  }
641
663
  }
642
- if (group_replacements.isHostBindingReference(ref) || group_replacements.isTemplateReference(ref)) {
664
+ if (index.isHostBindingReference(ref) || index.isTemplateReference(ref)) {
643
665
  for (const problematicFn of problematicQueryListMethods) {
644
666
  const access = checkNonTsReferenceAccessesField(ref, problematicFn);
645
667
  if (access !== null) {
@@ -655,7 +677,7 @@ const mapping = new Map([
655
677
  ['last', 'at(-1)!'],
656
678
  ]);
657
679
  function replaceQueryListFirstAndLastReferences(ref, info, globalMetadata, knownQueries, replacements) {
658
- if (!group_replacements.isHostBindingReference(ref) && !group_replacements.isTemplateReference(ref) && !group_replacements.isTsReference(ref)) {
680
+ if (!index.isHostBindingReference(ref) && !index.isTemplateReference(ref) && !index.isTsReference(ref)) {
659
681
  return;
660
682
  }
661
683
  if (knownQueries.isFieldIncompatible(ref.target)) {
@@ -664,12 +686,12 @@ function replaceQueryListFirstAndLastReferences(ref, info, globalMetadata, known
664
686
  if (!globalMetadata.knownQueryFields[ref.target.key]?.isMulti) {
665
687
  return;
666
688
  }
667
- if (group_replacements.isTsReference(ref)) {
689
+ if (index.isTsReference(ref)) {
668
690
  const expr = checkTsReferenceAccessesField(ref, 'first') ?? checkTsReferenceAccessesField(ref, 'last');
669
691
  if (expr === null) {
670
692
  return;
671
693
  }
672
- replacements.push(new group_replacements.Replacement(group_replacements.projectFile(expr.getSourceFile(), info), new group_replacements.TextUpdate({
694
+ replacements.push(new index.Replacement(index.projectFile(expr.getSourceFile(), info), new index.TextUpdate({
673
695
  position: expr.name.getStart(),
674
696
  end: expr.name.getEnd(),
675
697
  toInsert: mapping.get(expr.name.text),
@@ -681,16 +703,16 @@ function replaceQueryListFirstAndLastReferences(ref, info, globalMetadata, known
681
703
  if (expr === null) {
682
704
  return;
683
705
  }
684
- const file = group_replacements.isHostBindingReference(ref) ? ref.from.file : ref.from.templateFile;
685
- const offset = group_replacements.isHostBindingReference(ref) ? ref.from.hostPropertyNode.getStart() + 1 : 0;
686
- replacements.push(new group_replacements.Replacement(file, new group_replacements.TextUpdate({
706
+ const file = index.isHostBindingReference(ref) ? ref.from.file : ref.from.templateFile;
707
+ const offset = index.isHostBindingReference(ref) ? ref.from.hostPropertyNode.getStart() + 1 : 0;
708
+ replacements.push(new index.Replacement(file, new index.TextUpdate({
687
709
  position: offset + expr.nameSpan.start,
688
710
  end: offset + expr.nameSpan.end,
689
711
  toInsert: mapping.get(expr.name),
690
712
  })));
691
713
  }
692
714
 
693
- class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
715
+ class SignalQueriesMigration extends index.TsurgeComplexMigration {
694
716
  constructor(config = {}) {
695
717
  super();
696
718
  this.config = config;
@@ -709,7 +731,7 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
709
731
  potentialProblematicReferenceForMultiQueries: {},
710
732
  reusableAnalysisReferences: null,
711
733
  };
712
- const groupedAstVisitor = new group_replacements.GroupedTsAstVisitor(sourceFiles);
734
+ const groupedAstVisitor = new migrate_ts_type_references.GroupedTsAstVisitor(sourceFiles);
713
735
  const referenceResult = { references: [] };
714
736
  const classesWithFilteredQueries = new Set();
715
737
  const filteredQueriesForCompilationUnit = new Map();
@@ -721,7 +743,7 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
721
743
  key: extractedQuery.id,
722
744
  node: queryNode,
723
745
  };
724
- const containingFile = group_replacements.projectFile(queryNode.getSourceFile(), info);
746
+ const containingFile = index.projectFile(queryNode.getSourceFile(), info);
725
747
  // If we have a config filter function, use it here for later
726
748
  // perf-boosted reference lookups. Useful in non-batch mode.
727
749
  if (this.config.shouldMigrateQuery === undefined ||
@@ -736,7 +758,7 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
736
758
  isMulti: extractedQuery.queryInfo.first === false,
737
759
  };
738
760
  if (ts__default["default"].isAccessor(queryNode)) {
739
- markFieldIncompatibleInMetadata(res.potentialProblematicQueries, extractedQuery.id, group_replacements.FieldIncompatibilityReason.Accessor);
761
+ markFieldIncompatibleInMetadata(res.potentialProblematicQueries, extractedQuery.id, migrate_ts_type_references.FieldIncompatibilityReason.Accessor);
740
762
  }
741
763
  // Detect queries with union types that are uncommon to be
742
764
  // automatically migrate-able. E.g. `refs: ElementRef|null`,
@@ -746,7 +768,14 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
746
768
  // Either too large union, or doesn't match `T|undefined`.
747
769
  (queryNode.type.types.length > 2 ||
748
770
  !queryNode.type.types.some((t) => t.kind === ts__default["default"].SyntaxKind.UndefinedKeyword))) {
749
- markFieldIncompatibleInMetadata(res.potentialProblematicQueries, extractedQuery.id, group_replacements.FieldIncompatibilityReason.SignalQueries__IncompatibleMultiUnionType);
771
+ markFieldIncompatibleInMetadata(res.potentialProblematicQueries, extractedQuery.id, migrate_ts_type_references.FieldIncompatibilityReason.SignalQueries__IncompatibleMultiUnionType);
772
+ }
773
+ // Migrating fields with `@HostBinding` is incompatible as
774
+ // the host binding decorator does not invoke the signal.
775
+ const hostBindingDecorators = checker.getAngularDecorators(extractedQuery.fieldDecorators, ['HostBinding'],
776
+ /* isCore */ false);
777
+ if (hostBindingDecorators.length > 0) {
778
+ markFieldIncompatibleInMetadata(res.potentialProblematicQueries, extractedQuery.id, migrate_ts_type_references.FieldIncompatibilityReason.SignalIncompatibleWithHostBinding);
750
779
  }
751
780
  }
752
781
  };
@@ -774,15 +803,15 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
774
803
  return descriptor;
775
804
  },
776
805
  };
777
- groupedAstVisitor.register(group_replacements.createFindAllSourceFileReferencesVisitor(info, checker$1, reflector, info.ngCompiler['resourceManager'], evaluator, templateTypeChecker, allFieldsOrKnownQueries,
806
+ groupedAstVisitor.register(index.createFindAllSourceFileReferencesVisitor(info, checker$1, reflector, info.ngCompiler['resourceManager'], evaluator, templateTypeChecker, allFieldsOrKnownQueries,
778
807
  // In non-batch mode, we know what inputs exist and can optimize the reference
779
808
  // resolution significantly (for e.g. VSCode integration)— as we know what
780
809
  // field names may be used to reference potential queries.
781
810
  this.config.assumeNonBatch
782
811
  ? new Set(Array.from(filteredQueriesForCompilationUnit.values()).map((f) => f.fieldName))
783
812
  : null, referenceResult).visitor);
784
- const inheritanceGraph = new group_replacements.InheritanceGraph(checker$1).expensivePopulate(info.sourceFiles);
785
- group_replacements.checkIncompatiblePatterns(inheritanceGraph, checker$1, groupedAstVisitor, {
813
+ const inheritanceGraph = new migrate_ts_type_references.InheritanceGraph(checker$1).expensivePopulate(info.sourceFiles);
814
+ migrate_ts_type_references.checkIncompatiblePatterns(inheritanceGraph, checker$1, groupedAstVisitor, {
786
815
  ...allFieldsOrKnownQueries,
787
816
  isFieldIncompatible: (f) => res.potentialProblematicQueries[f.key]?.fieldReason !== null ||
788
817
  res.potentialProblematicQueries[f.key]?.classReason !== null,
@@ -802,16 +831,16 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
802
831
  // Determine incompatible queries based on problematic references
803
832
  // we saw in TS code, templates or host bindings.
804
833
  for (const ref of referenceResult.references) {
805
- if (group_replacements.isTsReference(ref) && ref.from.isWrite) {
806
- markFieldIncompatibleInMetadata(res.potentialProblematicQueries, ref.target.key, group_replacements.FieldIncompatibilityReason.WriteAssignment);
834
+ if (index.isTsReference(ref) && ref.from.isWrite) {
835
+ markFieldIncompatibleInMetadata(res.potentialProblematicQueries, ref.target.key, migrate_ts_type_references.FieldIncompatibilityReason.WriteAssignment);
807
836
  }
808
- if ((group_replacements.isTemplateReference(ref) || group_replacements.isHostBindingReference(ref)) && ref.from.isWrite) {
809
- markFieldIncompatibleInMetadata(res.potentialProblematicQueries, ref.target.key, group_replacements.FieldIncompatibilityReason.WriteAssignment);
837
+ if ((index.isTemplateReference(ref) || index.isHostBindingReference(ref)) && ref.from.isWrite) {
838
+ markFieldIncompatibleInMetadata(res.potentialProblematicQueries, ref.target.key, migrate_ts_type_references.FieldIncompatibilityReason.WriteAssignment);
810
839
  }
811
840
  // TODO: Remove this when we support signal narrowing in templates.
812
841
  // https://github.com/angular/angular/pull/55456.
813
- if (group_replacements.isTemplateReference(ref) && ref.from.isLikelyPartOfNarrowing) {
814
- markFieldIncompatibleInMetadata(res.potentialProblematicQueries, ref.target.key, group_replacements.FieldIncompatibilityReason.PotentiallyNarrowedInTemplateButNoSupportYet);
842
+ if (index.isTemplateReference(ref) && ref.from.isLikelyPartOfNarrowing) {
843
+ markFieldIncompatibleInMetadata(res.potentialProblematicQueries, ref.target.key, migrate_ts_type_references.FieldIncompatibilityReason.PotentiallyNarrowedInTemplateButNoSupportYet);
815
844
  }
816
845
  // Check for other incompatible query list accesses.
817
846
  checkForIncompatibleQueryListAccesses(ref, res);
@@ -819,7 +848,7 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
819
848
  if (this.config.assumeNonBatch) {
820
849
  res.reusableAnalysisReferences = referenceResult.references;
821
850
  }
822
- return group_replacements.confirmAsSerializable(res);
851
+ return index.confirmAsSerializable(res);
823
852
  }
824
853
  async merge(units) {
825
854
  const merged = {
@@ -851,11 +880,11 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
851
880
  for (const unit of units) {
852
881
  for (const id of Object.keys(unit.potentialProblematicReferenceForMultiQueries)) {
853
882
  if (merged.knownQueryFields[id]?.isMulti) {
854
- markFieldIncompatibleInMetadata(merged.problematicQueries, id, group_replacements.FieldIncompatibilityReason.SignalQueries__QueryListProblematicFieldAccessed);
883
+ markFieldIncompatibleInMetadata(merged.problematicQueries, id, migrate_ts_type_references.FieldIncompatibilityReason.SignalQueries__QueryListProblematicFieldAccessed);
855
884
  }
856
885
  }
857
886
  }
858
- return group_replacements.confirmAsSerializable(merged);
887
+ return index.confirmAsSerializable(merged);
859
888
  }
860
889
  async migrate(globalMetadata, info) {
861
890
  assert__default["default"](info.ngCompiler !== null, 'Expected queries migration to have an Angular program.');
@@ -909,21 +938,21 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
909
938
  // lookups below.
910
939
  const fieldNamesToConsiderForReferenceLookup = new Set(Object.values(globalMetadata.knownQueryFields).map((f) => f.fieldName));
911
940
  // Find all references.
912
- const groupedAstVisitor = new group_replacements.GroupedTsAstVisitor(sourceFiles);
941
+ const groupedAstVisitor = new migrate_ts_type_references.GroupedTsAstVisitor(sourceFiles);
913
942
  // Re-use previous reference result if available, instead of
914
943
  // looking for references which is quite expensive.
915
944
  if (globalMetadata.reusableAnalysisReferences !== null) {
916
945
  referenceResult.references = globalMetadata.reusableAnalysisReferences;
917
946
  }
918
947
  else {
919
- groupedAstVisitor.register(group_replacements.createFindAllSourceFileReferencesVisitor(info, checker$1, reflector, info.ngCompiler['resourceManager'], evaluator, templateTypeChecker, knownQueries, fieldNamesToConsiderForReferenceLookup, referenceResult).visitor);
948
+ groupedAstVisitor.register(index.createFindAllSourceFileReferencesVisitor(info, checker$1, reflector, info.ngCompiler['resourceManager'], evaluator, templateTypeChecker, knownQueries, fieldNamesToConsiderForReferenceLookup, referenceResult).visitor);
920
949
  }
921
950
  // Check inheritance.
922
951
  // NOTE: Inheritance is only checked in the migrate stage as we cannot reliably
923
952
  // check during analyze— where we don't know what fields from foreign `.d.ts`
924
953
  // files refer to queries or not.
925
- const inheritanceGraph = new group_replacements.InheritanceGraph(checker$1).expensivePopulate(info.sourceFiles);
926
- group_replacements.checkInheritanceOfKnownFields(inheritanceGraph, metaReader, knownQueries, {
954
+ const inheritanceGraph = new migrate_ts_type_references.InheritanceGraph(checker$1).expensivePopulate(info.sourceFiles);
955
+ migrate_ts_type_references.checkInheritanceOfKnownFields(inheritanceGraph, metaReader, knownQueries, {
927
956
  getFieldsForClass: (n) => knownQueries.getQueryFieldsOfClass(n) ?? [],
928
957
  isClassWithKnownFields: (clazz) => knownQueries.getQueryFieldsOfClass(clazz) !== undefined,
929
958
  });
@@ -943,7 +972,7 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
943
972
  if (incompatibility !== null) {
944
973
  // Add a TODO for the incompatible query, if desired.
945
974
  if (this.config.insertTodosForSkippedFields) {
946
- replacements.push(...group_replacements.insertTodoForIncompatibility(node, info, incompatibility, {
975
+ replacements.push(...migrate_ts_type_references.insertTodoForIncompatibility(node, info, incompatibility, {
947
976
  single: 'query',
948
977
  plural: 'queries',
949
978
  }));
@@ -951,7 +980,7 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
951
980
  updateFileState(filesWithIncompleteMigration, sf, extractedQuery.kind);
952
981
  continue;
953
982
  }
954
- replacements.push(...computeReplacementsToMigrateQuery(node, extractedQuery, importManager, info, printer));
983
+ replacements.push(...computeReplacementsToMigrateQuery(node, extractedQuery, importManager, info, printer, info.userOptions, checker$1));
955
984
  }
956
985
  // Migrate references.
957
986
  const referenceMigrationHost = {
@@ -962,10 +991,10 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
962
991
  .getQueryFieldsOfClass(clazz)
963
992
  ?.some((q) => !knownQueries.isFieldIncompatible(q)),
964
993
  };
965
- group_replacements.migrateTypeScriptReferences(referenceMigrationHost, referenceResult.references, checker$1, info);
994
+ migrate_ts_type_references.migrateTypeScriptReferences(referenceMigrationHost, referenceResult.references, checker$1, info);
966
995
  migrateTemplateReferences(referenceMigrationHost, referenceResult.references);
967
996
  migrateHostBindings(referenceMigrationHost, referenceResult.references, info);
968
- group_replacements.migrateTypeScriptTypeReferences(referenceMigrationHost, referenceResult.references, importManager, info);
997
+ migrate_ts_type_references.migrateTypeScriptTypeReferences(referenceMigrationHost, referenceResult.references, importManager, info);
969
998
  // Fix problematic calls, like `QueryList#toArray`, or `QueryList#get`.
970
999
  for (const ref of referenceResult.references) {
971
1000
  removeQueryListToArrayCall(ref, info, globalMetadata, knownQueries, replacements);
@@ -989,7 +1018,7 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
989
1018
  importManager.removeImport(file, 'QueryList', '@angular/core');
990
1019
  }
991
1020
  }
992
- group_replacements.applyImportManagerChanges(importManager, replacements, sourceFiles, info);
1021
+ index.applyImportManagerChanges(importManager, replacements, sourceFiles, info);
993
1022
  return { replacements, knownQueries };
994
1023
  }
995
1024
  async stats(globalMetadata) {
@@ -1010,13 +1039,13 @@ class SignalQueriesMigration extends group_replacements.TsurgeComplexMigration {
1010
1039
  }
1011
1040
  incompatibleQueries++;
1012
1041
  if (info.classReason !== null) {
1013
- const reasonName = group_replacements.ClassIncompatibilityReason[info.classReason];
1042
+ const reasonName = migrate_ts_type_references.ClassIncompatibilityReason[info.classReason];
1014
1043
  const key = `incompat-class-${reasonName}`;
1015
1044
  classIncompatibleCounts[key] ??= 0;
1016
1045
  classIncompatibleCounts[key]++;
1017
1046
  }
1018
1047
  if (info.fieldReason !== null) {
1019
- const reasonName = group_replacements.FieldIncompatibilityReason[info.fieldReason];
1048
+ const reasonName = migrate_ts_type_references.FieldIncompatibilityReason[info.fieldReason];
1020
1049
  const key = `incompat-field-${reasonName}`;
1021
1050
  fieldIncompatibleCounts[key] ??= 0;
1022
1051
  fieldIncompatibleCounts[key]++;
@@ -1052,7 +1081,7 @@ function migrate(options) {
1052
1081
  if (!buildPaths.length && !testPaths.length) {
1053
1082
  throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run signal queries migration.');
1054
1083
  }
1055
- const fs = new group_replacements.DevkitMigrationFilesystem(tree);
1084
+ const fs = new index.DevkitMigrationFilesystem(tree);
1056
1085
  checker.setFileSystem(fs);
1057
1086
  const migration = new SignalQueriesMigration({
1058
1087
  bestEffortMode: options.bestEffortMode,
@@ -1089,7 +1118,7 @@ function migrate(options) {
1089
1118
  for (const { info, tsconfigPath } of programInfos) {
1090
1119
  context.logger.info(`Migrating: ${tsconfigPath}..`);
1091
1120
  const { replacements } = await migration.migrate(merged, info);
1092
- const changesPerFile = group_replacements.groupReplacementsByFile(replacements);
1121
+ const changesPerFile = index.groupReplacementsByFile(replacements);
1093
1122
  for (const [file, changes] of changesPerFile) {
1094
1123
  if (!replacementsPerFile.has(file)) {
1095
1124
  replacementsPerFile.set(file, changes);