mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(migrations): optimize some of the import utilities (#57179)
Makes a few optimizations in the utilities we use for dealing with imports in migrations. I didn't end up using these in the inject migration, but they should still come in handy. Includes: 1. Exiting `isReferenceToImport` early when the node being checked is an identifier and it doesn't match the identifier of the import. This saves us some type checker calls. 2. Adds the ability to pass a single string to `getImportSpecifiers`. This saves us unnecessary arrays and for loops. PR Close #57179
This commit is contained in:
parent
2ffa417665
commit
7a40234fb7
2 changed files with 33 additions and 14 deletions
|
|
@ -67,28 +67,40 @@ export function getImportSpecifier(
|
|||
moduleName: string | RegExp,
|
||||
specifierName: string,
|
||||
): ts.ImportSpecifier | null {
|
||||
return getImportSpecifiers(sourceFile, moduleName, [specifierName])[0] ?? null;
|
||||
return getImportSpecifiers(sourceFile, moduleName, specifierName)[0] ?? null;
|
||||
}
|
||||
|
||||
export function getImportSpecifiers(
|
||||
sourceFile: ts.SourceFile,
|
||||
moduleName: string | RegExp,
|
||||
specifierNames: string[],
|
||||
specifierOrSpecifiers: string | string[],
|
||||
): ts.ImportSpecifier[] {
|
||||
const matches: ts.ImportSpecifier[] = [];
|
||||
for (const node of sourceFile.statements) {
|
||||
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
||||
const isMatch =
|
||||
typeof moduleName === 'string'
|
||||
? node.moduleSpecifier.text === moduleName
|
||||
: moduleName.test(node.moduleSpecifier.text);
|
||||
const namedBindings = node.importClause?.namedBindings;
|
||||
if (isMatch && namedBindings && ts.isNamedImports(namedBindings)) {
|
||||
for (const specifierName of specifierNames) {
|
||||
const match = findImportSpecifier(namedBindings.elements, specifierName);
|
||||
if (match) {
|
||||
matches.push(match);
|
||||
}
|
||||
if (!ts.isImportDeclaration(node) || !ts.isStringLiteral(node.moduleSpecifier)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const namedBindings = node.importClause?.namedBindings;
|
||||
const isMatch =
|
||||
typeof moduleName === 'string'
|
||||
? node.moduleSpecifier.text === moduleName
|
||||
: moduleName.test(node.moduleSpecifier.text);
|
||||
|
||||
if (!isMatch || !namedBindings || !ts.isNamedImports(namedBindings)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof specifierOrSpecifiers === 'string') {
|
||||
const match = findImportSpecifier(namedBindings.elements, specifierOrSpecifiers);
|
||||
if (match) {
|
||||
matches.push(match);
|
||||
}
|
||||
} else {
|
||||
for (const specifierName of specifierOrSpecifiers) {
|
||||
const match = findImportSpecifier(namedBindings.elements, specifierName);
|
||||
if (match) {
|
||||
matches.push(match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,13 @@ export function isReferenceToImport(
|
|||
node: ts.Node,
|
||||
importSpecifier: ts.ImportSpecifier,
|
||||
): boolean {
|
||||
// If this function is called on an identifier (should be most cases), we can quickly rule out
|
||||
// non-matches by comparing the identifier's string and the local name of the import specifier
|
||||
// which saves us some calls to the type checker.
|
||||
if (ts.isIdentifier(node) && node.text !== importSpecifier.name.text) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nodeSymbol = typeChecker.getTypeAtLocation(node).getSymbol();
|
||||
const importSymbol = typeChecker.getTypeAtLocation(importSpecifier).getSymbol();
|
||||
return (
|
||||
|
|
|
|||
Loading…
Reference in a new issue