// 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:convert' show jsonDecode;
import 'dart:io' hide File;

import 'package:analyzer/dart/analysis/analysis_context_collection.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:args/command_runner.dart';
import 'package:cli_util/cli_logging.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/json.dart' as json;
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;

  AnalysisResult(
      this.errors, this.lineInfo, this.pathContext, this.rootDirectory) {
    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 skipPubOutdatedFlag = 'skip-pub-outdated';
  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 skipPubOutdated;

  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.skipPubOutdated,
      @required this.summary,
      @required this.webPreview});
}

@visibleForTesting
class DependencyChecker {
  /// The directory which contains the package being migrated.
  final String _directory;
  final Context _pathContext;
  final Logger _logger;
  final ProcessManager _processManager;

  DependencyChecker(
      this._directory, this._pathContext, this._logger, this._processManager);

  bool check() {
    var pubPath = _pathContext.join(getSdkPath(), 'bin', 'dart');
    var pubArguments = ['pub', 'outdated', '--mode=null-safety', '--json'];
    var preNullSafetyPackages = <String, String>{};
    try {
      var result = _processManager.runSync(pubPath, pubArguments,
          workingDirectory: _directory);
      if ((result.stderr as String).isNotEmpty) {
        throw FormatException(
            '`dart pub outdated --mode=null-safety` exited with exit code '
            '${result.exitCode} and stderr:\n\n${result.stderr}');
      }
      var outdatedOutput = jsonDecode(result.stdout as String);
      var outdatedMap = json.expectType<Map>(outdatedOutput, 'root');
      var packageList =
          json.expectType<List>(outdatedMap['packages'], 'packages');
      for (var package_ in packageList) {
        var package = json.expectType<Map>(package_, '');
        var current_ = json.expectKey(package, 'current');
        if (current_ == null) {
          continue;
        }
        var current = json.expectType<Map>(current_, 'current');
        if (json.expectType<bool>(current['nullSafety'], 'nullSafety')) {
          // For whatever reason, there is no "current" version of this package.
          // TODO(srawlins): We may want to report this to the user. But it may
          // be inconsequential.
          continue;
        }

        json.expectKey(package, 'package');
        json.expectKey(current, 'version');
        var name = json.expectType<String>(package['package'], 'package');
        // A version will be given, even if a package was provided with a local
        // or git path.
        var version = json.expectType<String>(current['version'], 'version');
        preNullSafetyPackages[name] = version;
      }
    } on ProcessException catch (e) {
      _logger.stderr(
          'Warning: Could not execute `$pubPath ${pubArguments.join(' ')}`: '
          '"${e.message}"');
      // Allow the program to continue; users should be allowed to attempt to
      // migrate when `pub outdated` is misbehaving, or if there is a bug above.
    } on FormatException catch (e) {
      _logger.stderr('Warning: ${e.message}');
      // Allow the program to continue; users should be allowed to attempt to
      // migrate when `pub outdated` is misbehaving, or if there is a bug above.
    }
    if (preNullSafetyPackages.isNotEmpty) {
      _logger.stderr('Warning: not all current dependencies have migrated to '
          'null safety:');
      _logger.stderr('');
      for (var package in preNullSafetyPackages.entries) {
        _logger.stderr(
            '  package:${package.key} (currently at version ${package.value})');
      }
      _logger.stderr('');
      _logger.stderr('For the best migration experience, please update to null '
          'safe versions of these packages before migrating your code. You can '
          'use \'dart pub outdated --mode=null-safety\' to check the status of '
          'dependencies.');
      _logger.stderr('');
      _logger.stderr('Visit https://dart.dev/tools/pub/cmd/pub-outdated for '
          'more information.');
      return false;
    }
    return true;
  }
}

// TODO(devoncarew): Refactor so this class extends DartdevCommand.
class MigrateCommand extends Command<dynamic> {
  static const String cmdName = 'migrate';

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

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

  static const String preFlagFlipCaveat =
      'Note: this tool is currently running on an SDK version where null '
      'safety is not yet enabled by default. You may encounter issues in the '
      'migration process - some aspects of the toolchain assume that they are '
      'running on an SDK where null safety has been enabled by default.';

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

  final bool verbose;

  @override
  final bool hidden;

  ArgParser _argParser;

  MigrateCommand({this.verbose = false, this.hidden = false}) {
    MigrationCli._defineOptions(argParser, !verbose);
  }

  @override
  ArgParser get argParser {
    // We override this in order to configure the help text line wrapping.
    return _argParser ??= ArgParser(
      usageLineLength: stdout.hasTerminal ? stdout.terminalColumns : null,
    );
  }

  @override
  String get description => nullSafetyOnByDefault
      ? '$cmdDescription\n\n$migrationGuideLink'
      : '$cmdDescription\n\n$preFlagFlipCaveat\n\n$migrationGuideLink';

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

  @override
  String get name => cmdName;

  @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 package has '
                  'analysis errors.',
            )),
    MigrationCliOption(
        CommandLineOptions.skipPubOutdatedFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.skipPubOutdatedFlag,
              // TODO(srawlins): Before "beta," change the default to "false," and
              // negatable to "false." See
              // https://github.com/dart-lang/sdk/issues/43774.
              defaultsTo: true,
              negatable: true,
              help:
                  'Skip the `pub outdated --mode=null-safety` check. This allows a '
                  'migration to proceed even if some package dependencies 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;

  /// Process manager that should be used to run processes. Used in testing to
  /// redirect to mock processes.
  @visibleForTesting
  final ProcessManager processManager;

  /// 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 this.processManager = const ProcessManager.system(),
    @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}');
      }
      var webPreview = argResults[CommandLineOptions.webPreviewFlag] as bool;
      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(),
          skipPubOutdated:
              argResults[CommandLineOptions.skipPubOutdatedFlag] 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...] [<package 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 {
  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;

  AnalysisContextCollection _contextCollection;

  bool _hasExceptions = false;

  bool _hasAnalysisErrors = false;

  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)
          as DriverBasedAnalysisContext;
    } else {
      return contextCollection.contexts.single as DriverBasedAnalysisContext;
    }
  }

  Ansi get ansi => logger.ansi;

  AnalysisContextCollection 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?.isPreviewServerRunnning ?? 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() {}

  /// Blocks until an interrupt signal (control-C) is received.  Tests may
  /// override this method to simulate control-C.
  @visibleForTesting
  Future<void> blockUntilSignalInterrupt() {
    Stream<ProcessSignal> stream = ProcessSignal.sigint.watch();
    return stream.first;
  }

  /// 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'))
          .toSet();

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

  /// 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 {
    if (!options.skipPubOutdated) {
      _checkDependencies();
    }

    logger.stdout('Migrating ${options.directory}');
    logger.stdout('');

    if (!MigrateCommand.nullSafetyOnByDefault) {
      logger.stdout(MigrateCommand.preFlagFlipCaveat);
      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('');
    }

    DriverBasedAnalysisContext context = analysisContext;

    NonNullableFix nonNullableFix;

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

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

      if (analysisResult.hasErrors) {
        _logErrors(analysisResult);
        if (!options.ignoreErrors) {
          throw MigrationExit(1);
        }
      } 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.

''');

      // Block until sigint (ctrl-c).
      await blockUntilSignalInterrupt();
      nonNullableFix.shutdownServer();
    } else {
      logger.stdout(ansi.emphasized('Summary of changes:'));

      _displayChangeSummary(_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(DriverBasedAnalysisContext context, String path) {
    return context.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 _checkDependencies() {
    var successful = DependencyChecker(
            options.directory, pathContext, logger, cli.processManager)
        .check();
    if (!successful) {
      throw MigrationExit(1);
    }
  }

  void _displayChangeSummary(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 _exceptionReported(String detail) {
    if (_hasExceptions) 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');
      logger.stderr('''
To attempt to perform migration anyway, you may re-run with
--${CommandLineOptions.ignoreExceptionsFlag}.

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

  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('');
    logger.stdout('Note: analysis errors will result in erroneous migration '
        'suggestions.');

    _hasAnalysisErrors = true;
    if (options.ignoreErrors) {
      logger.stdout('Continuing with migration suggestions due to the use of '
          '--${CommandLineOptions.ignoreErrorsFlag}.');
    } else {
      // Fail with how to continue.
      logger.stdout('');
      if (analysisResult.hasImportErrors) {
        logger
            .stdout('Unresolved URIs found.  Did you forget to run "pub get"?');
        logger.stdout('');
      }
      logger.stdout(
          'Please fix the analysis issues (or, force generation of migration '
          'suggestions by re-running with '
          '--${CommandLineOptions.ignoreErrorsFlag}).');
    }
  }

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

    _dartFixListener.reset();
    _fixCodeProcessor.prepareToRerun();
    var analysisResult = await _fixCodeProcessor.runFirstPhase();
    if (analysisResult.hasErrors) {
      _logErrors(analysisResult);
      return MigrationState(
          _fixCodeProcessor._task.migration,
          _fixCodeProcessor._task.includedRoot,
          _dartFixListener,
          _fixCodeProcessor._task.instrumentationListener,
          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 isPreviewServerRunnning => _task?.isPreviewServerRunning ?? false;

  LineInfo getLineInfo(String path) =>
      context.currentSession.getFile(path).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;
      switch (await driver.getSourceKind(path)) {
        case SourceKind.PART:
          // Parts will either be found in a library, below, or if the library
          // isn't [isIncluded], will be picked up in the final loop.
          continue;
          break;
        case SourceKind.LIBRARY:
          var result = await driver.getResolvedLibrary(path);
          if (result != null) {
            for (var unit in result.units) {
              if (!pathsProcessed.contains(unit.path)) {
                await process(unit);
                pathsProcessed.add(unit.path);
              }
            }
          }
          break;
        default:
          break;
      }
    }

    for (var path in pathsToProcess.difference(pathsProcessed)) {
      var result = await driver.getResolvedUnit(path);
      if (result == null || result.unit == null) {
        continue;
      }
      await process(result);
    }
  }

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

  Future<AnalysisResult> runFirstPhase() async {
    // All tasks should be registered; [numPhases] should be finalized.
    _progressBar = _ProgressBar(_migrationCli.logger, pathsToProcess.length);

    // Process package
    _task.processPackage(context.contextRoot.root);

    var analysisErrors = <AnalysisError>[];

    // Process each source file.
    await processResources((ResolvedUnitResult result) async {
      _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);
      }
    });

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

  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(context, result.path)) {
        await _task.finalizeUnit(result);
      }
    });
    var state = await _task.finish();
    if (_migrationCli.options.webPreview) {
      await _task.startPreviewServer(state, _migrationCli.applyHook);
    }
    _progressBar.complete();
    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()})',
    );
  }
}

/// A facility for drawing a progress bar in the terminal.
///
/// The bar is instantiated with the total number of "ticks" to be completed,
/// and progress is made by calling [tick]. The bar is drawn across one entire
/// line, like so:
///
///     [----------                                                   ]
///
/// The hyphens represent completed progress, and the whitespace represents
/// remaining progress.
///
/// If there is no terminal, the progress bar will not be drawn.
class _ProgressBar {
  /// Whether the progress bar should be drawn.
  /*late*/ bool _shouldDrawProgress;

  /// The width of the terminal, in terms of characters.
  /*late*/ int _width;

  final Logger _logger;

  /// The inner width of the terminal, in terms of characters.
  ///
  /// This represents the number of characters available for drawing progress.
  /*late*/ int _innerWidth;

  final int _totalTickCount;

  int _tickCount = 0;

  _ProgressBar(this._logger, this._totalTickCount) {
    if (!stdout.hasTerminal) {
      _shouldDrawProgress = false;
    } else {
      _shouldDrawProgress = true;
      _width = stdout.terminalColumns;
      _innerWidth = stdout.terminalColumns - 2;
      _logger.write('[' + ' ' * _innerWidth + ']');
    }
  }

  /// Clear the progress bar from the terminal, allowing other logging to be
  /// printed.
  void clear() {
    if (!_shouldDrawProgress) {
      return;
    }
    _logger.write('\r' + ' ' * _width + '\r');
  }

  /// Draw the progress bar as complete, and print two newlines.
  void complete() {
    if (!_shouldDrawProgress) {
      return;
    }
    _logger.write('\r[' + '-' * _innerWidth + ']\n\n');
  }

  /// Progress the bar by one tick.
  void tick() {
    if (!_shouldDrawProgress) {
      return;
    }
    _tickCount++;
    var fractionComplete = _tickCount * _innerWidth ~/ _totalTickCount - 1;
    var remaining = _innerWidth - fractionComplete - 1;
    _logger.write('\r[' + // Bring cursor back to the start of the line.
        '-' * fractionComplete + // Print complete work.
        AnsiProgress.kAnimationItems[_tickCount % 4] + // Print spinner.
        ' ' * remaining + // Print remaining work.
        ']');
  }
}

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 '???';
  }
}
