in src/material/schematics/ng-update/migrations/hammer-gestures-v9/import-manager.ts [325:407]
recordChanges() {
this._importCache.forEach((fileImports, sourceFile) => {
const recorder = this._fileSystem.edit(this._fileSystem.resolve(sourceFile.fileName));
const lastUnmodifiedImport = fileImports
.reverse()
.find(i => i.state === ImportState.UNMODIFIED);
const importStartIndex = lastUnmodifiedImport
? this._getEndPositionOfNode(lastUnmodifiedImport.node)
: 0;
fileImports.forEach(importData => {
if (importData.state === ImportState.UNMODIFIED) {
return;
}
if (hasFlag(importData, ImportState.DELETED)) {
// Imports which do not exist in source file, can be just skipped as
// we do not need any replacement to delete the import.
if (!hasFlag(importData, ImportState.ADDED)) {
recorder.remove(importData.node.getFullStart(), importData.node.getFullWidth());
}
return;
}
if (importData.specifiers) {
const namedBindings = importData.node.importClause!.namedBindings as ts.NamedImports;
const importSpecifiers = importData.specifiers.map(s =>
createImportSpecifier(s.propertyName, s.name),
);
const updatedBindings = ts.updateNamedImports(namedBindings, importSpecifiers);
// In case an import has been added newly, we need to print the whole import
// declaration and insert it at the import start index. Otherwise, we just
// update the named bindings to not re-print the whole import (which could
// cause unnecessary formatting changes)
if (hasFlag(importData, ImportState.ADDED)) {
const updatedImport = ts.updateImportDeclaration(
importData.node,
undefined,
undefined,
ts.createImportClause(undefined, updatedBindings),
ts.createStringLiteral(importData.moduleName),
undefined,
);
const newImportText = this._printer.printNode(
ts.EmitHint.Unspecified,
updatedImport,
sourceFile,
);
recorder.insertLeft(
importStartIndex,
importStartIndex === 0 ? `${newImportText}\n` : `\n${newImportText}`,
);
return;
} else if (hasFlag(importData, ImportState.MODIFIED)) {
const newNamedBindingsText = this._printer.printNode(
ts.EmitHint.Unspecified,
updatedBindings,
sourceFile,
);
recorder.remove(namedBindings.getStart(), namedBindings.getWidth());
recorder.insertRight(namedBindings.getStart(), newNamedBindingsText);
return;
}
} else if (hasFlag(importData, ImportState.ADDED)) {
const newImportText = this._printer.printNode(
ts.EmitHint.Unspecified,
importData.node,
sourceFile,
);
recorder.insertLeft(
importStartIndex,
importStartIndex === 0 ? `${newImportText}\n` : `\n${newImportText}`,
);
return;
}
// we should never hit this, but we rather want to print a custom exception
// instead of just skipping imports silently.
throw Error('Unexpected import modification.');
});
});
}