// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:io' hide File;

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart'
    show File, ResourceProvider;
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
    hide AnalysisError;
import 'package:args/args.dart';
import 'package:cli_util/cli_logging.dart';
import 'package:dartdev/src/core.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:nnbd_migration/src/exceptions.dart';
import 'package:nnbd_migration/src/front_end/dartfix_listener.dart';
import 'package:nnbd_migration/src/front_end/driver_provider_impl.dart';
import 'package:nnbd_migration/src/front_end/migration_state.dart';
import 'package:nnbd_migration/src/front_end/non_nullable_fix.dart';
import 'package:nnbd_migration/src/messages.dart';
import 'package:nnbd_migration/src/utilities/progress_bar.dart';
import 'package:nnbd_migration/src/utilities/source_edit_diff_formatter.dart';
import 'package:path/path.dart' show Context;

String _pluralize(int count, String single, {String multiple}) {
  return count == 1 ? single : (multiple ?? '${single}s');
}

String _removePeriod(String value) {
  return value.endsWith('.') ? value.substring(0, value.length - 1) : value;
}

/// The result of a round of static analysis; primarily a list of
/// [AnalysisError]s.
class AnalysisResult {
  final List<AnalysisError> errors;
  final Map<String, LineInfo> lineInfo;
  final Context pathContext;
  final String rootDirectory;
  final bool allSourcesAlreadyMigrated;

  AnalysisResult(this.errors, this.lineInfo, this.pathContext,
      this.rootDirectory, this.allSourcesAlreadyMigrated) {
    errors.sort((AnalysisError one, AnalysisError two) {
      if (one.source != two.source) {
        return one.source.fullName.compareTo(two.source.fullName);
      }
      return one.offset - two.offset;
    });
  }

  bool get hasErrors => errors.isNotEmpty;

  /// Whether the errors include any which may be the result of not yet having
  /// run "pub get".
  bool get hasImportErrors => errors.any(
      (error) => error.errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST);

  /// Converts the list of errors into JSON, for displaying in the web preview.
  List<Map<String, dynamic>> toJson() {
    var result = <Map<String, dynamic>>[];
    // severity • Message ... at foo/bar.dart:6:1 • (error_code)
    for (var error in errors) {
      var lineInfoForThisFile = lineInfo[error.source.fullName];
      var location = lineInfoForThisFile.getLocation(error.offset);
      var path =
          pathContext.relative(error.source.fullName, from: rootDirectory);
      result.add({
        'severity': error.severity.name,
        'message': _removePeriod(error.message),
        'location': '$path:${location.lineNumber}:${location.columnNumber}',
        'code': error.errorCode.name.toLowerCase(),
      });
    }
    return result;
  }
}

/// Data structure recording command-line options for the migration tool that
/// have been passed in by the client.
class CommandLineOptions {
  static const applyChangesFlag = 'apply-changes';
  static const helpFlag = 'help';
  static const ignoreErrorsFlag = 'ignore-errors';
  static const ignoreExceptionsFlag = 'ignore-exceptions';
  static const previewHostnameOption = 'preview-hostname';
  static const previewPortOption = 'preview-port';
  static const sdkPathOption = 'sdk-path';
  static const skipImportCheckFlag = 'skip-import-check';
  static const summaryOption = 'summary';
  static const verboseFlag = 'verbose';
  static const webPreviewFlag = 'web-preview';

  final bool applyChanges;

  final String directory;

  final bool ignoreErrors;

  final bool ignoreExceptions;

  final String previewHostname;

  final int previewPort;

  final String sdkPath;

  final bool skipImportCheck;

  final String summary;

  final bool webPreview;

  CommandLineOptions(
      {@required this.applyChanges,
      @required this.directory,
      @required this.ignoreErrors,
      @required this.ignoreExceptions,
      @required this.previewHostname,
      @required this.previewPort,
      @required this.sdkPath,
      @required this.skipImportCheck,
      @required this.summary,
      @required this.webPreview});
}

class MigrateCommand extends DartdevCommand {
  static const String cmdName = 'migrate';

  static const String cmdDescription =
      'Perform null safety migration on a project.';

  static const String migrationGuideLink =
      'See https://dart.dev/go/null-safety-migration for a migration guide.';

  /// Return whether the SDK has null safety on by default.
  static bool get nullSafetyOnByDefault => IsEnabledByDefault.non_nullable;

  final bool verbose;

  MigrateCommand({this.verbose = false})
      : super(cmdName, '$cmdDescription\n\n$migrationGuideLink', verbose) {
    MigrationCli._defineOptions(argParser, !verbose);
  }

  @override
  String get invocation {
    return '${super.invocation} [project or directory]';
  }

  @override
  FutureOr<int> run() async {
    var cli = MigrationCli(binaryName: 'dart $name');
    try {
      await cli.decodeCommandLineArgs(argResults, isVerbose: verbose)?.run();
    } on MigrationExit catch (migrationExit) {
      return migrationExit.exitCode;
    }
    return 0;
  }
}

/// Command-line API for the migration tool, with additional parameters exposed
/// for testing.
///
/// Recommended usage: create an instance of this object and call
/// [decodeCommandLineArgs].  If it returns non-null, call
/// [MigrationCliRunner.run] on the result.  If either method throws a
/// [MigrationExit], exit with the error code contained therein.
class MigrationCli {
  /// A list of all the command-line options supported by the tool.
  ///
  /// This may be used by clients that wish to run migration but provide their
  /// own command-line interface.
  static final List<MigrationCliOption> options = [
    MigrationCliOption(
        CommandLineOptions.verboseFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.verboseFlag,
              abbr: 'v',
              defaultsTo: false,
              help: 'Show additional command output.',
              negatable: false,
            )),
    MigrationCliOption(
        CommandLineOptions.applyChangesFlag,
        (parser, hide) => parser.addFlag(CommandLineOptions.applyChangesFlag,
            defaultsTo: false,
            negatable: false,
            help:
                'Apply the proposed null safety changes to the files on disk.')),
    MigrationCliOption(
        CommandLineOptions.ignoreErrorsFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.ignoreErrorsFlag,
              defaultsTo: false,
              negatable: false,
              help:
                  'Attempt to perform null safety analysis even if the project has '
                  'analysis errors.',
            )),
    MigrationCliOption(
        CommandLineOptions.skipImportCheckFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.skipImportCheckFlag,
              defaultsTo: false,
              negatable: false,
              help: 'Go ahead with migration even if some imported files have '
                  'not yet been migrated.',
            )),
    MigrationCliOption.separator('Web interface options:'),
    MigrationCliOption(
        CommandLineOptions.webPreviewFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.webPreviewFlag,
              defaultsTo: true,
              negatable: true,
              help:
                  'Show an interactive preview of the proposed null safety changes '
                  'in a browser window. Use --no-web-preview to print proposed changes '
                  'to the console.',
            )),
    MigrationCliOption(
        CommandLineOptions.previewHostnameOption,
        (parser, hide) => parser.addOption(
              CommandLineOptions.previewHostnameOption,
              defaultsTo: 'localhost',
              valueHelp: 'host',
              help: 'Run the preview server on the specified hostname. If not '
                  'specified, "localhost" is used. Use "any" to specify IPv6.any or '
                  'IPv4.any.',
            )),
    MigrationCliOption(
        CommandLineOptions.previewPortOption,
        (parser, hide) => parser.addOption(
              CommandLineOptions.previewPortOption,
              valueHelp: 'port',
              help:
                  'Run the preview server on the specified port. If not specified, '
                  'dynamically allocate a port.',
            )),
    MigrationCliOption.separator('Additional options:'),
    MigrationCliOption(
        CommandLineOptions.summaryOption,
        (parser, hide) => parser.addOption(
              CommandLineOptions.summaryOption,
              help: 'Output a machine-readable summary of migration changes.',
              valueHelp: 'path',
            )),
    // hidden options
    MigrationCliOption(
        CommandLineOptions.ignoreExceptionsFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.ignoreExceptionsFlag,
              defaultsTo: false,
              negatable: false,
              help:
                  'Attempt to perform null safety analysis even if exceptions occur.',
              hide: hide,
            )),
    MigrationCliOption(
        CommandLineOptions.sdkPathOption,
        (parser, hide) => parser.addOption(
              CommandLineOptions.sdkPathOption,
              valueHelp: 'sdk-path',
              help: 'The path to the Dart SDK.',
              hide: hide,
            )),
  ];

  /// The name of the executable, for reporting in help messages.
  final String binaryName;

  /// The SDK path that should be used if none is provided by the user.  Used in
  /// testing to install a mock SDK.
  final String defaultSdkPathOverride;

  /// Factory to create an appropriate Logger instance to give feedback to the
  /// user.  Used in testing to allow user feedback messages to be tested.
  final Logger Function(bool isVerbose) loggerFactory;

  /// Resource provider that should be used to access the filesystem.  Used in
  /// testing to redirect to an in-memory filesystem.
  final ResourceProvider resourceProvider;

  /// Logger instance we use to give feedback to the user.
  final Logger logger;

  /// The environment variables, tracked to help users debug if SDK_PATH was
  /// specified and that resulted in any [ExperimentStatusException]s.
  final Map<String, String> _environmentVariables;

  MigrationCli({
    @required this.binaryName,
    @visibleForTesting this.loggerFactory = _defaultLoggerFactory,
    @visibleForTesting this.defaultSdkPathOverride,
    @visibleForTesting ResourceProvider resourceProvider,
    @visibleForTesting Map<String, String> environmentVariables,
  })  : logger = loggerFactory(false),
        resourceProvider =
            resourceProvider ?? PhysicalResourceProvider.INSTANCE,
        _environmentVariables = environmentVariables ?? Platform.environment;

  Context get pathContext => resourceProvider.pathContext;

  /// Parses and validates command-line arguments, and creates a
  /// [MigrationCliRunner] that is prepared to perform migration.
  ///
  /// If the user asked for help, it is printed using the logger configured in
  /// the constructor, and `null` is returned.
  ///
  /// If the user supplied a bad option, a message is printed using the logger
  /// configured in the constructor, and [MigrationExit] is thrown.
  MigrationCliRunner decodeCommandLineArgs(ArgResults argResults,
      {bool isVerbose}) {
    try {
      isVerbose ??= argResults[CommandLineOptions.verboseFlag] as bool;
      if (argResults[CommandLineOptions.helpFlag] as bool) {
        _showUsage(isVerbose);
        return null;
      }
      var rest = argResults.rest;
      String migratePath;
      if (rest.isEmpty) {
        migratePath = pathContext.current;
      } else if (rest.length > 1) {
        throw _BadArgException('No more than one path may be specified.');
      } else {
        migratePath = pathContext
            .normalize(pathContext.join(pathContext.current, rest[0]));
      }
      var migrateResource = resourceProvider.getResource(migratePath);
      if (migrateResource is File) {
        if (migrateResource.exists) {
          throw _BadArgException('$migratePath is a file.');
        } else {
          throw _BadArgException('$migratePath does not exist.');
        }
      }
      var applyChanges =
          argResults[CommandLineOptions.applyChangesFlag] as bool;
      var previewPortRaw =
          argResults[CommandLineOptions.previewPortOption] as String;
      int previewPort;
      try {
        previewPort = previewPortRaw == null ? null : int.parse(previewPortRaw);
      } on FormatException catch (_) {
        throw _BadArgException(
            'Invalid value for --${CommandLineOptions.previewPortOption}');
      }
      bool webPreview;
      if (argResults.wasParsed(CommandLineOptions.webPreviewFlag)) {
        webPreview = argResults[CommandLineOptions.webPreviewFlag] as bool;
      } else {
        // If the `webPreviewFlag` wasn't explicitly passed, then the value of
        // this option is based on the value of the [applyChanges] option.
        webPreview = !applyChanges;
      }
      if (applyChanges && webPreview) {
        throw _BadArgException('--apply-changes requires --no-web-preview');
      }
      var options = CommandLineOptions(
          applyChanges: applyChanges,
          directory: migratePath,
          ignoreErrors: argResults[CommandLineOptions.ignoreErrorsFlag] as bool,
          ignoreExceptions:
              argResults[CommandLineOptions.ignoreExceptionsFlag] as bool,
          previewHostname:
              argResults[CommandLineOptions.previewHostnameOption] as String,
          previewPort: previewPort,
          sdkPath: argResults[CommandLineOptions.sdkPathOption] as String ??
              defaultSdkPathOverride ??
              getSdkPath(),
          skipImportCheck:
              argResults[CommandLineOptions.skipImportCheckFlag] as bool,
          summary: argResults[CommandLineOptions.summaryOption] as String,
          webPreview: webPreview);
      return MigrationCliRunner(this, options,
          logger: isVerbose ? loggerFactory(true) : null);
    } on Object catch (exception) {
      handleArgParsingException(exception);
    }
  }

  @alwaysThrows
  void handleArgParsingException(Object exception) {
    String message;
    if (exception is FormatException) {
      message = exception.message;
    } else if (exception is _BadArgException) {
      message = exception.message;
    } else {
      message =
          'Exception occurred while parsing command-line options: $exception';
    }
    logger.stderr(message);
    _showUsage(false);
    throw MigrationExit(1);
  }

  void _showUsage(bool isVerbose) {
    logger.stderr('Usage: $binaryName [options...] [<project directory>]');

    logger.stderr('');
    logger.stderr(createParser(hide: !isVerbose).usage);
    if (!isVerbose) {
      logger.stderr('');
      logger
          .stderr('Run "$binaryName -h -v" for verbose help output, including '
              'less commonly used options.');
    }
  }

  static ArgParser createParser({bool hide = true}) {
    var parser = ArgParser();
    parser.addFlag(CommandLineOptions.helpFlag,
        abbr: 'h',
        help:
            'Display this help message. Add --verbose to show hidden options.',
        defaultsTo: false,
        negatable: false);
    _defineOptions(parser, hide);
    return parser;
  }

  static Logger _defaultLoggerFactory(bool isVerbose) {
    var ansi = Ansi(Ansi.terminalSupportsAnsi);
    if (isVerbose) {
      return Logger.verbose(ansi: ansi);
    } else {
      return Logger.standard(ansi: ansi);
    }
  }

  static void _defineOptions(ArgParser parser, bool hide) {
    for (var option in options) {
      option.addToParser(parser, hide);
    }
  }
}

/// Data structure representing a single command-line option to the migration
/// tool, or a separator in the list of command-line options.
class MigrationCliOption {
  /// The name of the option, without the leading `--`.
  final String name;

  /// Callback function that can be used to add the option or separator to the
  /// given [parser].  If [hide] is `true`, and the option is rarely used, it
  /// is added as a hidden option.
  final void Function(ArgParser parser, bool hide) addToParser;

  /// If `true`, this is a separator between command line options; if `false`,
  /// it's an option.
  final bool isSeparator;

  MigrationCliOption(this.name, this.addToParser) : isSeparator = false;

  MigrationCliOption.separator(this.name)
      : addToParser = ((parser, hide) => parser.addSeparator(name)),
        isSeparator = true;
}

/// Internals of the command-line API for the migration tool, with additional
/// methods exposed for testing.
///
/// This class may be used directly by clients that with to run migration but
/// provide their own command-line interface.
class MigrationCliRunner implements DartFixListenerClient {
  final MigrationCli cli;

  /// Logger instance we use to give feedback to the user.
  final Logger logger;

  /// The result of parsing command-line options.
  final CommandLineOptions options;

  final Map<String, LineInfo> lineInfo = {};

  DartFixListener _dartFixListener;

  _FixCodeProcessor _fixCodeProcessor;

  AnalysisContextCollectionImpl _contextCollection;

  bool _hasExceptions = false;

  bool _hasAnalysisErrors = false;

  /// Subscription of interrupt signals (control-C).
  StreamSubscription<ProcessSignal> _sigIntSubscription;

  /// Completes when an interrupt signal (control-C) is received.
  Completer<void> sigIntSignalled;

  MigrationCliRunner(this.cli, this.options, {Logger logger})
      : logger = logger ?? cli.logger;

  @visibleForTesting
  DriverBasedAnalysisContext get analysisContext {
    // Handle the case of more than one analysis context being found (typically,
    // the current directory and one or more sub-directories).
    if (hasMultipleAnalysisContext) {
      return contextCollection.contextFor(options.directory);
    } else {
      return contextCollection.contexts.single;
    }
  }

  Ansi get ansi => logger.ansi;

  AnalysisContextCollectionImpl get contextCollection {
    _contextCollection ??= AnalysisContextCollectionImpl(
        includedPaths: [options.directory],
        resourceProvider: resourceProvider,
        sdkPath: pathContext.normalize(options.sdkPath));
    return _contextCollection;
  }

  @visibleForTesting
  bool get hasMultipleAnalysisContext {
    return contextCollection.contexts.length > 1;
  }

  @visibleForTesting
  bool get isPreviewServerRunning =>
      _fixCodeProcessor?.isPreviewServerRunning ?? false;

  Context get pathContext => resourceProvider.pathContext;

  ResourceProvider get resourceProvider => cli.resourceProvider;

  /// Called after changes have been applied on disk.  Maybe overridden by a
  /// derived class.
  void applyHook() {}

  /// Computes the internet address that should be passed to `HttpServer.bind`
  /// when starting the preview server.  May be overridden in derived classes.
  Object computeBindAddress() {
    var hostname = options.previewHostname;
    if (hostname == 'localhost') {
      return InternetAddress.loopbackIPv4;
    } else if (hostname == 'any') {
      return InternetAddress.anyIPv6;
    } else {
      return hostname;
    }
  }

  /// Computes the set of file paths that should be analyzed by the migration
  /// engine.  May be overridden by a derived class.
  ///
  /// All files to be migrated must be included in the returned set.  It is
  /// permissible for the set to contain additional files that could help the
  /// migration tool build up a more complete nullability graph (for example
  /// generated files, or usages of the code-to-be-migrated by one one of its
  /// clients).
  ///
  /// By default returns the set of all `.dart` files contained in the context.
  Set<String> computePathsToProcess(DriverBasedAnalysisContext context) =>
      context.contextRoot
          .analyzedFiles()
          .where((s) =>
              s.endsWith('.dart') &&
              // Any file may have been deleted since its initial analysis.
              resourceProvider.getFile(s).exists)
          .toSet();

  NonNullableFix createNonNullableFix(
      DartFixListener listener,
      ResourceProvider resourceProvider,
      LineInfo Function(String path) getLineInfo,
      Object bindAddress,
      {List<String> included = const <String>[],
      int preferredPort,
      String summaryPath,
      @required String sdkPath}) {
    return NonNullableFix(listener, resourceProvider, getLineInfo, bindAddress,
        logger, (String path) => shouldBeMigrated(path),
        included: included,
        preferredPort: preferredPort,
        summaryPath: summaryPath,
        sdkPath: sdkPath);
  }

  /// Subscribes to the interrupt signal (control-C).
  @visibleForTesting
  void listenForSignalInterrupt() {
    var stream = ProcessSignal.sigint.watch();
    sigIntSignalled = Completer();
    _sigIntSubscription = stream.listen((_) {
      if (!sigIntSignalled.isCompleted) {
        sigIntSignalled.complete();
      }
    });
  }

  @override
  void onException(String detail) {
    if (_hasExceptions) {
      if (!options.ignoreExceptions) {
        // Our intention is to exit immediately when an exception occurred.  We
        // tried, but failed (probably due to permissive mode logic in the
        // migration tool itself catching the MigrationExit exception).  The
        // stack has now been unwound further, so throw again.
        throw MigrationExit(1);
      }
      // We're not exiting immediately when an exception occurs.  We've already
      // reported that an exception happened.  So do nothing further.
      return;
    }
    _hasExceptions = true;
    if (options.ignoreExceptions) {
      logger.stdout('''
Exception(s) occurred during migration.  Attempting to perform
migration anyway due to the use of --${CommandLineOptions.ignoreExceptionsFlag}.

To see exception details, re-run without --${CommandLineOptions.ignoreExceptionsFlag}.
''');
    } else {
      if (_hasAnalysisErrors) {
        logger.stderr('''
Aborting migration due to an exception.  This may be due to a bug in
the migration tool, or it may be due to errors in the source code
being migrated.  If possible, try to fix errors in the source code and
re-try migrating.  If that doesn't work, consider filing a bug report
at:
''');
      } else {
        logger.stderr('''
Aborting migration due to an exception.  This most likely is due to a
bug in the migration tool.  Please consider filing a bug report at:
''');
      }
      logger.stderr('https://github.com/dart-lang/sdk/issues/new');
      var sdkVersion = Platform.version.split(' ')[0];
      logger.stderr('''
Please include the SDK version ($sdkVersion) in your bug report.

To attempt to perform migration anyway, you may re-run with
--${CommandLineOptions.ignoreExceptionsFlag}.

Exception details:
''');
      logger.stderr(detail);
      throw MigrationExit(1);
    }
  }

  @override
  void onFatalError(String detail) {
    logger.stderr(detail);
    throw MigrationExit(1);
  }

  @override
  void onMessage(String detail) {
    logger.stdout(detail);
  }

  /// Runs the full migration process.
  ///
  /// If something goes wrong, a message is printed using the logger configured
  /// in the constructor, and [MigrationExit] is thrown.
  Future<void> run() async {
    logger.stdout('Migrating ${options.directory}');
    logger.stdout('');

    logger.stdout(MigrateCommand.migrationGuideLink);
    logger.stdout('');

    if (hasMultipleAnalysisContext) {
      logger.stdout('Note: more than one project found; migrating the '
          'top-level project.');
      logger.stdout('');
    }

    NonNullableFix nonNullableFix;

    logger.stdout(ansi.emphasized('Analyzing project...'));
    _fixCodeProcessor = _FixCodeProcessor(analysisContext, this);
    _dartFixListener = DartFixListener(
        DriverProviderImpl(resourceProvider, analysisContext), this);
    nonNullableFix = createNonNullableFix(_dartFixListener, resourceProvider,
        _fixCodeProcessor.getLineInfo, computeBindAddress(),
        included: [options.directory],
        preferredPort: options.previewPort,
        summaryPath: options.summary,
        sdkPath: options.sdkPath);
    nonNullableFix.rerunFunction = _rerunFunction;
    _fixCodeProcessor.registerCodeTask(nonNullableFix);

    try {
      var analysisResult = await _fixCodeProcessor.runFirstPhase();

      if (analysisResult.hasErrors) {
        _logErrors(analysisResult);
        if (!options.ignoreErrors) {
          throw MigrationExit(1);
        }
      } else if (analysisResult.allSourcesAlreadyMigrated) {
        _logAlreadyMigrated();
        throw MigrationExit(0);
      } else {
        logger.stdout('No analysis issues found.');
      }
    } on ExperimentStatusException catch (e) {
      logger.stdout(e.toString());
      final sdkPathVar = cli._environmentVariables['SDK_PATH'];
      if (sdkPathVar != null) {
        logger.stdout('$sdkPathEnvironmentVariableSet: $sdkPathVar');
      }
      throw MigrationExit(1);
    }

    logger.stdout('');
    logger.stdout(ansi.emphasized('Generating migration suggestions...'));
    var previewUrls = (await _fixCodeProcessor.runLaterPhases()).previewUrls;

    if (options.applyChanges) {
      logger.stdout(ansi.emphasized('Applying changes:'));

      var allEdits = _dartFixListener.sourceChange.edits;
      _applyMigrationSuggestions(allEdits);

      logger.stdout('');
      logger.stdout(
          'Applied ${allEdits.length} ${_pluralize(allEdits.length, 'edit')}.');

      // Note: do not open the web preview if apply-changes is specified, as we
      // currently cannot tell the web preview to disable the "apply migration"
      // button.
      return;
    }

    if (options.webPreview) {
      assert(previewUrls.length == 1,
          'Got unexpected extra preview URLs from server');

      var url = previewUrls.single;
      // TODO(#41809): Open a browser automatically.
      logger.stdout('''
View the migration suggestions by visiting:

  ${ansi.emphasized(url)}

Use this interactive web view to review, improve, or apply the results.
When finished with the preview, hit ctrl-c to terminate this process.

If you make edits outside of the web view (in your IDE), use the 'Rerun from
sources' action.

''');

      listenForSignalInterrupt();
      await Future.any([
        sigIntSignalled.future,
        nonNullableFix.serverIsShutdown.future,
      ]);
      // Either the interrupt signal was caught, or the server was shutdown.
      // Either way, cancel the interrupt signal subscription, and shutdown the
      // server.
      _sigIntSubscription?.cancel();
      nonNullableFix.shutdownServer();
    } else {
      logger.stdout(ansi.emphasized('Diff of changes:'));

      _displayChangeDiff(_dartFixListener);

      logger.stdout('');
      logger.stdout('To apply these changes, re-run the tool with '
          '--${CommandLineOptions.applyChangesFlag}.');
    }
  }

  /// Determines whether a migrated version of the file at [path] should be
  /// output by the migration too.  May be overridden by a derived class.
  ///
  /// This method should return `false` for files that are being considered by
  /// the migration tool for information only (for example generated files, or
  /// usages of the code-to-be-migrated by one one of its clients).
  ///
  /// By default returns `true` if the file is contained within the context
  /// root.  This means that if a client overrides [computePathsToProcess] to
  /// return additional paths that aren't inside the user's project, but doesn't
  /// override this method, then those additional paths will be analyzed but not
  /// migrated.
  bool shouldBeMigrated(String path) {
    return analysisContext.contextRoot.isAnalyzed(path);
  }

  /// Perform the indicated source edits to the given source, returning the
  /// resulting transformed text.
  String _applyEdits(SourceFileEdit sourceFileEdit, String source) {
    List<SourceEdit> edits = _sortEdits(sourceFileEdit);
    return SourceEdit.applySequence(source, edits);
  }

  void _applyMigrationSuggestions(List<SourceFileEdit> edits) {
    // Apply the changes to disk.
    for (SourceFileEdit sourceFileEdit in edits) {
      String relPath =
          pathContext.relative(sourceFileEdit.file, from: options.directory);
      int count = sourceFileEdit.edits.length;
      logger.stdout('  $relPath ($count ${_pluralize(count, 'change')})');

      String source;
      var file = resourceProvider.getFile(sourceFileEdit.file);
      try {
        source = file.readAsStringSync();
      } catch (_) {}

      if (source == null) {
        logger.stdout('    Unable to retrieve source for file.');
      } else {
        source = _applyEdits(sourceFileEdit, source);

        try {
          file.writeAsStringSync(source);
        } catch (e) {
          logger.stdout('    Unable to write source for file: $e');
        }
      }
    }
    applyHook();
  }

  void _displayChangeDiff(DartFixListener migrationResults) {
    Map<String, List<DartFixSuggestion>> fileSuggestions = {};
    for (DartFixSuggestion suggestion in migrationResults.suggestions) {
      String file = suggestion.location.file;
      fileSuggestions.putIfAbsent(file, () => <DartFixSuggestion>[]);
      fileSuggestions[file].add(suggestion);
    }

    // present a diff-like view
    var diffStyle = DiffStyle(logger.ansi);
    for (SourceFileEdit sourceFileEdit in migrationResults.sourceChange.edits) {
      String file = sourceFileEdit.file;
      String relPath = pathContext.relative(file, from: options.directory);
      var edits = sourceFileEdit.edits;
      int count = edits.length;

      logger.stdout('');
      logger.stdout('${ansi.emphasized(relPath)} '
          '($count ${_pluralize(count, 'change')}):');

      String source;
      try {
        source = resourceProvider.getFile(file).readAsStringSync();
      } catch (_) {}

      if (source == null) {
        logger.stdout('  (unable to retrieve source for file)');
      } else {
        for (var line
            in diffStyle.formatDiff(source, _sourceEditsToAtomicEdits(edits))) {
          logger.stdout('  $line');
        }
      }
    }
  }

  void _logAlreadyMigrated() {
    logger.stdout(migratedAlready);
  }

  void _logErrors(AnalysisResult analysisResult) {
    logger.stdout('');

    var issueCount = analysisResult.errors.length;
    logger.stdout(
        '$issueCount analysis ${_pluralize(issueCount, 'issue')} found:');

    _IssueRenderer renderer =
        _IssueRenderer(logger, options.directory, pathContext, lineInfo);
    for (AnalysisError error in analysisResult.errors) {
      renderer.render(error);
    }
    logger.stdout('');
    _hasAnalysisErrors = true;

    if (options.ignoreErrors) {
      logger.stdout('Note: analysis errors will result in erroneous migration '
          'suggestions.');
      logger.stdout('Continuing with migration suggestions due to the use of '
          '--${CommandLineOptions.ignoreErrorsFlag}.');
    } else {
      // Fail with how to continue.
      logger.stdout("The migration tool didn't start, due to analysis errors.");
      logger.stdout('');
      if (analysisResult.hasImportErrors) {
        logger.stdout('''
The following steps might fix your problem:
1. Run `dart pub get`.
2. Try running `dart migrate` again.
''');
      } else if (analysisResult.allSourcesAlreadyMigrated) {
        logger.stdout('''
The following steps might fix your problem:
1. Set the lower SDK constraint (in pubspec.yaml) to a version before 2.12.
2. Run `dart pub get`.
3. Try running `dart migrate` again.
''');
      } else {
        const ignoreErrors = CommandLineOptions.ignoreErrorsFlag;
        logger.stdout('''
We recommend fixing the analysis issues before running `dart migrate`.
Alternatively, you can run `dart migrate --$ignoreErrors`, but you might
get erroneous migration suggestions.
''');
      }
      logger.stdout(
          'More information: https://dart.dev/go/null-safety-migration');
    }
  }

  Future<MigrationState> _rerunFunction() async {
    logger.stdout(ansi.emphasized('Re-analyzing project...'));

    _dartFixListener.reset();
    _fixCodeProcessor.prepareToRerun();
    var analysisResult = await _fixCodeProcessor.runFirstPhase();
    if (analysisResult.hasErrors && !options.ignoreErrors) {
      _logErrors(analysisResult);
      return MigrationState(
          _fixCodeProcessor._task.migration,
          _fixCodeProcessor._task.includedRoot,
          _dartFixListener,
          _fixCodeProcessor._task.instrumentationListener,
          {},
          _fixCodeProcessor._task.shouldBeMigratedFunction,
          analysisResult);
    } else if (analysisResult.allSourcesAlreadyMigrated) {
      _logAlreadyMigrated();
      return MigrationState(
          _fixCodeProcessor._task.migration,
          _fixCodeProcessor._task.includedRoot,
          _dartFixListener,
          _fixCodeProcessor._task.instrumentationListener,
          {},
          _fixCodeProcessor._task.shouldBeMigratedFunction,
          analysisResult);
    } else {
      logger.stdout(ansi.emphasized('Re-generating migration suggestions...'));
      return await _fixCodeProcessor.runLaterPhases();
    }
  }

  List<SourceEdit> _sortEdits(SourceFileEdit sourceFileEdit) {
    // Sort edits in reverse offset order.
    List<SourceEdit> edits = sourceFileEdit.edits.toList();
    edits.sort((a, b) {
      return b.offset - a.offset;
    });
    return edits;
  }

  static Map<int, List<AtomicEdit>> _sourceEditsToAtomicEdits(
      List<SourceEdit> edits) {
    return {
      for (var edit in edits)
        edit.offset: [AtomicEdit.replace(edit.length, edit.replacement)]
    };
  }
}

/// Exception thrown by [MigrationCli] if the client should exit.
class MigrationExit {
  /// The exit code that the client should set.
  final int exitCode;

  MigrationExit(this.exitCode);
}

/// An abstraction over the static methods on [Process].
///
/// Used in tests to run mock processes.
abstract class ProcessManager {
  const factory ProcessManager.system() = SystemProcessManager;

  /// Run a process synchronously, as in [Process.runSync].
  ProcessResult runSync(String executable, List<String> arguments,
      {String workingDirectory});
}

/// A [ProcessManager] that directs all method calls to static methods of
/// [Process], in order to run real processes.
class SystemProcessManager implements ProcessManager {
  const SystemProcessManager();

  ProcessResult runSync(String executable, List<String> arguments,
          {String workingDirectory}) =>
      Process.runSync(executable, arguments,
          workingDirectory: workingDirectory ?? Directory.current.path);
}

class _BadArgException implements Exception {
  final String message;

  _BadArgException(this.message);
}

class _FixCodeProcessor extends Object {
  static const numPhases = 3;

  final DriverBasedAnalysisContext context;

  /// The task used to migrate to NNBD.
  NonNullableFix _task;

  Set<String> pathsToProcess;

  ProgressBar _progressBar;

  final MigrationCliRunner _migrationCli;

  _FixCodeProcessor(this.context, this._migrationCli)
      : pathsToProcess = _migrationCli.computePathsToProcess(context);

  bool get isPreviewServerRunning => _task?.isPreviewServerRunning ?? false;

  LineInfo getLineInfo(String path) =>
      (context.currentSession.getFile2(path) as FileResult).lineInfo;

  void prepareToRerun() {
    var driver = context.driver;
    pathsToProcess = _migrationCli.computePathsToProcess(context);
    pathsToProcess.forEach(driver.changeFile);
  }

  /// Call the supplied [process] function to process each compilation unit.
  Future<void> processResources(
      Future<void> Function(ResolvedUnitResult result) process) async {
    var driver = context.currentSession;
    var pathsProcessed = <String>{};
    for (var path in pathsToProcess) {
      if (pathsProcessed.contains(path)) continue;
      var result = await driver.getResolvedLibrary2(path);
      // Parts will either be found in a library, below, or if the library
      // isn't [isIncluded], will be picked up in the final loop.
      if (result is ResolvedLibraryResult) {
        for (var unit in result.units) {
          if (!pathsProcessed.contains(unit.path)) {
            await process(unit);
            pathsProcessed.add(unit.path);
          }
        }
      }
    }

    for (var path in pathsToProcess.difference(pathsProcessed)) {
      var result = await driver.getResolvedUnit2(path);
      if (result is ResolvedUnitResult) {
        await process(result);
      }
    }
  }

  void registerCodeTask(NonNullableFix task) {
    _task = task;
  }

  Future<AnalysisResult> runFirstPhase() async {
    var analysisErrors = <AnalysisError>[];

    // All tasks should be registered; [numPhases] should be finalized.
    _progressBar = ProgressBar(_migrationCli.logger, pathsToProcess.length);

    // Process each source file.
    bool allSourcesAlreadyMigrated = true;
    await processResources((ResolvedUnitResult result) async {
      if (!result.unit.featureSet.isEnabled(Feature.non_nullable)) {
        allSourcesAlreadyMigrated = false;
      }
      _progressBar.tick();
      List<AnalysisError> errors = result.errors
          .where((error) => error.severity == Severity.error)
          .toList();
      if (errors.isNotEmpty) {
        analysisErrors.addAll(errors);
        _migrationCli.lineInfo[result.path] = result.lineInfo;
      }
      if (_migrationCli.options.ignoreErrors || analysisErrors.isEmpty) {
        await _task.prepareUnit(result);
      }
    });

    var unmigratedDependencies = _task.migration.unmigratedDependencies;
    if (unmigratedDependencies.isNotEmpty) {
      if (_migrationCli.options.skipImportCheck) {
        _migrationCli.logger.stdout(unmigratedDependenciesWarning);
      } else {
        throw ExperimentStatusException.unmigratedDependencies(
            unmigratedDependencies);
      }
    }

    return AnalysisResult(
        analysisErrors,
        _migrationCli.lineInfo,
        _migrationCli.pathContext,
        _migrationCli.options.directory,
        allSourcesAlreadyMigrated);
  }

  Future<MigrationState> runLaterPhases() async {
    _progressBar = ProgressBar(
        _migrationCli.logger, pathsToProcess.length * (numPhases - 1));

    await processResources((ResolvedUnitResult result) async {
      _progressBar.tick();
      await _task.processUnit(result);
    });
    await processResources((ResolvedUnitResult result) async {
      _progressBar.tick();
      if (_migrationCli.shouldBeMigrated(result.path)) {
        await _task.finalizeUnit(result);
      }
    });
    _progressBar.complete();
    _migrationCli.logger.stdout(_migrationCli.ansi
        .emphasized('Compiling instrumentation information...'));
    // Update the tasks paths-to-process, in case of new or deleted files.
    _task.pathsToProcess = pathsToProcess;
    var state = await _task.finish();
    _task.processPackage(context.contextRoot.root, state.neededPackages);
    if (_migrationCli.options.webPreview) {
      await _task.startPreviewServer(state, _migrationCli.applyHook);
    }
    state.previewUrls = _task.previewUrls;

    return state;
  }
}

/// Given a Logger and an analysis issue, render the issue to the logger.
class _IssueRenderer {
  final Logger logger;
  final String rootDirectory;
  final Context pathContext;
  final Map<String, LineInfo> lineInfo;

  _IssueRenderer(
      this.logger, this.rootDirectory, this.pathContext, this.lineInfo);

  void render(AnalysisError issue) {
    // severity • Message ... at foo/bar.dart:6:1 • (error_code)
    var lineInfoForThisFile = lineInfo[issue.source.fullName];
    var location = lineInfoForThisFile.getLocation(issue.offset);

    final Ansi ansi = logger.ansi;

    logger.stdout(
      '  ${ansi.error(issue.severity.name)} • '
      '${ansi.emphasized(_removePeriod(issue.message))} '
      'at ${pathContext.relative(issue.source.fullName, from: rootDirectory)}'
      ':${location.lineNumber}:${location.columnNumber} '
      '• (${issue.errorCode.name.toLowerCase()})',
    );
  }
}

extension on Severity {
  /// Returns the simple name of the Severity, as a String.
  String get name {
    switch (this) {
      case Severity.error:
        return 'error';
      case Severity.warning:
        return 'warning';
      case Severity.info:
        return 'info';
    }
    return '???';
  }
}
