refactor(migrations): improve generic assignability in tsurge and pass more info (#57451)

* Improves some of the generic assignability for tsurge. Anything is
  allowed to be returned from an overridden `prepareProgram` method.
  This is useful for the signal input migration.
* Passes the absolute root paths to migrations. This is helpful for the
  signal input migration and there is no other way to access it. It's
  better to pass specifically, compared to passing the whole unsafe
  `ParsedConfiguration` object.

PR Close #57451
This commit is contained in:
Paul Gschwendtner 2024-08-19 14:47:25 +00:00 committed by Dylan Hunn
parent 3afce0f8c2
commit d3c01efef3
7 changed files with 32 additions and 12 deletions

View file

@ -4,7 +4,7 @@ ts_library(
name = "tsurge",
srcs = glob(["**/*.ts"]),
visibility = [
"//packages/core/schematics/utils/tsurge/test:__pkg__",
"//packages/core/schematics:__subpackages__",
],
deps = [
"//packages/compiler-cli",

View file

@ -8,6 +8,8 @@
import {TsurgeMigration} from '../migration';
import {Serializable} from '../helpers/serializable';
import ts from 'typescript';
import {NgtscProgram} from '../../../../../compiler-cli/src/ngtsc/program';
/**
* Executes the analyze phase of the given migration against
@ -15,8 +17,12 @@ import {Serializable} from '../helpers/serializable';
*
* @returns the serializable migration unit data.
*/
export async function executeAnalyzePhase<UnitData, GlobalData>(
migration: TsurgeMigration<UnitData, GlobalData>,
export async function executeAnalyzePhase<
UnitData,
GlobalData,
TsProgramType extends ts.Program | NgtscProgram,
>(
migration: TsurgeMigration<UnitData, GlobalData, TsProgramType, unknown>,
tsconfigAbsolutePath: string,
): Promise<Serializable<UnitData>> {
const baseInfo = migration.createProgram(tsconfigAbsolutePath);

View file

@ -6,8 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
import ts from 'typescript';
import {Serializable} from '../helpers/serializable';
import {TsurgeMigration} from '../migration';
import {NgtscProgram} from '../../../../../compiler-cli/src/ngtsc/program';
/**
* Executes the merge phase for the given migration against
@ -15,8 +17,12 @@ import {TsurgeMigration} from '../migration';
*
* @returns the serializable migration global data.
*/
export async function executeMergePhase<UnitData, GlobalData>(
migration: TsurgeMigration<UnitData, GlobalData>,
export async function executeMergePhase<
UnitData,
GlobalData,
TsProgramType extends ts.Program | NgtscProgram,
>(
migration: TsurgeMigration<UnitData, GlobalData, TsProgramType, unknown>,
units: UnitData[],
): Promise<Serializable<GlobalData>> {
return await migration.merge(units);

View file

@ -8,6 +8,8 @@
import {TsurgeMigration} from '../migration';
import {Replacement} from '../replacement';
import {NgtscProgram} from '../../../../../compiler-cli/src/ngtsc/program';
import ts from 'typescript';
/**
* Executes the migrate phase of the given migration against
@ -18,8 +20,12 @@ import {Replacement} from '../replacement';
*
* @returns a list of text replacements to apply to disk.
*/
export async function executeMigratePhase<UnitData, GlobalData>(
migration: TsurgeMigration<UnitData, GlobalData>,
export async function executeMigratePhase<
UnitData,
GlobalData,
TsProgramType extends ts.Program | NgtscProgram,
>(
migration: TsurgeMigration<UnitData, GlobalData, TsProgramType, unknown>,
globalMetadata: GlobalData,
tsconfigAbsolutePath: string,
): Promise<Replacement[]> {

View file

@ -59,6 +59,7 @@ export function createNgtscProgram(
return {
program: ngtscProgram,
userOptions: tsconfig.options,
programAbsoluteRootPaths: tsconfig.rootNames,
tsconfigAbsolutePath: absoluteTsconfigPath,
};
}

View file

@ -48,7 +48,7 @@ export abstract class TsurgeMigration<
UnitAnalysisMetadata,
CombinedGlobalMetadata,
TsProgramType extends ts.Program | NgtscProgram = NgtscProgram,
FullProgramInfo extends ProgramInfo<TsProgramType> = ProgramInfo<TsProgramType>,
PreparationInfo = ProgramInfo<TsProgramType>,
> {
// By default, ngtsc programs are being created.
createProgram(tsconfigAbsPath: string, fs?: FileSystem): BaseProgramInfo<TsProgramType> {
@ -57,7 +57,7 @@ export abstract class TsurgeMigration<
// Optional function to prepare the base `ProgramInfo` even further,
// for the analyze and migrate phases. E.g. determining source files.
prepareProgram(info: BaseProgramInfo<TsProgramType>): FullProgramInfo {
prepareProgram(info: BaseProgramInfo<TsProgramType>): PreparationInfo {
assert(info.program instanceof NgtscProgram);
const userProgram = info.program.getTsProgram();
@ -78,11 +78,11 @@ export abstract class TsurgeMigration<
sourceFiles,
fullProgramSourceFiles,
projectDirAbsPath,
} as FullProgramInfo;
} as PreparationInfo;
}
/** Analyzes the given TypeScript project and returns serializable compilation unit data. */
abstract analyze(program: FullProgramInfo): Promise<Serializable<UnitAnalysisMetadata>>;
abstract analyze(program: PreparationInfo): Promise<Serializable<UnitAnalysisMetadata>>;
/** Merges all compilation unit data from previous analysis phases into a global metadata. */
abstract merge(units: UnitAnalysisMetadata[]): Promise<Serializable<CombinedGlobalMetadata>>;
@ -93,6 +93,6 @@ export abstract class TsurgeMigration<
*/
abstract migrate(
globalMetadata: CombinedGlobalMetadata,
program: FullProgramInfo,
program: PreparationInfo,
): Promise<Replacement[]>;
}

View file

@ -19,6 +19,7 @@ import ts from 'typescript';
export interface BaseProgramInfo<T extends NgtscProgram | ts.Program> {
program: T;
userOptions: NgCompilerOptions;
programAbsoluteRootPaths: string[];
tsconfigAbsolutePath: string;
}