// 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/sdk/build_sdk_summary.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
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/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/pub.dart';
import 'package:analyzer/src/manifest/manifest_validator.dart';
import 'package:analyzer/src/pubspec/pubspec_validator.dart';
import 'package:analyzer/src/source/path_filter.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/yaml.dart';
import 'package:analyzer_cli/src/analyzer_impl.dart';
import 'package:analyzer_cli/src/batch_mode.dart';
import 'package:analyzer_cli/src/error_formatter.dart';
import 'package:analyzer_cli/src/error_severity.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:analyzer_cli/src/perf_report.dart';
import 'package:analyzer_cli/starter.dart' show CommandLineStarter;
import 'package:linter/src/rules.dart' as linter;
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart';

/// Shared IO sink for standard error reporting.
late StringSink errorSink = io.stderr;

/// Shared IO sink for standard out reporting.
late StringSink outSink = io.stdout;

/// Test this option map to see if it specifies lint rules.
bool containsLintRuleEntry(YamlMap options) {
  var linterNode = options.valueAt('linter');
  return linterNode is YamlMap && linterNode.valueAt('rules') != null;
}

class Driver implements CommandLineStarter {
  static final ByteStore analysisDriverMemoryByteStore = MemoryByteStore();

  bool _isStarted = false;

  late _AnalysisContextProvider _analysisContextProvider;
  DriverBasedAnalysisContext? analysisContext;

  /// The driver that was most recently created by a call to [_analyzeAll].
  @visibleForTesting
  AnalysisDriver? analysisDriver;

  /// The total number of source files loaded by an AnalysisContext.
  int _analyzedFileCount = 0;

  /// The resource provider used to access the file system.
  final ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;

  /// Collected analysis statistics.
  final AnalysisStats stats = AnalysisStats();

  /// The [PathFilter] for excluded files with wildcards, etc.
  late PathFilter pathFilter;

  /// Create a new Driver instance.
  Driver({@Deprecated('This parameter has no effect') bool isTesting = false});

  /// Converts the given [filePath] into absolute and normalized.
  String normalizePath(String filePath) {
    filePath = filePath.trim();
    filePath = resourceProvider.pathContext.absolute(filePath);
    filePath = resourceProvider.pathContext.normalize(filePath);
    return filePath;
  }

  @override
  Future<void> start(List<String> arguments) async {
    if (_isStarted) {
      throw StateError('start() can only be called once');
    }
    _isStarted = true;
    var startTime = DateTime.now().millisecondsSinceEpoch;

    linter.registerLintRules();

    // Parse commandline options.
    var options = CommandLineOptions.parse(resourceProvider, arguments)!;

    _analysisContextProvider = _AnalysisContextProvider(resourceProvider);

    // Do analysis.
    if (options.batchMode) {
      var batchRunner = BatchRunner(outSink, errorSink);
      batchRunner.runAsBatch(arguments, (List<String> args) async {
        var options = CommandLineOptions.parse(resourceProvider, args)!;
        return await _analyzeAll(options);
      });
    } else {
      var severity = await _analyzeAll(options);
      // Propagate issues to the exit code.
      if (_shouldBeFatal(severity, options)) {
        io.exitCode = severity.ordinal;
      }
    }

    // When training a snapshot, in addition to training regular analysis
    // (above), we train build mode as well.
    if (options.trainSnapshot) {
      // TODO(devoncarew): Iterate on this training to make it more
      // representative of what we see internally; call into _buildModeAnalyze()
      // with some appropriate options.
      print('\nGenerating strong mode summary...');
      final stopwatch = Stopwatch()..start();

      for (var i = 0; i < 3; i++) {
        buildSdkSummary(
          resourceProvider: PhysicalResourceProvider.INSTANCE,
          sdkPath: options.dartSdkPath!,
        );
      }

      print('Done in ${stopwatch.elapsedMilliseconds} ms.');
    }

    if (analysisDriver != null) {
      _analyzedFileCount += analysisDriver!.knownFiles.length;
    }

    if (options.perfReport != null) {
      var json = makePerfReport(
          startTime, currentTimeMillis, options, _analyzedFileCount, stats);
      io.File(options.perfReport!).writeAsStringSync(json);
    }
  }

  /// Perform analysis according to the given [options].
  Future<ErrorSeverity> _analyzeAll(CommandLineOptions options) async {
    if (!options.jsonFormat && !options.machineFormat) {
      var fileNames = options.sourceFiles.map((String file) {
        file = path.normalize(file);
        if (file == '.') {
          file = path.basename(path.current);
        } else if (file == '..') {
          file = path.basename(path.normalize(path.absolute(file)));
        }
        return file;
      }).toList();

      outSink.writeln("Analyzing ${fileNames.join(', ')}...");
    }

    _verifyAnalysisOptionsFileExists(options);

    // These are used to do part file analysis across sources.
    var dartFiles = <String>{};
    var libraryFiles = <FileState>{};
    var danglingParts = <FileState>{};

    // Note: This references analysisDriver via closure, so it will change over
    // time during the following analysis.
    SeverityProcessor defaultSeverityProcessor;
    defaultSeverityProcessor = (AnalysisError error) {
      return determineProcessedSeverity(
          error, options, analysisDriver!.analysisOptions);
    };

    // We currently print out to stderr to ensure that when in batch mode we
    // print to stderr, this is because the prints from batch are made to
    // stderr. The reason that options.shouldBatch isn't used is because when
    // the argument flags are constructed in BatchRunner and passed in from
    // batch mode which removes the batch flag to prevent the "cannot have the
    // batch flag and source file" error message.
    ErrorFormatter formatter;
    if (options.jsonFormat) {
      formatter = JsonErrorFormatter(outSink, options, stats,
          severityProcessor: defaultSeverityProcessor);
    } else if (options.machineFormat) {
      // The older machine format emits to stderr (instead of stdout) for legacy
      // reasons.
      formatter = MachineErrorFormatter(errorSink, options, stats,
          severityProcessor: defaultSeverityProcessor);
    } else {
      formatter = HumanErrorFormatter(outSink, options, stats,
          severityProcessor: defaultSeverityProcessor);
    }

    var allResult = ErrorSeverity.NONE;

    void reportPartError(String partPath) {
      errorSink.writeln('$partPath is a part and cannot be analyzed.');
      errorSink.writeln('Please pass in a library that contains this part.');
      io.exitCode = ErrorSeverity.ERROR.ordinal;
      allResult = allResult.max(ErrorSeverity.ERROR);
    }

    var pathList = options.sourceFiles.map(normalizePath).toList();
    _analysisContextProvider.setCommandLineOptions(options, pathList);

    for (var sourcePath in pathList) {
      _analysisContextProvider.configureForPath(sourcePath);
      analysisContext = _analysisContextProvider.analysisContext;
      final analysisDriver =
          this.analysisDriver = _analysisContextProvider.analysisDriver;
      pathFilter = _analysisContextProvider.pathFilter;

      // Add all the files to be analyzed en masse to the context. Skip any
      // files that were added earlier (whether explicitly or implicitly) to
      // avoid causing those files to be unnecessarily re-read.
      var filesToAnalyze = <String>{};

      // Collect files for analysis.
      // Note that these files will all be analyzed in the same context.
      // This should be updated when the ContextManager re-work is complete
      // (See: https://github.com/dart-lang/sdk/issues/24133)
      var files = _collectFiles(sourcePath, analysisDriver.analysisOptions);
      if (files.isEmpty) {
        errorSink.writeln('No dart files found at: $sourcePath');
        io.exitCode = ErrorSeverity.ERROR.ordinal;
        return ErrorSeverity.ERROR;
      }

      for (var file in files) {
        filesToAnalyze.add(file.absolute.path);
      }

      // Analyze the libraries.
      var pathContext = resourceProvider.pathContext;
      for (var path in filesToAnalyze) {
        if (file_paths.isAnalysisOptionsYaml(pathContext, path)) {
          var file = resourceProvider.getFile(path);
          var content = file.readAsStringSync();
          var lineInfo = LineInfo.fromContent(content);
          var errors = analyzeAnalysisOptions(
            file.createSource(),
            content,
            analysisDriver.sourceFactory,
            analysisDriver.currentSession.analysisContext.contextRoot.root.path,
          );
          formatter.formatErrors([
            ErrorsResultImpl(analysisDriver.currentSession, path,
                pathContext.toUri(path), lineInfo, false, errors)
          ]);
          for (var error in errors) {
            var severity = determineProcessedSeverity(
                error, options, analysisDriver.analysisOptions);
            if (severity != null) {
              allResult = allResult.max(severity);
            }
          }
        } else if (file_paths.isPubspecYaml(pathContext, path)) {
          var errors = <AnalysisError>[];
          try {
            var file = resourceProvider.getFile(path);
            var content = file.readAsStringSync();
            var node = loadYamlNode(content);
            if (node is YamlMap) {
              var validator =
                  PubspecValidator(resourceProvider, file.createSource());
              errors.addAll(validator.validate(node.nodes));
            }

            if (analysisDriver.analysisOptions.lint) {
              var visitors = <LintRule, PubspecVisitor>{};
              for (var linter in analysisDriver.analysisOptions.lintRules) {
                if (linter is LintRule) {
                  var visitor = linter.getPubspecVisitor();
                  if (visitor != null) {
                    visitors[linter] = visitor;
                  }
                }
              }
              if (visitors.isNotEmpty) {
                var sourceUri = pathContext.toUri(path);
                var pubspecAst = Pubspec.parse(content,
                    sourceUrl: sourceUri, resourceProvider: resourceProvider);
                var listener = RecordingErrorListener();
                var reporter = ErrorReporter(listener,
                    resourceProvider.getFile(path).createSource(sourceUri),
                    isNonNullableByDefault: false);
                for (var entry in visitors.entries) {
                  entry.key.reporter = reporter;
                  pubspecAst.accept(entry.value);
                }
                errors.addAll(listener.errors);
              }
            }

            if (errors.isNotEmpty) {
              for (var error in errors) {
                var severity = determineProcessedSeverity(
                    error, options, analysisDriver.analysisOptions)!;
                allResult = allResult.max(severity);
              }
              var lineInfo = LineInfo.fromContent(content);
              formatter.formatErrors([
                ErrorsResultImpl(analysisDriver.currentSession, path,
                    pathContext.toUri(path), lineInfo, false, errors)
              ]);
            }
          } catch (exception) {
            // If the file cannot be analyzed, ignore it.
          }
        } else if (file_paths.isAndroidManifestXml(pathContext, path)) {
          try {
            var file = resourceProvider.getFile(path);
            var content = file.readAsStringSync();
            var validator = ManifestValidator(file.createSource());
            var lineInfo = LineInfo.fromContent(content);
            var errors = validator.validate(
                content, analysisDriver.analysisOptions.chromeOsManifestChecks);
            formatter.formatErrors([
              ErrorsResultImpl(analysisDriver.currentSession, path,
                  pathContext.toUri(path), lineInfo, false, errors)
            ]);
            for (var error in errors) {
              var severity = determineProcessedSeverity(
                  error, options, analysisDriver.analysisOptions)!;
              allResult = allResult.max(severity);
            }
          } catch (exception) {
            // If the file cannot be analyzed, ignore it.
          }
        } else {
          dartFiles.add(path);
          var file = analysisDriver.fsState.getFileForPath(path);

          if (file.isPart) {
            if (!libraryFiles.contains(file.library)) {
              danglingParts.add(file);
            }
            continue;
          }
          libraryFiles.add(file);

          var status = await _runAnalyzer(file, options, formatter);
          allResult = allResult.max(status);

          // Mark previously dangling parts as no longer dangling.
          for (var part in file.partedFiles) {
            danglingParts.remove(part);
          }
        }
      }
    }

    // We are done analyzing this batch of files.
    // The next batch should not be affected by a previous batch.
    // E.g. the same parts in both batches, but with different libraries.
    for (var path in dartFiles) {
      analysisDriver!.removeFile(path);
    }

    // Any dangling parts still in this list were definitely dangling.
    for (var partFile in danglingParts) {
      reportPartError(partFile.path);
    }

    formatter.flush();

    if (!options.machineFormat && !options.jsonFormat) {
      stats.print(outSink);
    }

    return allResult;
  }

  /// Collect all analyzable files at [filePath], recursively if it's a
  /// directory, ignoring links.
  Iterable<io.File> _collectFiles(String filePath, AnalysisOptions options) {
    var files = <io.File>[];
    var file = io.File(filePath);
    if (file.existsSync()) {
      files.add(file);
    } else {
      var directory = io.Directory(filePath);
      if (directory.existsSync()) {
        var pathContext = resourceProvider.pathContext;
        for (var entry
            in directory.listSync(recursive: true, followLinks: false)) {
          var relative = path.relative(entry.path, from: directory.path);
          if ((file_paths.isDart(pathContext, entry.path) ||
                  file_paths.isAndroidManifestXml(pathContext, entry.path)) &&
              entry is io.File &&
              !pathFilter.ignored(entry.path) &&
              !_isInHiddenDir(relative)) {
            files.add(entry);
          }
        }
      }
    }
    return files;
  }

  /// Returns `true` if this relative path is a hidden directory.
  bool _isInHiddenDir(String relative) =>
      path.split(relative).any((part) => part.startsWith('.'));

  /// Analyze a single source.
  Future<ErrorSeverity> _runAnalyzer(
      FileState file, CommandLineOptions options, ErrorFormatter formatter) {
    var startTime = currentTimeMillis;
    final analysisDriver = this.analysisDriver!;
    var analyzer = AnalyzerImpl(analysisDriver.analysisOptions, analysisDriver,
        file, options, stats, startTime);
    return analyzer.analyze(formatter);
  }

  bool _shouldBeFatal(ErrorSeverity severity, CommandLineOptions options) {
    if (severity == ErrorSeverity.ERROR) {
      return true;
    } else if (severity == ErrorSeverity.WARNING &&
        (options.warningsAreFatal || options.infosAreFatal)) {
      return true;
    } else if (severity == ErrorSeverity.INFO && options.infosAreFatal) {
      return true;
    } else {
      return false;
    }
  }

  void _verifyAnalysisOptionsFileExists(CommandLineOptions options) {
    var path = options.defaultAnalysisOptionsPath;
    if (path != null) {
      if (!resourceProvider.getFile(path).exists) {
        printAndFail('Options file not found: $path',
            exitCode: ErrorSeverity.ERROR.ordinal);
      }
    }
  }

  static void verbosePrint(String text) {
    outSink.writeln(text);
  }

  /// Return whether the [newOptions] are equal to the [previous].
  static bool _equalCommandLineOptions(
      CommandLineOptions? previous, CommandLineOptions newOptions) {
    return previous != null &&
        newOptions.defaultPackagesPath == previous.defaultPackagesPath &&
        _equalMaps(newOptions.declaredVariables, previous.declaredVariables) &&
        newOptions.log == previous.log &&
        newOptions.disableHints == previous.disableHints &&
        newOptions.showPackageWarnings == previous.showPackageWarnings &&
        newOptions.showPackageWarningsPrefix ==
            previous.showPackageWarningsPrefix &&
        newOptions.showSdkWarnings == previous.showSdkWarnings &&
        newOptions.lints == previous.lints &&
        newOptions.defaultLanguageVersion == previous.defaultLanguageVersion &&
        newOptions.disableCacheFlushing == previous.disableCacheFlushing &&
        _equalLists(
            newOptions.enabledExperiments!, previous.enabledExperiments!);
  }

  /// Perform a deep comparison of two string lists.
  static bool _equalLists(List<String> l1, List<String> l2) {
    if (l1.length != l2.length) {
      return false;
    }
    for (var i = 0; i < l1.length; i++) {
      if (l1[i] != l2[i]) {
        return false;
      }
    }
    return true;
  }

  /// Perform a deep comparison of two string maps.
  static bool _equalMaps(Map<String, String> m1, Map<String, String> m2) {
    if (m1.length != m2.length) {
      return false;
    }
    for (var key in m1.keys) {
      if (!m2.containsKey(key) || m1[key] != m2[key]) {
        return false;
      }
    }
    return true;
  }
}

class _AnalysisContextProvider {
  final ResourceProvider _resourceProvider;
  final FileContentCache _fileContentCache;

  CommandLineOptions? _commandLineOptions;
  late List<String> _pathList;

  final Map<Folder, DriverBasedAnalysisContext?> _folderContexts = {};
  AnalysisContextCollectionImpl? _collection;
  DriverBasedAnalysisContext? _analysisContext;

  _AnalysisContextProvider(this._resourceProvider)
      : _fileContentCache = FileContentCache(_resourceProvider);

  DriverBasedAnalysisContext? get analysisContext {
    return _analysisContext;
  }

  AnalysisDriver get analysisDriver {
    return _analysisContext!.driver;
  }

  /// TODO(scheglov) Use analyzedFiles()
  PathFilter get pathFilter {
    var contextRoot = analysisContext!.contextRoot;
    var optionsFile = contextRoot.optionsFile;

    // If there is no options file, there can be no excludes.
    if (optionsFile == null) {
      return PathFilter(contextRoot.root.path, contextRoot.root.path, []);
    }

    // Exclude patterns are relative to the directory with the options file.
    return PathFilter(contextRoot.root.path, optionsFile.parent2.path,
        analysisContext!.analysisOptions.excludePatterns);
  }

  void configureForPath(String path) {
    var folder = _resourceProvider.getFolder(path);
    if (!folder.exists) {
      folder = _resourceProvider.getFile(path).parent2;
    }

    // In batch mode we are given separate file paths to analyze.
    // All files of a folder have the same configuration.
    // So, reuse the corresponding analysis context.
    _analysisContext = _folderContexts[folder];
    if (_analysisContext != null) {
      return;
    }

    if (_collection != null) {
      try {
        _setContextForPath(path);
        return;
      } on StateError {
        // The previous collection cannot analyze the path.
        _collection = null;
      }
    }

    _collection = AnalysisContextCollectionImpl(
      byteStore: Driver.analysisDriverMemoryByteStore,
      includedPaths: _pathList,
      optionsFile: _commandLineOptions!.defaultAnalysisOptionsPath,
      packagesFile: _commandLineOptions!.defaultPackagesPath,
      resourceProvider: _resourceProvider,
      sdkPath: _commandLineOptions!.dartSdkPath,
      updateAnalysisOptions: _updateAnalysisOptions,
      fileContentCache: _fileContentCache,
    );

    _setContextForPath(path);
    _folderContexts[folder] = _analysisContext;
  }

  void setCommandLineOptions(
    CommandLineOptions options,
    List<String> pathList,
  ) {
    if (!Driver._equalCommandLineOptions(_commandLineOptions, options)) {
      _folderContexts.clear();
      _collection = null;
      _analysisContext = null;
    }
    _commandLineOptions = options;
    _pathList = pathList;
  }

  void _setContextForPath(String path) {
    _analysisContext = _collection!.contextFor(path);
  }

  void _updateAnalysisOptions(AnalysisOptionsImpl analysisOptions) {
    _commandLineOptions!.updateAnalysisOptions(analysisOptions);
  }
}
