refactor(migrations): share reference migration code of signal input migration (#57766)

The reference migration code of the signal input migration should be
re-usable as the queries migration needs the exact same.

This builds on top of the shared reference resolution logic from
previous commits. Similarly this commit introduces a small "host" for
providing necessary configurable information about what references
should be migrated; supporting e.g. "input incompatibilities".

This is important as e.g. queries may also be incompatible for migration
and references to such, should not be migrated.

PR Close #57766
This commit is contained in:
Paul Gschwendtner 2024-09-10 18:32:35 +00:00 committed by Jessica Janiuk
parent acafa3b91d
commit ebe0c168e2
14 changed files with 395 additions and 139 deletions

View file

@ -7,89 +7,23 @@
*/
import ts from 'typescript';
import {KnownInputs} from '../input_detection/known_inputs';
import {MigrationResult} from '../result';
import {
migrateBindingElementInputReference,
IdentifierOfBindingElement,
} from './migrate_ts_reference/object_expansion_refs';
import {
migrateStandardTsReference,
NarrowableTsReferences,
} from './migrate_ts_reference/standard_reference';
import {migrateTypeScriptReferences} from './reference_migration/migrate_ts_references';
import {ProgramInfo} from '../../../../utils/tsurge';
import {ClassFieldUniqueKey} from './reference_resolution/known_fields';
import {isTsReference} from './reference_resolution/reference_kinds';
import {Reference} from './reference_resolution/reference_kinds';
import {ClassFieldDescriptor} from './reference_resolution/known_fields';
import {ReferenceMigrationHost} from './reference_migration/reference_migration_host';
/**
* Phase that migrates TypeScript input references to be signal compatible.
*
* The phase takes care of control flow analysis and generates temporary variables
* where needed to ensure narrowing continues to work. E.g.
*
* ```
* someMethod() {
* if (this.input) {
* this.input.charAt(0);
* }
* }
* ```
*
* will be transformed into:
*
* ```
* someMethod() {
* const input_1 = this.input();
* if (input_1) {
* input_1.charAt(0);
* }
* }
* ```
*/
export function pass5__migrateTypeScriptReferences(
result: MigrationResult,
export function pass5__migrateTypeScriptReferences<D extends ClassFieldDescriptor>(
host: ReferenceMigrationHost<D>,
references: Reference<D>[],
checker: ts.TypeChecker,
knownInputs: KnownInputs,
info: ProgramInfo,
) {
const tsReferencesWithNarrowing = new Map<ClassFieldUniqueKey, NarrowableTsReferences>();
const tsReferencesInBindingElements = new Set<IdentifierOfBindingElement>();
const seenIdentifiers = new WeakSet<ts.Identifier>();
for (const reference of result.references) {
// This pass only deals with TS references.
if (!isTsReference(reference)) {
continue;
}
// Skip references to incompatible inputs.
if (knownInputs.get(reference.target)!.isIncompatible()) {
continue;
}
// Never attempt to migrate write references.
// Those usually invalidate the target input most of the time, but in
// best-effort mode they are not.
if (reference.from.isWrite) {
continue;
}
// Skip duplicate references. E.g. in batching.
if (seenIdentifiers.has(reference.from.node)) {
continue;
}
seenIdentifiers.add(reference.from.node);
const targetKey = reference.target.key;
if (reference.from.isPartOfElementBinding) {
tsReferencesInBindingElements.add(reference.from.node as IdentifierOfBindingElement);
} else {
if (!tsReferencesWithNarrowing.has(targetKey)) {
tsReferencesWithNarrowing.set(targetKey, {accesses: []});
}
tsReferencesWithNarrowing.get(targetKey)!.accesses.push(reference.from.node);
}
}
migrateBindingElementInputReference(tsReferencesInBindingElements, info, result);
migrateStandardTsReference(tsReferencesWithNarrowing, checker, result, info);
migrateTypeScriptReferences(host, references, checker, info);
}

View file

@ -6,28 +6,27 @@
* found in the LICENSE file at https://angular.io/license
*/
import {MigrationResult} from '../result';
import {KnownInputs} from '../input_detection/known_inputs';
import {Replacement, TextUpdate} from '../../../../utils/tsurge';
import {isTemplateReference} from './reference_resolution/reference_kinds';
import {ReferenceMigrationHost} from './reference_migration/reference_migration_host';
import {ClassFieldDescriptor} from './reference_resolution/known_fields';
import {isTemplateReference, Reference} from './reference_resolution/reference_kinds';
/**
* Phase that migrates Angular template references to
* unwrap signals.
*/
export function pass7__migrateTemplateReferences(
result: MigrationResult,
knownInputs: KnownInputs,
export function pass7__migrateTemplateReferences<D extends ClassFieldDescriptor>(
host: ReferenceMigrationHost<D>,
references: Reference<D>[],
) {
const seenFileReferences = new Set<string>();
for (const reference of result.references) {
for (const reference of references) {
// This pass only deals with HTML template references.
if (!isTemplateReference(reference)) {
continue;
}
// Skip references to incompatible inputs.
if (knownInputs.get(reference.target)!.isIncompatible()) {
if (!host.shouldMigrateReferencesToField(reference.target)) {
continue;
}
@ -43,7 +42,7 @@ export function pass7__migrateTemplateReferences(
? `: ${reference.from.read.name}()`
: `()`;
result.replacements.push(
host.replacements.push(
new Replacement(
reference.from.templateFile,
new TextUpdate({

View file

@ -7,29 +7,29 @@
*/
import ts from 'typescript';
import {ReferenceMigrationHost} from './reference_migration/reference_migration_host';
import {ClassFieldDescriptor} from './reference_resolution/known_fields';
import {isHostBindingReference, Reference} from './reference_resolution/reference_kinds';
import {ProgramInfo, projectFile, Replacement, TextUpdate} from '../../../../utils/tsurge';
import {MigrationResult} from '../result';
import {KnownInputs} from '../input_detection/known_inputs';
import {isHostBindingReference} from './reference_resolution/reference_kinds';
/**
* Phase that migrates Angular host binding references to
* unwrap signals.
*/
export function pass8__migrateHostBindings(
result: MigrationResult,
knownInputs: KnownInputs,
export function pass8__migrateHostBindings<D extends ClassFieldDescriptor>(
host: ReferenceMigrationHost<D>,
references: Reference<D>[],
info: ProgramInfo,
) {
const seenReferences = new WeakMap<ts.Node, Set<number>>();
for (const reference of result.references) {
for (const reference of references) {
// This pass only deals with host binding references.
if (!isHostBindingReference(reference)) {
continue;
}
// Skip references to incompatible inputs.
if (knownInputs.get(reference.target)!.isIncompatible()) {
if (!host.shouldMigrateReferencesToField(reference.target)) {
continue;
}
@ -52,7 +52,7 @@ export function pass8__migrateHostBindings(
? `: ${reference.from.read.name}()`
: `()`;
result.replacements.push(
host.replacements.push(
new Replacement(
projectFile(bindingField.getSourceFile(), info),
new TextUpdate({position: readEndPos, end: readEndPos, toInsert: appendText}),

View file

@ -6,13 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import ts from 'typescript';
import {KnownInputs} from '../input_detection/known_inputs';
import {MigrationResult} from '../result';
import {ProgramInfo, projectFile, Replacement, TextUpdate} from '../../../../utils/tsurge';
import assert from 'assert';
import {ImportManager} from '@angular/compiler-cli/src/ngtsc/translator';
import {isTsClassTypeReference} from './reference_resolution/reference_kinds';
import assert from 'assert';
import ts from 'typescript';
import {ReferenceMigrationHost} from './reference_migration/reference_migration_host';
import {ClassFieldDescriptor} from './reference_resolution/known_fields';
import {ProgramInfo, projectFile, Replacement, TextUpdate} from '../../../../utils/tsurge';
import {isTsClassTypeReference, Reference} from './reference_resolution/reference_kinds';
/**
* Migrates TypeScript "ts.Type" references. E.g.
@ -20,21 +20,21 @@ import {isTsClassTypeReference} from './reference_resolution/reference_kinds';
* - `Partial<MyComp>` will be converted to `UnwrapSignalInputs<Partial<MyComp>>`.
in Catalyst test files.
*/
export function pass9__migrateTypeScriptTypeReferences(
result: MigrationResult,
knownInputs: KnownInputs,
export function pass9__migrateTypeScriptTypeReferences<D extends ClassFieldDescriptor>(
host: ReferenceMigrationHost<D>,
references: Reference<D>[],
importManager: ImportManager,
info: ProgramInfo,
) {
const seenTypeNodes = new WeakSet<ts.TypeReferenceNode>();
for (const reference of result.references) {
for (const reference of references) {
// This pass only deals with TS input class type references.
if (!isTsClassTypeReference(reference)) {
continue;
}
// Skip references to classes that are not fully migrated.
if (knownInputs.getDirectiveInfoForClass(reference.target)?.hasIncompatibleMembers()) {
if (!host.shouldMigrateReferencesToClass(reference.target)) {
continue;
}
// Skip duplicate references. E.g. in batching.
@ -62,17 +62,17 @@ export function pass9__migrateTypeScriptTypeReferences(
requestedFile: sf,
});
result.replacements.push(
host.replacements.push(
new Replacement(
projectFile(sf, info),
new TextUpdate({
position: firstArg.getStart(),
end: firstArg.getStart(),
toInsert: `${result.printer.printNode(ts.EmitHint.Unspecified, unwrapImportExpr, sf)}<`,
toInsert: `${host.printer.printNode(ts.EmitHint.Unspecified, unwrapImportExpr, sf)}<`,
}),
),
);
result.replacements.push(
host.replacements.push(
new Replacement(
projectFile(sf, info),
new TextUpdate({position: firstArg.getEnd(), end: firstArg.getEnd(), toInsert: '>'}),

View file

@ -7,7 +7,7 @@
*/
import ts from 'typescript';
import {ProjectFile, Replacement, TextUpdate} from '../../../../../utils/tsurge';
import {ProjectFile, Replacement, TextUpdate} from '../../../../../../utils/tsurge';
/**
* Creates replacements to insert the given statement as

View file

@ -13,11 +13,10 @@ import {
ProgramInfo,
projectFile,
ProjectFile,
} from '../../../../../utils/tsurge';
import {getBindingElementDeclaration} from '../../utils/binding_elements';
import {UniqueNamesGenerator} from '../../utils/unique_names';
} from '../../../../../../utils/tsurge';
import {getBindingElementDeclaration} from '../../../utils/binding_elements';
import {UniqueNamesGenerator} from '../../../utils/unique_names';
import assert from 'assert';
import {MigrationResult} from '../../result';
import {createNewBlockToInsertVariable} from './create_block_arrow_function';
/** An identifier part of a binding element. */
@ -44,7 +43,8 @@ export interface IdentifierOfBindingElement extends ts.Identifier {
export function migrateBindingElementInputReference(
tsReferencesInBindingElements: Set<IdentifierOfBindingElement>,
info: ProgramInfo,
result: MigrationResult,
replacements: Replacement[],
printer: ts.Printer,
) {
const nameGenerator = new UniqueNamesGenerator(['Input', 'Signal', 'Ref']);
@ -90,13 +90,13 @@ export function migrateBindingElementInputReference(
continue;
}
result.replacements.push(
replacements.push(
new Replacement(
file,
new TextUpdate({
position: bindingElement.getStart(),
end: bindingElement.getEnd(),
toInsert: result.printer.printNode(
toInsert: printer.printNode(
ts.EmitHint.Unspecified,
newBindingToAccessInputField,
sourceFile,

View file

@ -7,12 +7,11 @@
*/
import ts from 'typescript';
import {analyzeControlFlow} from '../../flow_analysis';
import {MigrationResult} from '../../result';
import {ProgramInfo, projectFile, Replacement, TextUpdate} from '../../../../../utils/tsurge';
import {traverseAccess} from '../../utils/traverse_access';
import {UniqueNamesGenerator} from '../../utils/unique_names';
import {createNewBlockToInsertVariable} from './create_block_arrow_function';
import {analyzeControlFlow} from '../../../flow_analysis';
import {ProgramInfo, projectFile, Replacement, TextUpdate} from '../../../../../../utils/tsurge';
import {traverseAccess} from '../../../utils/traverse_access';
import {UniqueNamesGenerator} from '../../../utils/unique_names';
import {createNewBlockToInsertVariable} from '../helpers/create_block_arrow_function';
export interface NarrowableTsReferences {
accesses: ts.Identifier[];
@ -21,8 +20,8 @@ export interface NarrowableTsReferences {
export function migrateStandardTsReference(
tsReferencesWithNarrowing: Map<unknown, NarrowableTsReferences>,
checker: ts.TypeChecker,
result: MigrationResult,
info: ProgramInfo,
replacements: Replacement[],
) {
const nameGenerator = new UniqueNamesGenerator(['Value', 'Val', 'Input']);
@ -38,7 +37,7 @@ export function migrateStandardTsReference(
// Unwrap the signal directly.
if (recommendedNode === 'preserve') {
// Append `()` to unwrap the signal.
result.replacements.push(
replacements.push(
new Replacement(
projectFile(sf, info),
new TextUpdate({
@ -55,7 +54,7 @@ export function migrateStandardTsReference(
// with the temporary variable.
if (typeof recommendedNode === 'number') {
const replaceNode = traverseAccess(originalNode);
result.replacements.push(
replacements.push(
new Replacement(
projectFile(sf, info),
new TextUpdate({
@ -94,13 +93,13 @@ export function migrateStandardTsReference(
// without a block, convert the arrow function to a block and insert the temporary
// variable at the beginning.
if (ts.isArrowFunction(parent) && !ts.isBlock(parent.body)) {
result.replacements.push(
replacements.push(
...createNewBlockToInsertVariable(parent, filePath, temporaryVariableStr),
);
} else {
const leadingSpace = ts.getLineAndCharacterOfPosition(sf, referenceNodeInBlock.getStart());
result.replacements.push(
replacements.push(
new Replacement(
filePath,
new TextUpdate({
@ -112,7 +111,7 @@ export function migrateStandardTsReference(
);
}
result.replacements.push(
replacements.push(
new Replacement(
projectFile(sf, info),
new TextUpdate({

View file

@ -0,0 +1,62 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import ts from 'typescript';
import {ProgramInfo, projectFile, Replacement, TextUpdate} from '../../../../../utils/tsurge';
import {ClassFieldDescriptor} from '../reference_resolution/known_fields';
import {isHostBindingReference, Reference} from '../reference_resolution/reference_kinds';
import {ReferenceMigrationHost} from './reference_migration_host';
/**
* Phase that migrates Angular host binding references to
* unwrap signals.
*/
export function migrateHostBindings<D extends ClassFieldDescriptor>(
host: ReferenceMigrationHost<D>,
references: Reference<D>[],
info: ProgramInfo,
) {
const seenReferences = new WeakMap<ts.Node, Set<number>>();
for (const reference of references) {
// This pass only deals with host binding references.
if (!isHostBindingReference(reference)) {
continue;
}
// Skip references to incompatible inputs.
if (!host.shouldMigrateReferencesToField(reference.target)) {
continue;
}
const bindingField = reference.from.hostPropertyNode;
const expressionOffset = bindingField.getStart() + 1; // account for quotes.
const readEndPos = expressionOffset + reference.from.read.sourceSpan.end;
// Skip duplicate references. Can happen if the host object is shared.
if (seenReferences.get(bindingField)?.has(readEndPos)) {
continue;
}
if (seenReferences.has(bindingField)) {
seenReferences.get(bindingField)!.add(readEndPos);
} else {
seenReferences.set(bindingField, new Set([readEndPos]));
}
// Expand shorthands like `{bla}` to `{bla: bla()}`.
const appendText = reference.from.isObjectShorthandExpression
? `: ${reference.from.read.name}()`
: `()`;
host.replacements.push(
new Replacement(
projectFile(bindingField.getSourceFile(), info),
new TextUpdate({position: readEndPos, end: readEndPos, toInsert: appendText}),
),
);
}
}

View file

@ -0,0 +1,57 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Replacement, TextUpdate} from '../../../../../utils/tsurge';
import {ClassFieldDescriptor} from '../reference_resolution/known_fields';
import {isTemplateReference, Reference} from '../reference_resolution/reference_kinds';
import {ReferenceMigrationHost} from './reference_migration_host';
/**
* Phase that migrates Angular template references to
* unwrap signals.
*/
export function migrateTemplateReferences<D extends ClassFieldDescriptor>(
host: ReferenceMigrationHost<D>,
references: Reference<D>[],
) {
const seenFileReferences = new Set<string>();
for (const reference of references) {
// This pass only deals with HTML template references.
if (!isTemplateReference(reference)) {
continue;
}
// Skip references to incompatible inputs.
if (!host.shouldMigrateReferencesToField(reference.target)) {
continue;
}
// Skip duplicate references. E.g. if a template is shared.
const fileReferenceId = `${reference.from.templateFile.id}:${reference.from.read.sourceSpan.end}`;
if (seenFileReferences.has(fileReferenceId)) {
continue;
}
seenFileReferences.add(fileReferenceId);
// Expand shorthands like `{bla}` to `{bla: bla()}`.
const appendText = reference.from.isObjectShorthandExpression
? `: ${reference.from.read.name}()`
: `()`;
host.replacements.push(
new Replacement(
reference.from.templateFile,
new TextUpdate({
position: reference.from.read.sourceSpan.end,
end: reference.from.read.sourceSpan.end,
toInsert: appendText,
}),
),
);
}
}

View file

@ -0,0 +1,96 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import ts from 'typescript';
import {
migrateBindingElementInputReference,
IdentifierOfBindingElement,
} from './helpers/object_expansion_refs';
import {migrateStandardTsReference, NarrowableTsReferences} from './helpers/standard_reference';
import {ProgramInfo} from '../../../../../utils/tsurge';
import {ClassFieldDescriptor, ClassFieldUniqueKey} from '../reference_resolution/known_fields';
import {isTsReference, Reference} from '../reference_resolution/reference_kinds';
import {ReferenceMigrationHost} from './reference_migration_host';
/**
* Migrates TypeScript input references to be signal compatible.
*
* The phase takes care of control flow analysis and generates temporary variables
* where needed to ensure narrowing continues to work. E.g.
*
* ```
* someMethod() {
* if (this.input) {
* this.input.charAt(0);
* }
* }
* ```
*
* will be transformed into:
*
* ```
* someMethod() {
* const input_1 = this.input();
* if (input_1) {
* input_1.charAt(0);
* }
* }
* ```
*/
export function migrateTypeScriptReferences<D extends ClassFieldDescriptor>(
host: ReferenceMigrationHost<D>,
references: Reference<D>[],
checker: ts.TypeChecker,
info: ProgramInfo,
) {
const tsReferencesWithNarrowing = new Map<ClassFieldUniqueKey, NarrowableTsReferences>();
const tsReferencesInBindingElements = new Set<IdentifierOfBindingElement>();
const seenIdentifiers = new WeakSet<ts.Identifier>();
for (const reference of references) {
// This pass only deals with TS references.
if (!isTsReference(reference)) {
continue;
}
// Skip references to incompatible inputs.
if (!host.shouldMigrateReferencesToField(reference.target)) {
continue;
}
// Never attempt to migrate write references.
// Those usually invalidate the target input most of the time, but in
// best-effort mode they are not.
if (reference.from.isWrite) {
continue;
}
// Skip duplicate references. E.g. in batching.
if (seenIdentifiers.has(reference.from.node)) {
continue;
}
seenIdentifiers.add(reference.from.node);
const targetKey = reference.target.key;
if (reference.from.isPartOfElementBinding) {
tsReferencesInBindingElements.add(reference.from.node as IdentifierOfBindingElement);
} else {
if (!tsReferencesWithNarrowing.has(targetKey)) {
tsReferencesWithNarrowing.set(targetKey, {accesses: []});
}
tsReferencesWithNarrowing.get(targetKey)!.accesses.push(reference.from.node);
}
}
migrateBindingElementInputReference(
tsReferencesInBindingElements,
info,
host.replacements,
host.printer,
);
migrateStandardTsReference(tsReferencesWithNarrowing, checker, info, host.replacements);
}

View file

@ -0,0 +1,77 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import ts from 'typescript';
import {KnownInputs} from '../../input_detection/known_inputs';
import {MigrationResult} from '../../result';
import {ProgramInfo, projectFile, Replacement, TextUpdate} from '../../../../../utils/tsurge';
import assert from 'assert';
import {ImportManager} from '@angular/compiler-cli/src/ngtsc/translator';
import {isTsClassTypeReference} from '../reference_resolution/reference_kinds';
/**
* Migrates TypeScript "ts.Type" references. E.g.
* - `Partial<MyComp>` will be converted to `UnwrapSignalInputs<Partial<MyComp>>`.
in Catalyst test files.
*/
export function migrateTypeScriptTypeReferences(
result: MigrationResult,
knownInputs: KnownInputs,
importManager: ImportManager,
info: ProgramInfo,
) {
const seenTypeNodes = new WeakSet<ts.TypeReferenceNode>();
for (const reference of result.references) {
// This pass only deals with TS input class type references.
if (!isTsClassTypeReference(reference)) {
continue;
}
// Skip references to classes that are not fully migrated.
if (knownInputs.getDirectiveInfoForClass(reference.target)?.hasIncompatibleMembers()) {
continue;
}
// Skip duplicate references. E.g. in batching.
if (seenTypeNodes.has(reference.from.node)) {
continue;
}
seenTypeNodes.add(reference.from.node);
if (reference.isPartialReference && reference.isPartOfCatalystFile) {
assert(reference.from.node.typeArguments, 'Expected type arguments for partial reference.');
assert(reference.from.node.typeArguments.length === 1, 'Expected an argument for reference.');
const firstArg = reference.from.node.typeArguments[0];
const sf = firstArg.getSourceFile();
const unwrapImportExpr = importManager.addImport({
exportModuleSpecifier: 'google3/javascript/angular2/testing/catalyst',
exportSymbolName: 'UnwrapSignalInputs',
requestedFile: sf,
});
result.replacements.push(
new Replacement(
projectFile(sf, info),
new TextUpdate({
position: firstArg.getStart(),
end: firstArg.getStart(),
toInsert: `${result.printer.printNode(ts.EmitHint.Unspecified, unwrapImportExpr, sf)}<`,
}),
),
);
result.replacements.push(
new Replacement(
projectFile(sf, info),
new TextUpdate({position: firstArg.getEnd(), end: firstArg.getEnd(), toInsert: '>'}),
),
);
}
}
}

View file

@ -0,0 +1,18 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import ts from 'typescript';
import {Replacement} from '../../../../../utils/tsurge';
import {ClassFieldDescriptor} from '../reference_resolution/known_fields';
export interface ReferenceMigrationHost<D extends ClassFieldDescriptor> {
shouldMigrateReferencesToField: (descriptor: D) => boolean;
shouldMigrateReferencesToClass: (clazz: ts.ClassDeclaration) => boolean;
replacements: Replacement[];
printer: ts.Printer;
}

View file

@ -117,10 +117,7 @@ export function executeAnalysisPhase(
// TODO: Remove this when we support signal narrowing in templates.
// https://github.com/angular/angular/pull/55456.
if (isTemplateReference(reference)) {
if (
process.env['MIGRATE_NARROWED_NARROWED_IN_TEMPLATES'] !== '1' &&
reference.from.isLikelyPartOfNarrowing
) {
if (reference.from.isLikelyPartOfNarrowing) {
knownInputs.markInputAsIncompatible(reference.target, {
reason: InputIncompatibilityReason.PotentiallyNarrowedInTemplateButNoSupportYet,
context: null,

View file

@ -9,14 +9,16 @@
import {AnalysisProgramInfo} from './analysis_deps';
import {KnownInputs} from './input_detection/known_inputs';
import {MigrationHost} from './migration_host';
import {pass5__migrateTypeScriptReferences} from './passes/5_migrate_ts_references';
import {pass6__migrateInputDeclarations} from './passes/6_migrate_input_declarations';
import {pass7__migrateTemplateReferences} from './passes/7_migrate_template_references';
import {pass8__migrateHostBindings} from './passes/8_migrate_host_bindings';
import {pass9__migrateTypeScriptTypeReferences} from './passes/9_migrate_ts_type_references';
import {MigrationResult} from './result';
import {pass10_applyImportManager} from './passes/10_apply_import_manager';
import {ImportManager} from '@angular/compiler-cli/src/ngtsc/translator';
import {InputDescriptor} from './utils/input_id';
import {ReferenceMigrationHost} from './passes/reference_migration/reference_migration_host';
import {pass5__migrateTypeScriptReferences} from './passes/5_migrate_ts_references';
import {pass7__migrateTemplateReferences} from './passes/7_migrate_template_references';
import {pass8__migrateHostBindings} from './passes/8_migrate_host_bindings';
import {pass9__migrateTypeScriptTypeReferences} from './passes/9_migrate_ts_type_references';
/**
* Executes the migration phase.
@ -40,11 +42,26 @@ export function executeMigrationPhase(
generateUniqueIdentifier: () => null,
});
const referenceMigrationHost: ReferenceMigrationHost<InputDescriptor> = {
printer: result.printer,
replacements: result.replacements,
shouldMigrateReferencesToField: (inputDescr) =>
knownInputs.has(inputDescr) && knownInputs.get(inputDescr)!.isIncompatible() === false,
shouldMigrateReferencesToClass: (clazz) =>
knownInputs.getDirectiveInfoForClass(clazz) !== undefined &&
knownInputs.getDirectiveInfoForClass(clazz)!.hasIncompatibleMembers() === false,
};
// Migrate passes.
pass5__migrateTypeScriptReferences(result, typeChecker, knownInputs, info);
pass5__migrateTypeScriptReferences(referenceMigrationHost, result.references, typeChecker, info);
pass6__migrateInputDeclarations(typeChecker, result, knownInputs, importManager, info);
pass7__migrateTemplateReferences(result, knownInputs);
pass8__migrateHostBindings(result, knownInputs, info);
pass9__migrateTypeScriptTypeReferences(result, knownInputs, importManager, info);
pass7__migrateTemplateReferences(referenceMigrationHost, result.references);
pass8__migrateHostBindings(referenceMigrationHost, result.references, info);
pass9__migrateTypeScriptTypeReferences(
referenceMigrationHost,
result.references,
importManager,
info,
);
pass10_applyImportManager(importManager, result, sourceFiles, info);
}