Skip to content

Commit 389933f

Browse files
devversionalxhub
authored andcommitted
refactor(migrations): allow tsurge migrations to run with just NgCompiler (#57562)
This is important so that migrations can easily be wired up in the language service where only `NgCompiler` is available. PR Close #57562
1 parent 674aed5 commit 389933f

File tree

11 files changed

+52
-100
lines changed

11 files changed

+52
-100
lines changed

packages/core/schematics/migrations/signal-migration/src/analysis_deps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {TemplateTypeChecker} from '../../../../../compiler-cli/src/ngtsc/typeche
2525
* Interface containing the analysis information
2626
* for an Angular program to be migrated.
2727
*/
28-
export interface AnalysisProgramInfo extends ProgramInfo<NgtscProgram> {
28+
export interface AnalysisProgramInfo extends ProgramInfo {
2929
// List of source files in the program.
3030
sourceFiles: ts.SourceFile[];
3131
// List of all files in the program, including external `d.ts`.

packages/core/schematics/migrations/signal-migration/src/migration.ts

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {NgtscProgram} from '../../../../../compiler-cli/src/ngtsc/program';
109
import {FileSystem} from '../../../../../compiler-cli/src/ngtsc/file_system';
1110
import {confirmAsSerializable, Serializable} from '../../../utils/tsurge/helpers/serializable';
1211
import {BaseProgramInfo, ProgramInfo} from '../../../utils/tsurge/program_info';
@@ -26,24 +25,23 @@ import {InheritanceGraph} from './utils/inheritance_graph';
2625
import {executeMigrationPhase} from './phase_migrate';
2726
import {filterIncompatibilitiesForBestEffortMode} from './best_effort_mode';
2827
import {createNgtscProgram} from '../../../utils/tsurge/helpers/ngtsc_program';
28+
import assert from 'assert';
2929

3030
/**
3131
* Tsurge migration for migrating Angular `@Input()` declarations to
3232
* signal inputs, with support for batch execution.
3333
*/
3434
export class SignalInputMigration extends TsurgeComplexMigration<
3535
CompilationUnitData,
36-
CompilationUnitData,
37-
NgtscProgram,
38-
AnalysisProgramInfo
36+
CompilationUnitData
3937
> {
4038
upgradeAnalysisPhaseToAvoidBatch = false;
4139
upgradedAnalysisPhaseResults: Replacement[] | null = null;
4240

4341
bestEffortMode = false;
4442

4543
// Override the default ngtsc program creation, to add extra flags.
46-
override createProgram(tsconfigAbsPath: string, fs?: FileSystem): BaseProgramInfo<NgtscProgram> {
44+
override createProgram(tsconfigAbsPath: string, fs?: FileSystem): BaseProgramInfo {
4745
return createNgtscProgram(tsconfigAbsPath, fs, {
4846
_enableTemplateTypeChecker: true,
4947
_compilePoisonedComponents: true,
@@ -57,23 +55,20 @@ export class SignalInputMigration extends TsurgeComplexMigration<
5755
}
5856

5957
// Extend the program info with the analysis information we need in every phase.
60-
override prepareProgram(baseInfo: BaseProgramInfo<NgtscProgram>): AnalysisProgramInfo {
61-
const info = super.prepareProgram(baseInfo);
58+
prepareAnalysisDeps(info: ProgramInfo): AnalysisProgramInfo {
59+
assert(info.ngCompiler !== null, 'Expected `NgCompiler` to be configured.');
6260
return {
6361
...info,
64-
...prepareAnalysisInfo(
65-
info.program.getTsProgram(),
66-
info.program.compiler,
67-
info.programAbsoluteRootPaths,
68-
),
62+
...prepareAnalysisInfo(info.program, info.ngCompiler, info.programAbsoluteRootPaths),
6963
};
7064
}
7165

72-
override async analyze(analysisDeps: AnalysisProgramInfo) {
66+
override async analyze(info: ProgramInfo) {
67+
const analysisDeps = this.prepareAnalysisDeps(info);
7368
const {metaRegistry} = analysisDeps;
7469
const knownInputs = new KnownInputs();
7570
const result = new MigrationResult();
76-
const host = createMigrationHost(analysisDeps);
71+
const host = createMigrationHost(info);
7772

7873
const {inheritanceGraph} = executeAnalysisPhase(host, knownInputs, result, analysisDeps);
7974
pass4__checkInheritanceOfInputs(host, inheritanceGraph, metaRegistry, knownInputs);
@@ -86,11 +81,12 @@ export class SignalInputMigration extends TsurgeComplexMigration<
8681
// Non-batch mode!
8782
if (this.upgradeAnalysisPhaseToAvoidBatch) {
8883
const merged = await this.merge([unitData]);
89-
const replacements = await this.migrate(merged, analysisDeps, {
84+
const replacements = await this.migrate(merged, info, {
9085
knownInputs,
9186
result,
9287
host,
9388
inheritanceGraph,
89+
analysisDeps,
9490
});
9591

9692
// Expose the upgraded analysis stage results.
@@ -106,18 +102,19 @@ export class SignalInputMigration extends TsurgeComplexMigration<
106102

107103
override async migrate(
108104
globalMetadata: CompilationUnitData,
109-
analysisDeps: AnalysisProgramInfo,
105+
info: ProgramInfo,
110106
nonBatchData?: {
111107
knownInputs: KnownInputs;
112108
result: MigrationResult;
113109
host: MigrationHost;
114110
inheritanceGraph: InheritanceGraph;
111+
analysisDeps: AnalysisProgramInfo;
115112
},
116113
): Promise<Replacement[]> {
117114
const knownInputs = nonBatchData?.knownInputs ?? new KnownInputs();
118115
const result = nonBatchData?.result ?? new MigrationResult();
119-
const host = nonBatchData?.host ?? createMigrationHost(analysisDeps);
120-
const {metaRegistry} = analysisDeps;
116+
const host = nonBatchData?.host ?? createMigrationHost(info);
117+
const analysisDeps = nonBatchData?.analysisDeps ?? this.prepareAnalysisDeps(info);
121118
let inheritanceGraph: InheritanceGraph;
122119

123120
// Can't re-use analysis structures, so re-build them.
@@ -129,7 +126,7 @@ export class SignalInputMigration extends TsurgeComplexMigration<
129126
inheritanceGraph = nonBatchData.inheritanceGraph;
130127
}
131128

132-
pass4__checkInheritanceOfInputs(host, inheritanceGraph, metaRegistry, knownInputs);
129+
pass4__checkInheritanceOfInputs(host, inheritanceGraph, analysisDeps.metaRegistry, knownInputs);
133130
if (this.bestEffortMode) {
134131
filterIncompatibilitiesForBestEffortMode(knownInputs);
135132
}
@@ -140,7 +137,7 @@ export class SignalInputMigration extends TsurgeComplexMigration<
140137
}
141138
}
142139

143-
function createMigrationHost(info: ProgramInfo<NgtscProgram>): MigrationHost {
140+
function createMigrationHost(info: ProgramInfo): MigrationHost {
144141
return new MigrationHost(
145142
/* projectDir */ info.projectDirAbsPath,
146143
/* isMigratingCore */ false,

packages/core/schematics/utils/tsurge/base_migration.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import assert from 'assert';
109
import path from 'path';
11-
import ts from 'typescript';
1210
import {FileSystem} from '../../../../compiler-cli/src/ngtsc/file_system';
13-
import {NgtscProgram} from '../../../../compiler-cli/src/ngtsc/program';
1411
import {isShim} from '../../../../compiler-cli/src/ngtsc/shims';
1512
import {createNgtscProgram} from './helpers/ngtsc_program';
1613
import {BaseProgramInfo, ProgramInfo} from './program_info';
@@ -21,22 +18,16 @@ import {BaseProgramInfo, ProgramInfo} from './program_info';
2118
* For example, this class exposes methods to conveniently create
2219
* TypeScript programs, while also allowing migration authors to override.
2320
*/
24-
export abstract class TsurgeBaseMigration<
25-
TsProgramType extends ts.Program | NgtscProgram = NgtscProgram,
26-
PreparationInfo = ProgramInfo<TsProgramType>,
27-
> {
21+
export abstract class TsurgeBaseMigration {
2822
// By default, ngtsc programs are being created.
29-
createProgram(tsconfigAbsPath: string, fs?: FileSystem): BaseProgramInfo<TsProgramType> {
30-
return createNgtscProgram(tsconfigAbsPath, fs) as BaseProgramInfo<TsProgramType>;
23+
createProgram(tsconfigAbsPath: string, fs?: FileSystem): BaseProgramInfo {
24+
return createNgtscProgram(tsconfigAbsPath, fs);
3125
}
3226

3327
// Optional function to prepare the base `ProgramInfo` even further,
3428
// for the analyze and migrate phases. E.g. determining source files.
35-
prepareProgram(info: BaseProgramInfo<TsProgramType>): PreparationInfo {
36-
assert(info.program instanceof NgtscProgram);
37-
38-
const userProgram = info.program.getTsProgram();
39-
const fullProgramSourceFiles = userProgram.getSourceFiles();
29+
prepareProgram(info: BaseProgramInfo): ProgramInfo {
30+
const fullProgramSourceFiles = [...info.program.getSourceFiles()];
4031
const sourceFiles = fullProgramSourceFiles.filter(
4132
(f) =>
4233
!f.isDeclarationFile &&
@@ -53,6 +44,6 @@ export abstract class TsurgeBaseMigration<
5344
sourceFiles,
5445
fullProgramSourceFiles,
5546
projectDirAbsPath,
56-
} as PreparationInfo;
47+
};
5748
}
5849
}

packages/core/schematics/utils/tsurge/executors/analyze_exec.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,15 @@
88

99
import {TsurgeMigration} from '../migration';
1010
import {Serializable} from '../helpers/serializable';
11-
import ts from 'typescript';
12-
import {NgtscProgram} from '../../../../../compiler-cli/src/ngtsc/program';
1311

1412
/**
1513
* Executes the analyze phase of the given migration against
1614
* the specified TypeScript project.
1715
*
1816
* @returns the serializable migration unit data.
1917
*/
20-
export async function executeAnalyzePhase<
21-
UnitData,
22-
GlobalData,
23-
TsProgramType extends ts.Program | NgtscProgram,
24-
>(
25-
migration: TsurgeMigration<UnitData, GlobalData, TsProgramType, unknown>,
18+
export async function executeAnalyzePhase<UnitData, GlobalData>(
19+
migration: TsurgeMigration<UnitData, GlobalData>,
2620
tsconfigAbsolutePath: string,
2721
): Promise<Serializable<UnitData>> {
2822
const baseInfo = migration.createProgram(tsconfigAbsolutePath);

packages/core/schematics/utils/tsurge/executors/merge_exec.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,17 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import ts from 'typescript';
109
import {Serializable} from '../helpers/serializable';
1110
import {TsurgeMigration} from '../migration';
12-
import {NgtscProgram} from '../../../../../compiler-cli/src/ngtsc/program';
1311

1412
/**
1513
* Executes the merge phase for the given migration against
1614
* the given set of analysis unit data.
1715
*
1816
* @returns the serializable migration global data.
1917
*/
20-
export async function executeMergePhase<
21-
UnitData,
22-
GlobalData,
23-
TsProgramType extends ts.Program | NgtscProgram,
24-
>(
25-
migration: TsurgeMigration<UnitData, GlobalData, TsProgramType, unknown>,
18+
export async function executeMergePhase<UnitData, GlobalData>(
19+
migration: TsurgeMigration<UnitData, GlobalData>,
2620
units: UnitData[],
2721
): Promise<Serializable<GlobalData>> {
2822
return await migration.merge(units);

packages/core/schematics/utils/tsurge/executors/migrate_exec.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
import {TsurgeMigration} from '../migration';
1010
import {Replacement} from '../replacement';
11-
import {NgtscProgram} from '../../../../../compiler-cli/src/ngtsc/program';
12-
import ts from 'typescript';
1311

1412
/**
1513
* Executes the migrate phase of the given migration against
@@ -20,12 +18,8 @@ import ts from 'typescript';
2018
*
2119
* @returns a list of text replacements to apply to disk.
2220
*/
23-
export async function executeMigratePhase<
24-
UnitData,
25-
GlobalData,
26-
TsProgramType extends ts.Program | NgtscProgram,
27-
>(
28-
migration: TsurgeMigration<UnitData, GlobalData, TsProgramType, unknown>,
21+
export async function executeMigratePhase<UnitData, GlobalData>(
22+
migration: TsurgeMigration<UnitData, GlobalData>,
2923
globalMetadata: GlobalData,
3024
tsconfigAbsolutePath: string,
3125
): Promise<Replacement[]> {

packages/core/schematics/utils/tsurge/helpers/ngtsc_program.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function createNgtscProgram(
2525
absoluteTsconfigPath: string,
2626
fs?: FileSystem,
2727
optionOverrides: NgCompilerOptions = {},
28-
): BaseProgramInfo<NgtscProgram> {
28+
): BaseProgramInfo {
2929
if (fs === undefined) {
3030
fs = new NodeJSFileSystem();
3131
setFileSystem(fs);
@@ -57,7 +57,8 @@ export function createNgtscProgram(
5757
);
5858

5959
return {
60-
program: ngtscProgram,
60+
ngCompiler: ngtscProgram.compiler,
61+
program: ngtscProgram.getTsProgram(),
6162
userOptions: tsconfig.options,
6263
programAbsoluteRootPaths: tsconfig.rootNames,
6364
tsconfigAbsolutePath: absoluteTsconfigPath,

packages/core/schematics/utils/tsurge/migration.ts

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import ts from 'typescript';
10-
import {NgtscProgram} from '../../../../compiler-cli/src/ngtsc/program';
119
import {TsurgeBaseMigration} from './base_migration';
1210
import {Serializable} from './helpers/serializable';
1311
import {ProgramInfo} from './program_info';
@@ -37,24 +35,9 @@ import {Replacement} from './replacement';
3735
*
3836
* TODO: Link design doc
3937
*/
40-
export type TsurgeMigration<
41-
UnitAnalysisMetadata,
42-
CombinedGlobalMetadata,
43-
TsProgramType extends ts.Program | NgtscProgram = NgtscProgram,
44-
PreparationInfo = ProgramInfo<TsProgramType>,
45-
> =
46-
| TsurgeComplexMigration<
47-
UnitAnalysisMetadata,
48-
CombinedGlobalMetadata,
49-
TsProgramType,
50-
PreparationInfo
51-
>
52-
| TsurgeFunnelMigration<
53-
UnitAnalysisMetadata,
54-
CombinedGlobalMetadata,
55-
TsProgramType,
56-
PreparationInfo
57-
>;
38+
export type TsurgeMigration<UnitAnalysisMetadata, CombinedGlobalMetadata> =
39+
| TsurgeComplexMigration<UnitAnalysisMetadata, CombinedGlobalMetadata>
40+
| TsurgeFunnelMigration<UnitAnalysisMetadata, CombinedGlobalMetadata>;
5841

5942
/**
6043
* A simpler variant of a {@link TsurgeComplexMigration} that does not
@@ -71,9 +54,8 @@ export type TsurgeMigration<
7154
export abstract class TsurgeFunnelMigration<
7255
UnitAnalysisMetadata,
7356
CombinedGlobalMetadata,
74-
TsProgramType extends ts.Program | NgtscProgram = NgtscProgram,
75-
PreparationInfo = ProgramInfo<TsProgramType>,
76-
> extends TsurgeBaseMigration<TsProgramType, PreparationInfo> {
57+
PreparationInfo = ProgramInfo,
58+
> extends TsurgeBaseMigration {
7759
/** Analyzes the given TypeScript project and returns serializable compilation unit data. */
7860
abstract analyze(info: PreparationInfo): Promise<Serializable<UnitAnalysisMetadata>>;
7961

@@ -104,11 +86,9 @@ export abstract class TsurgeFunnelMigration<
10486
export abstract class TsurgeComplexMigration<
10587
UnitAnalysisMetadata,
10688
CombinedGlobalMetadata,
107-
TsProgramType extends ts.Program | NgtscProgram = NgtscProgram,
108-
PreparationInfo = ProgramInfo<TsProgramType>,
109-
> extends TsurgeBaseMigration<TsProgramType, PreparationInfo> {
89+
> extends TsurgeBaseMigration {
11090
/** Analyzes the given TypeScript project and returns serializable compilation unit data. */
111-
abstract analyze(info: PreparationInfo): Promise<Serializable<UnitAnalysisMetadata>>;
91+
abstract analyze(info: ProgramInfo): Promise<Serializable<UnitAnalysisMetadata>>;
11292

11393
/** Merges all compilation unit data from previous analysis phases into a global result. */
11494
abstract merge(units: UnitAnalysisMetadata[]): Promise<Serializable<CombinedGlobalMetadata>>;
@@ -122,6 +102,6 @@ export abstract class TsurgeComplexMigration<
122102
*/
123103
abstract migrate(
124104
globalMetadata: CombinedGlobalMetadata,
125-
info: PreparationInfo,
105+
info: ProgramInfo,
126106
): Promise<Replacement[]>;
127107
}

packages/core/schematics/utils/tsurge/program_info.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@ import {NgtscProgram} from '../../../../compiler-cli/src/ngtsc/program';
1010
import {NgCompilerOptions} from '../../../../compiler-cli/src/ngtsc/core/api';
1111

1212
import ts from 'typescript';
13+
import {NgCompiler} from '../../../../compiler-cli/src/ngtsc/core';
1314

1415
/**
1516
* Base information for a TypeScript project, including an instantiated
1617
* TypeScript program. Base information may be extended by user-overridden
1718
* migration preparation methods to extend the stages with more data.
1819
*/
19-
export interface BaseProgramInfo<T extends NgtscProgram | ts.Program> {
20-
program: T;
20+
export interface BaseProgramInfo {
21+
ngCompiler: NgCompiler | null;
22+
program: ts.Program;
2123
userOptions: NgCompilerOptions;
2224
programAbsoluteRootPaths: string[];
2325
tsconfigAbsolutePath: string;
@@ -30,8 +32,8 @@ export interface BaseProgramInfo<T extends NgtscProgram | ts.Program> {
3032
* A different interface may be used as full program information, configured via a
3133
* {@link TsurgeMigration.prepareProgram} override.
3234
*/
33-
export interface ProgramInfo<T extends NgtscProgram | ts.Program> extends BaseProgramInfo<T> {
35+
export interface ProgramInfo extends BaseProgramInfo {
3436
sourceFiles: ts.SourceFile[];
35-
fullProgramSourceFiles: ts.SourceFile[];
37+
fullProgramSourceFiles: readonly ts.SourceFile[];
3638
projectDirAbsPath: string;
3739
}

packages/core/schematics/utils/tsurge/test/output_helpers.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import path from 'path';
1010
import {UniqueID} from '../helpers/unique_id';
1111
import ts from 'typescript';
1212
import {ProgramInfo} from '../program_info';
13-
import {NgtscProgram} from '../../../../../compiler-cli/src/ngtsc/program';
1413
import {DtsMetadataReader} from '../../../../../compiler-cli/src/ngtsc/metadata';
1514
import {ClassDeclaration, ReflectionHost} from '../../../../../compiler-cli/src/ngtsc/reflection';
1615
import {Reference} from '../../../../../compiler-cli/src/ngtsc/imports';
@@ -24,7 +23,7 @@ export function getIdOfOutput(projectDirAbsPath: string, prop: ts.PropertyDeclar
2423
}
2524

2625
export function findOutputDeclarationsAndReferences(
27-
{sourceFiles, projectDirAbsPath}: ProgramInfo<NgtscProgram>,
26+
{sourceFiles, projectDirAbsPath}: ProgramInfo,
2827
checker: ts.TypeChecker,
2928
reflector: ReflectionHost,
3029
dtsReader: DtsMetadataReader,

0 commit comments

Comments
 (0)