refactor(migrations): add API to remap generated import names (#48974)

Internally we'll need to remap some imports to generate better import statements. These changes add an API that we can use to do the remapping.

PR Close #48974
This commit is contained in:
Kristiyan Kostadinov
2023-02-06 17:15:43 +01:00
committed by Andrew Scott
parent 4f6127aa34
commit a47721c2f1
4 changed files with 17 additions and 11 deletions
@@ -12,7 +12,7 @@ import ts from 'typescript';
import {getAngularDecorators, NgDecorator} from '../../utils/ng_decorators';
import {closestNode} from '../../utils/typescript/nodes';
import {ChangeTracker, createLanguageService, findClassDeclaration, findLiteralProperty, getNodeLookup, offsetsToNodes, UniqueItemTracker} from './util';
import {ChangeTracker, createLanguageService, findClassDeclaration, findLiteralProperty, getNodeLookup, ImportRemapper, offsetsToNodes, UniqueItemTracker} from './util';
/** Mapping between a file name and spans for node references inside of it. */
type ReferencesByFile = Map<string, [start: number, end: number][]>;
@@ -28,9 +28,9 @@ interface RemovalLocations {
export function pruneNgModules(
program: NgtscProgram, host: ts.CompilerHost, basePath: string, rootFileNames: string[],
sourceFiles: ts.SourceFile[], printer: ts.Printer) {
sourceFiles: ts.SourceFile[], printer: ts.Printer, importRemapper?: ImportRemapper) {
const filesToRemove = new Set<ts.SourceFile>();
const tracker = new ChangeTracker(printer);
const tracker = new ChangeTracker(printer, importRemapper);
const typeChecker = program.getTsProgram().getTypeChecker();
const languageService = createLanguageService(program, host, rootFileNames, basePath);
const removalLocations: RemovalLocations = {
@@ -16,7 +16,7 @@ import {getAngularDecorators} from '../../utils/ng_decorators';
import {closestNode} from '../../utils/typescript/nodes';
import {convertNgModuleDeclarationToStandalone} from './to-standalone';
import {ChangeTracker, createLanguageService, findClassDeclaration, findLiteralProperty, getNodeLookup, getRelativeImportPath, NamedClassDeclaration, NodeLookup, offsetsToNodes, UniqueItemTracker} from './util';
import {ChangeTracker, createLanguageService, findClassDeclaration, findLiteralProperty, getNodeLookup, getRelativeImportPath, ImportRemapper, NamedClassDeclaration, NodeLookup, offsetsToNodes, UniqueItemTracker} from './util';
/** Information extracted from a `bootstrapModule` call necessary to migrate it. */
interface BootstrapCallAnalysis {
@@ -32,8 +32,8 @@ interface BootstrapCallAnalysis {
export function toStandaloneBootstrap(
program: NgtscProgram, host: ts.CompilerHost, basePath: string, rootFileNames: string[],
sourceFiles: ts.SourceFile[], printer: ts.Printer) {
const tracker = new ChangeTracker(printer);
sourceFiles: ts.SourceFile[], printer: ts.Printer, importRemapper?: ImportRemapper) {
const tracker = new ChangeTracker(printer, importRemapper);
const typeChecker = program.getTsProgram().getTypeChecker();
const templateTypeChecker = program.compiler.getTemplateTypeChecker();
const languageService = createLanguageService(program, host, rootFileNames, basePath);
@@ -15,7 +15,7 @@ import {getImportSpecifier} from '../../utils/typescript/imports';
import {closestNode} from '../../utils/typescript/nodes';
import {isReferenceToImport} from '../../utils/typescript/symbol';
import {ChangesByFile, ChangeTracker, findClassDeclaration, findLiteralProperty, NamedClassDeclaration} from './util';
import {ChangesByFile, ChangeTracker, findClassDeclaration, findLiteralProperty, ImportRemapper, NamedClassDeclaration} from './util';
/**
* Converts all declarations in the specified files to standalone.
@@ -24,13 +24,14 @@ import {ChangesByFile, ChangeTracker, findClassDeclaration, findLiteralProperty,
* @param printer
*/
export function toStandalone(
sourceFiles: ts.SourceFile[], program: NgtscProgram, printer: ts.Printer): ChangesByFile {
sourceFiles: ts.SourceFile[], program: NgtscProgram, printer: ts.Printer,
importRemapper?: ImportRemapper): ChangesByFile {
const templateTypeChecker = program.compiler.getTemplateTypeChecker();
const typeChecker = program.getTsProgram().getTypeChecker();
const modulesToMigrate: ts.ClassDeclaration[] = [];
const testObjectsToMigrate: ts.ObjectLiteralExpression[] = [];
const declarations: Reference<ts.ClassDeclaration>[] = [];
const tracker = new ChangeTracker(printer);
const tracker = new ChangeTracker(printer, importRemapper);
for (const sourceFile of sourceFiles) {
const {modules, testObjects} = findModulesToMigrate(sourceFile, typeChecker);
@@ -21,6 +21,9 @@ export type NodeLookup = Map<number, ts.Node[]>;
/** Utility to type a class declaration with a name. */
export type NamedClassDeclaration = ts.ClassDeclaration&{name: ts.Identifier};
/** Function that can be used to remap a generated import. */
export type ImportRemapper = (moduleName: string) => string;
/** Change that needs to be applied to a file. */
interface PendingChange {
/** Index at which to start changing the file. */
@@ -45,7 +48,7 @@ export class ChangeTracker {
}),
this._printer);
constructor(private _printer: ts.Printer) {}
constructor(private _printer: ts.Printer, private _importRemapper?: ImportRemapper) {}
/**
* Tracks the insertion of some text.
@@ -104,7 +107,9 @@ export class ChangeTracker {
addImport(
sourceFile: ts.SourceFile, symbolName: string, moduleName: string,
alias: string|null = null): ts.Expression {
return this._importManager.addImportToSourceFile(sourceFile, symbolName, moduleName, alias);
return this._importManager.addImportToSourceFile(
sourceFile, symbolName,
this._importRemapper ? this._importRemapper(moduleName) : moduleName, alias);
}
/**