// Copyright (c) 2015, 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:io' as io;

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer_cli/src/ansi.dart' as ansi;
import 'package:analyzer_cli/src/driver.dart';
import 'package:args/args.dart';
import 'package:pub_semver/pub_semver.dart';

const _analysisOptionsFileOption = 'options';
const _binaryName = 'dartanalyzer';
const _defaultLanguageVersionOption = 'default-language-version';
const _defineVariableOption = 'D';
const _enableExperimentOption = 'enable-experiment';
const _enableInitializingFormalAccessFlag = 'initializing-formal-access';
const _ignoreUnrecognizedFlagsFlag = 'ignore-unrecognized-flags';
const _implicitCastsFlag = 'implicit-casts';
const _lintsFlag = 'lints';
const _noImplicitDynamicFlag = 'no-implicit-dynamic';
const _packagesOption = 'packages';
const _sdkPathOption = 'dart-sdk';

/// Shared exit handler.
///
/// *Visible for testing.*
ExitHandler exitHandler = io.exit;

T cast<T>(dynamic value) => value as T;

/// Print the given [message] to stderr and exit with the given [exitCode].
void printAndFail(String message, {int exitCode = 15}) {
  errorSink.writeln(message);
  exitHandler(exitCode);
}

/// Exit handler.
///
/// *Visible for testing.*
typedef ExitHandler = void Function(int code);

/// Analyzer commandline configuration options.
class CommandLineOptions {
  final ArgResults _argResults;

  /// The options defining the context in which analysis is performed.
  final ContextBuilderOptions contextBuilderOptions;

  /// The path to the dart SDK.
  String dartSdkPath;

  /// Whether to disable cache flushing. This option can improve analysis
  /// speed at the expense of memory usage. It may also be useful for working
  /// around bugs.
  final bool disableCacheFlushing;

  /// Whether to report hints
  final bool disableHints;

  /// Whether to display version information
  final bool displayVersion;

  /// Whether to ignore unrecognized flags
  final bool ignoreUnrecognizedFlags;

  /// Whether to log additional analysis messages and exceptions
  final bool log;

  /// Whether to use 'json' format for error display
  final bool jsonFormat;

  /// Whether to use 'machine' format for error display
  final bool machineFormat;

  /// The path to a file to write a performance log.
  /// (Or null if not enabled.)
  final String perfReport;

  /// Batch mode (for unit testing)
  final bool batchMode;

  /// Whether to show package: warnings
  final bool showPackageWarnings;

  /// If not null, show package: warnings only for matching packages.
  final String showPackageWarningsPrefix;

  /// Whether to show SDK warnings
  final bool showSdkWarnings;

  /// The source files to analyze
  final List<String> sourceFiles;

  /// Whether to treat warnings as fatal
  final bool warningsAreFatal;

  /// Whether to treat info level items as fatal
  final bool infosAreFatal;

  /// Whether to treat lints as fatal
  // TODO(devoncarew): Deprecate and remove this flag.
  final bool lintsAreFatal;

  /// Emit output in a verbose mode.
  final bool verbose;

  /// Use ANSI color codes for output.
  final bool color;

  /// Whether we should analyze the given source for the purposes of training a
  /// Dart analyzer snapshot.
  final bool trainSnapshot;

  /// Initialize options from the given parsed [args].
  CommandLineOptions._fromArgs(
    ResourceProvider resourceProvider,
    ArgResults args,
  )   : _argResults = args,
        contextBuilderOptions = _createContextBuilderOptions(
          resourceProvider,
          args,
        ),
        dartSdkPath = cast(args[_sdkPathOption]),
        disableCacheFlushing = cast(args['disable-cache-flushing']),
        disableHints = cast(args['no-hints']),
        displayVersion = cast(args['version']),
        ignoreUnrecognizedFlags = cast(args[_ignoreUnrecognizedFlagsFlag]),
        log = cast(args['log']),
        jsonFormat = args['format'] == 'json',
        machineFormat = args['format'] == 'machine',
        perfReport = cast(args['x-perf-report']),
        batchMode = cast(args['batch']),
        showPackageWarnings = cast(args['show-package-warnings']) ||
            cast(args['package-warnings']) ||
            args['x-package-warnings-prefix'] != null,
        showPackageWarningsPrefix = cast(args['x-package-warnings-prefix']),
        showSdkWarnings = cast(args['sdk-warnings']),
        sourceFiles = args.rest,
        infosAreFatal = cast(args['fatal-infos']) || cast(args['fatal-hints']),
        warningsAreFatal = cast(args['fatal-warnings']),
        lintsAreFatal = cast(args['fatal-lints']),
        trainSnapshot = cast(args['train-snapshot']),
        verbose = cast(args['verbose']),
        color = cast(args['color']);

  /// The path to an analysis options file
  String get analysisOptionsFile =>
      contextBuilderOptions.defaultAnalysisOptionsFilePath;

  /// The default language version for files that are not in a package.
  /// (Or null if no default language version to force.)
  String get defaultLanguageVersion {
    return cast(_argResults[_defaultLanguageVersionOption]);
  }

  /// A table mapping the names of defined variables to their values.
  Map<String, String> get definedVariables =>
      contextBuilderOptions.declaredVariables;

  /// A list of the names of the experiments that are to be enabled.
  List<String> get enabledExperiments {
    return cast(_argResults[_enableExperimentOption]);
  }

  bool get implicitCasts => _argResults[_implicitCastsFlag] as bool;

  bool get lints => _argResults[_lintsFlag] as bool;

  bool get noImplicitDynamic => _argResults[_noImplicitDynamicFlag] as bool;

  /// The path to a `.packages` configuration file
  String get packageConfigPath => contextBuilderOptions.defaultPackageFilePath;

  /// Update the [analysisOptions] with flags that the user specified
  /// explicitly. The [analysisOptions] are usually loaded from one of
  /// `analysis_options.yaml` files, possibly with includes. We consider
  /// flags that the user specified as command line options more important,
  /// so override the corresponding options.
  void updateAnalysisOptions(AnalysisOptionsImpl analysisOptions) {
    var defaultLanguageVersion = this.defaultLanguageVersion;
    if (defaultLanguageVersion != null) {
      var nonPackageLanguageVersion =
          Version.parse('$defaultLanguageVersion.0');
      analysisOptions.nonPackageLanguageVersion = nonPackageLanguageVersion;
      analysisOptions.nonPackageFeatureSet = FeatureSet.latestLanguageVersion()
          .restrictToVersion(nonPackageLanguageVersion);
    }

    var enabledExperiments = this.enabledExperiments;
    if (enabledExperiments.isNotEmpty) {
      analysisOptions.contextFeatures = FeatureSet.fromEnableFlags2(
        sdkLanguageVersion: ExperimentStatus.currentVersion,
        flags: enabledExperiments,
      );
    }

    var implicitCasts = this.implicitCasts;
    if (implicitCasts != null) {
      analysisOptions.implicitCasts = implicitCasts;
    }

    var lints = this.lints;
    if (lints != null) {
      analysisOptions.lint = lints;
    }

    var noImplicitDynamic = this.noImplicitDynamic;
    if (noImplicitDynamic != null) {
      analysisOptions.implicitDynamic = !noImplicitDynamic;
    }
  }

  /// Return a list of command-line arguments containing all of the given [args]
  /// that are defined by the given [parser]. An argument is considered to be
  /// defined by the parser if
  /// - it starts with '--' and the rest of the argument (minus any value
  ///   introduced by '=') is the name of a known option,
  /// - it starts with '-' and the rest of the argument (minus any value
  ///   introduced by '=') is the name of a known abbreviation, or
  /// - it starts with something other than '--' or '-'.
  ///
  /// This function allows command-line tools to implement the
  /// '--ignore-unrecognized-flags' option.
  static List<String> filterUnknownArguments(
      List<String> args, ArgParser parser) {
    var knownOptions = <String>{};
    var knownAbbreviations = <String>{};
    parser.options.forEach((String name, Option option) {
      knownOptions.add(name);
      var abbreviation = option.abbr;
      if (abbreviation != null) {
        knownAbbreviations.add(abbreviation);
      }
      if (option.negatable ?? false) {
        knownOptions.add('no-$name');
      }
    });
    String optionName(int prefixLength, String argument) {
      var equalsOffset = argument.lastIndexOf('=');
      if (equalsOffset < 0) {
        return argument.substring(prefixLength);
      }
      return argument.substring(prefixLength, equalsOffset);
    }

    var filtered = <String>[];
    for (var i = 0; i < args.length; i++) {
      var argument = args[i];
      if (argument.startsWith('--') && argument.length > 2) {
        if (knownOptions.contains(optionName(2, argument))) {
          filtered.add(argument);
        }
      } else if (argument.startsWith('-D') && argument.indexOf('=') > 0) {
        filtered.add(argument);
      }
      if (argument.startsWith('-') && argument.length > 1) {
        if (knownAbbreviations.contains(optionName(1, argument))) {
          filtered.add(argument);
        }
      } else {
        filtered.add(argument);
      }
    }
    return filtered;
  }

  /// Parse [args] into [CommandLineOptions] describing the specified
  /// analyzer options. In case of a format error, calls [printAndFail], which
  /// by default prints an error message to stderr and exits.
  static CommandLineOptions parse(
      ResourceProvider resourceProvider, List<String> args,
      {void Function(String msg) printAndFail = printAndFail}) {
    var options = _parse(resourceProvider, args);

    /// Only happens in testing.
    if (options == null) {
      return null;
    }

    // Check SDK.
    {
      var sdkPath = options.dartSdkPath;

      // Check that SDK is existing directory.
      if (sdkPath != null) {
        if (!(io.Directory(sdkPath)).existsSync()) {
          printAndFail('Invalid Dart SDK path: $sdkPath');
          return null; // Only reachable in testing.
        }
      }

      // Infer if unspecified.
      sdkPath ??= getSdkPath(args);

      var pathContext = resourceProvider.pathContext;
      options.dartSdkPath = file_paths.absoluteNormalized(pathContext, sdkPath);
    }

    return options;
  }

  /// Use the command-line [args] to create a context builder options.
  static ContextBuilderOptions _createContextBuilderOptions(
    ResourceProvider resourceProvider,
    ArgResults args,
  ) {
    String absoluteNormalizedPath(String path) {
      if (path == null) {
        return null;
      }
      var pathContext = resourceProvider.pathContext;
      return pathContext.normalize(
        pathContext.absolute(path),
      );
    }

    var builderOptions = ContextBuilderOptions();

    //
    // File locations.
    //
    builderOptions.defaultAnalysisOptionsFilePath = absoluteNormalizedPath(
      cast(args[_analysisOptionsFileOption]),
    );
    builderOptions.defaultPackageFilePath = absoluteNormalizedPath(
      cast(args[_packagesOption]),
    );
    //
    // Declared variables.
    //
    var declaredVariables = <String, String>{};
    var variables = (args[_defineVariableOption] as List).cast<String>();
    for (var variable in variables) {
      var index = variable.indexOf('=');
      if (index < 0) {
        // TODO (brianwilkerson) Decide the semantics we want in this case.
        // The VM prints "No value given to -D option", then tries to load '-Dfoo'
        // as a file and dies. Unless there was nothing after the '-D', in which
        // case it prints the warning and ignores the option.
      } else {
        var name = variable.substring(0, index);
        if (name.isNotEmpty) {
          // TODO (brianwilkerson) Decide the semantics we want in the case where
          // there is no name. If there is no name, the VM tries to load a file
          // named '-D' and dies.
          declaredVariables[name] = variable.substring(index + 1);
        }
      }
    }
    builderOptions.declaredVariables = declaredVariables;

    return builderOptions;
  }

  /// Add the standard flags and options to the given [parser]. The standard flags
  /// are those that are typically used to control the way in which the code is
  /// analyzed.
  ///
  /// TODO(danrubel) Update DDC to support all the options defined in this method
  /// then remove the [ddc] named argument from this method.
  static void _defineAnalysisArguments(ArgParser parser,
      {bool hide = true, bool ddc = false}) {
    parser.addOption(_sdkPathOption,
        help: 'The path to the Dart SDK.', hide: ddc && hide);
    parser.addOption(_analysisOptionsFileOption,
        help: 'Path to an analysis options file.', hide: ddc && hide);
    parser.addFlag('strong',
        help: 'Enable strong mode (deprecated); this option is now ignored.',
        defaultsTo: true,
        hide: true,
        negatable: true);
    parser.addFlag('declaration-casts',
        negatable: true,
        help:
            'Disable declaration casts in strong mode (https://goo.gl/cTLz40)\n'
            'This option is now ignored and will be removed in a future release.',
        hide: ddc && hide);
    parser.addMultiOption(_enableExperimentOption,
        help: 'Enable one or more experimental features. If multiple features '
            'are being added, they should be comma separated.',
        splitCommas: true);
    parser.addFlag(_implicitCastsFlag,
        negatable: true,
        help: 'Disable implicit casts in strong mode (https://goo.gl/cTLz40).',
        defaultsTo: null,
        hide: ddc && hide);
    parser.addFlag(_noImplicitDynamicFlag,
        defaultsTo: null,
        negatable: false,
        help: 'Disable implicit dynamic (https://goo.gl/m0UgXD).',
        hide: ddc && hide);

    //
    // Hidden flags and options.
    //
    parser.addMultiOption(_defineVariableOption,
        abbr: 'D',
        help:
            'Define an environment declaration. For example, "-Dfoo=bar" defines '
            'an environment declaration named "foo" whose value is "bar".',
        hide: hide);
    parser.addOption(_packagesOption,
        help: 'The path to the package resolution configuration file, which '
            'supplies a mapping of package names\nto paths.',
        hide: ddc);
    parser.addFlag(_enableInitializingFormalAccessFlag,
        help:
            'Enable support for allowing access to field formal parameters in a '
            'constructor\'s initializer list (deprecated).',
        defaultsTo: false,
        negatable: false,
        hide: hide || ddc);
    if (!ddc) {
      parser.addFlag(_lintsFlag,
          help: 'Show lint results.', defaultsTo: null, negatable: true);
    }
  }

  static String _getVersion() {
    try {
      // This is relative to bin/snapshot, so ../..
      var versionPath =
          io.Platform.script.resolve('../../version').toFilePath();
      var versionFile = io.File(versionPath);
      return versionFile.readAsStringSync().trim();
    } catch (_) {
      // This happens when the script is not running in the context of an SDK.
      return '<unknown>';
    }
  }

  static CommandLineOptions _parse(
    ResourceProvider resourceProvider,
    List<String> args,
  ) {
    var verbose = args.contains('-v') || args.contains('--verbose');
    var hide = !verbose;

    var parser = ArgParser(allowTrailingOptions: true);

    if (!hide) {
      parser.addSeparator('General options:');
    }

    // TODO(devoncarew): This defines some hidden flags, which would be better
    // defined with the rest of the hidden flags below (to group well with the
    // other flags).
    _defineAnalysisArguments(parser, hide: hide);

    parser
      ..addOption('format',
          help: 'Specifies the format in which errors are displayed; the only '
              'currently recognized values are \'json\' and \'machine\'.')
      ..addFlag('version',
          help: 'Print the analyzer version.',
          defaultsTo: false,
          negatable: false)
      ..addFlag('no-hints',
          help: 'Do not show hint results.',
          defaultsTo: false,
          negatable: false)
      ..addFlag('fatal-infos',
          help: 'Treat infos as fatal.', defaultsTo: false, negatable: false)
      ..addFlag('fatal-warnings',
          help: 'Treat non-type warnings as fatal.',
          defaultsTo: false,
          negatable: false)
      ..addFlag('help',
          abbr: 'h',
          help:
              'Display this help message. Add --verbose to show hidden options.',
          defaultsTo: false,
          negatable: false)
      ..addFlag('verbose',
          abbr: 'v',
          defaultsTo: false,
          help: 'Verbose output.',
          negatable: false);

    parser.addFlag('color',
        help: 'Use ansi colors when printing messages.',
        defaultsTo: ansi.terminalSupportsAnsi(),
        hide: hide);

    // Hidden flags.
    if (!hide) {
      parser.addSeparator('Less frequently used flags:');
    }

    parser
      ..addFlag('batch',
          help: 'Read commands from standard input (for testing).',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addFlag(_ignoreUnrecognizedFlagsFlag,
          help: 'Ignore unrecognized command line flags.',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addOption(_defaultLanguageVersionOption,
          help: 'The default language version when it is not specified via '
              'other ways (internal, tests only).',
          hide: false)
      ..addFlag('disable-cache-flushing', defaultsTo: false, hide: hide)
      ..addOption('x-perf-report',
          help: 'Writes a performance report to the given file (experimental).',
          hide: hide)
      ..addOption('x-package-warnings-prefix',
          help:
              'Show warnings from package: imports that match the given prefix (deprecated).',
          hide: hide)
      ..addFlag('enable-conditional-directives',
          help:
              'deprecated -- Enable support for conditional directives (DEP 40).',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addFlag('show-package-warnings',
          help: 'Show warnings from package: imports (deprecated).',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addFlag('sdk-warnings',
          help: 'Show warnings from SDK imports (deprecated).',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addFlag('log',
          help: 'Log additional messages and exceptions.',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addFlag('enable_type_checks',
          help: 'Check types in constant evaluation (deprecated).',
          defaultsTo: false,
          negatable: false,
          hide: true)
      ..addFlag('use-analysis-driver-memory-byte-store',
          help: 'Use memory byte store, not the file system cache.',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addFlag('fatal-hints',
          help: 'Treat hints as fatal (deprecated: use --fatal-infos).',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addFlag('fatal-lints',
          help: 'Treat lints as fatal.',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addFlag('package-warnings',
          help: 'Show warnings from package: imports (deprecated).',
          defaultsTo: false,
          negatable: false,
          hide: hide)
      ..addMultiOption('url-mapping',
          help: '--url-mapping=libraryUri,/path/to/library.dart directs the '
              'analyzer to use "library.dart" as the source for an import '
              'of "libraryUri".',
          splitCommas: false,
          hide: hide)
      ..addFlag('train-snapshot',
          help: 'Analyze the given source for the purposes of training a '
              'dartanalyzer snapshot.',
          hide: hide,
          negatable: false);

    try {
      if (args.contains('--$_ignoreUnrecognizedFlagsFlag')) {
        args = filterUnknownArguments(args, parser);
      }
      var results = parser.parse(args);

      // Help requests.
      if (cast(results['help'])) {
        _showUsage(parser, fromHelp: true);
        exitHandler(0);
        return null; // Only reachable in testing.
      }

      // Batch mode and input files.
      if (cast(results['batch'])) {
        if (results.rest.isNotEmpty) {
          errorSink.writeln('No source files expected in the batch mode.');
          _showUsage(parser);
          exitHandler(15);
          return null; // Only reachable in testing.
        }
      } else if (cast(results['version'])) {
        outSink.writeln('$_binaryName version ${_getVersion()}');
        exitHandler(0);
        return null; // Only reachable in testing.
      } else {
        if (results.rest.isEmpty) {
          _showUsage(parser, fromHelp: true);
          exitHandler(15);
          return null; // Only reachable in testing.
        }
      }

      if (results.wasParsed('strong')) {
        errorSink.writeln(
            'Note: the --strong flag is deprecated and will be removed in an '
            'future release.\n');
      }
      if (results.wasParsed(_enableExperimentOption)) {
        var names =
            (results[_enableExperimentOption] as List).cast<String>().toList();
        var errorFound = false;
        for (var validationResult in validateFlags(names)) {
          if (validationResult.isError) {
            errorFound = true;
          }
          var kind = validationResult.isError ? 'ERROR' : 'WARNING';
          errorSink.writeln('$kind: ${validationResult.message}');
        }
        if (errorFound) {
          _showUsage(parser);
          exitHandler(15);
          return null; // Only reachable in testing.
        }
      }

      return CommandLineOptions._fromArgs(resourceProvider, results);
    } on FormatException catch (e) {
      errorSink.writeln(e.message);
      _showUsage(parser);
      exitHandler(15);
      return null; // Only reachable in testing.
    }
  }

  static void _showUsage(ArgParser parser, {bool fromHelp = false}) {
    errorSink.writeln(
        'Usage: $_binaryName [options...] <directory or list of files>');

    errorSink.writeln('');
    errorSink.writeln(parser.usage);

    errorSink.writeln('');
    errorSink.writeln('''
Run "dartanalyzer -h -v" for verbose help output, including less commonly used options.
For more information, see https://dart.dev/tools/dartanalyzer.\n''');
  }
}
