recordChanges()

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.');
      });
    });
  }