// 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/results.dart';
import 'package:analyzer/dart/sdk/build_sdk_summary.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/source/file_source.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/analysis_options/analysis_options.dart';
import 'package:analyzer/src/analysis_options/analysis_options_parser.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/manifest/manifest_validator.dart';
import 'package:analyzer/src/pubspec/pubspec_validator.dart';
import 'package:analyzer/src/source/path_filter.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/yaml.dart';
import 'package:analyzer/src/workspace/pub.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.
StringSink errorSink = io.stderr;

/// Shared IO sink for standard out reporting.
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.
  new({@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)) {
        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++) {
        await buildSdkSummary(
          resourceProvider: PhysicalResourceProvider.INSTANCE,
          sdkPath: options.dartSdkPath!,
        );
      }

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

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

    await _analysisContextProvider.dispose();

    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<DiagnosticSeverity> _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>{};
    final analyzedFiles = <FileState>{};
    final partFiles = <FileState>{};

    // Note: This references analysisDriver via closure, so it will change over
    // time during the following analysis.
    SeverityProcessor defaultSeverityProcessor;
    defaultSeverityProcessor = (Diagnostic diagnostic) {
      var filePath = diagnostic.source.fullName;
      var file = analysisDriver!.resourceProvider.getFile(filePath);
      return determineProcessedSeverity(
        diagnostic,
        analysisDriver!.getAnalysisOptionsForFile(file),
      );
    };

    // 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 = DiagnosticSeverity.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 = DiagnosticSeverity.ERROR.ordinal;
      allResult = allResult.max(DiagnosticSeverity.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);
      if (files.isEmpty) {
        errorSink.writeln('No dart files found at: $sourcePath');
        io.exitCode = DiagnosticSeverity.ERROR.ordinal;
        return DiagnosticSeverity.ERROR;
      }

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

      // Analyze the libraries.
      var pathContext = resourceProvider.pathContext;
      final gotErrorsFor = <String>{};
      for (var path in filesToAnalyze) {
        if (file_paths.isAnalysisOptionsYaml(pathContext, path)) {
          var fileResult = analysisDriver.currentSession.getFile(path);
          if (fileResult is! FileResult) continue;
          var file = fileResult.file;
          var contextRoot =
              analysisDriver.currentSession.analysisContext.contextRoot;
          var package = contextRoot.workspace.findPackageFor(file.path);
          var sdkVersionConstraint = (package is PubPackage)
              ? package.sdkVersionConstraint
              : null;
          var parseResult = AnalysisOptionsParseSession().parse(
            sourceFactory: analysisDriver.sourceFactory,
            contextRoot: contextRoot.root,
            file: file,
            sdkVersionConstraint: sdkVersionConstraint,
          );
          var fileContent = parseResult.content;
          if (fileContent == null) continue;
          var lineInfo = fileContent.lineInfo;
          var errors = parseResult.diagnostics;
          var analysisOptions = parseResult.analysisOptions;
          await formatter.formatErrors([
            ErrorsResultImpl(
              session: analysisDriver.currentSession,
              file: file,
              content: fileContent.text,
              uri: pathContext.toUri(path),
              lineInfo: lineInfo,
              isLibrary: true,
              isPart: false,
              diagnostics: errors,
              analysisOptions: analysisOptions,
            ),
          ]);
          for (var error in errors) {
            var severity = determineProcessedSeverity(error, analysisOptions);
            if (severity != null) {
              allResult = allResult.max(severity);
            }
          }
        } else if (file_paths.isPubspecYaml(pathContext, path)) {
          var diagnostics = <Diagnostic>[];
          try {
            var file = resourceProvider.getFile(path);
            var analysisOptions = analysisDriver.currentSession.analysisContext
                .getAnalysisOptionsForFile(file);
            var content = file.readAsStringSync();
            var node = loadYamlNode(content, sourceUrl: file.toUri());

            if (node is YamlMap) {
              diagnostics.addAll(
                validatePubspec(
                  contents: node,
                  source: FileSource(file),
                  provider: resourceProvider,
                  analysisOptions: analysisOptions,
                ),
              );
            }
            if (diagnostics.isNotEmpty) {
              for (var error in diagnostics) {
                var severity = determineProcessedSeverity(
                  error,
                  analysisOptions,
                )!;
                allResult = allResult.max(severity);
              }
              var lineInfo = LineInfo.fromContent(content);
              await formatter.formatErrors([
                ErrorsResultImpl(
                  session: analysisDriver.currentSession,
                  file: file,
                  content: content,
                  uri: pathContext.toUri(path),
                  lineInfo: lineInfo,
                  isLibrary: true,
                  isPart: false,
                  diagnostics: diagnostics,
                  analysisOptions: analysisOptions,
                ),
              ]);
            }
          } catch (exception) {
            // If the file cannot be analyzed, ignore it.
          }
        } else if (file_paths.isAndroidManifestXml(pathContext, path)) {
          try {
            var file = resourceProvider.getFile(path);
            var analysisOptions = analysisDriver.getAnalysisOptionsForFile(
              file,
            );
            var content = file.readAsStringSync();
            var source = FileSource(file);
            var validator = ManifestValidator(source);
            var lineInfo = LineInfo.fromContent(content);
            var errors = validator.validate(
              content,
              analysisOptions.chromeOsManifestChecks,
            );
            await formatter.formatErrors([
              ErrorsResultImpl(
                session: analysisDriver.currentSession,
                file: file,
                content: content,
                uri: pathContext.toUri(path),
                lineInfo: lineInfo,
                isLibrary: true,
                isPart: false,
                diagnostics: errors,
                analysisOptions: analysisOptions,
              ),
            ]);
            for (var error in errors) {
              var severity = determineProcessedSeverity(
                error,
                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);

          final kind = file.kind;
          if (kind is LibraryFileKind) {
            var status = await _runAnalyzer(file, formatter, gotErrorsFor);
            allResult = allResult.max(status);
            analyzedFiles.addAll(kind.files);
          } else if (kind is PartFileKind) {
            partFiles.add(file);
          }
        }
      }
    }

    // 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 partFiles) {
      if (!analyzedFiles.contains(partFile)) {
        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) {
    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<DiagnosticSeverity> _runAnalyzer(
    FileState file,
    ErrorFormatter formatter,
    Set<String> gotErrorsFor,
  ) {
    var startTime = currentTimeMillis;
    final analysisDriver = this.analysisDriver!;
    var analysisOptions = analysisDriver.getAnalysisOptionsForFile(
      file.resource,
    );
    var analyzer = AnalyzerImpl(
      analysisOptions,
      analysisDriver,
      file,
      stats,
      startTime,
      gotErrorsFor,
    );
    return analyzer.analyze(formatter);
  }

  bool _shouldBeFatal(DiagnosticSeverity severity) =>
      severity == DiagnosticSeverity.ERROR;

  void _verifyAnalysisOptionsFileExists(CommandLineOptions options) {
    var path = options.defaultAnalysisOptionsPath;
    if (path != null) {
      if (!resourceProvider.getFile(path).exists) {
        printAndFail(
          'Options file not found: $path',
          exitCode: DiagnosticSeverity.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.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 List<AnalysisContextCollectionImpl> _toDispose = [];
  final Map<Folder, DriverBasedAnalysisContext?> _folderContexts = {};
  AnalysisContextCollectionImpl? _collection;
  DriverBasedAnalysisContext? _analysisContext;

  new(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.parent.path,
      analysisContext!.getAnalysisOptionsForFile(optionsFile).excludePatterns,
    );
  }

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

    // 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,
      packageConfigFile: _commandLineOptions!.defaultPackagesPath,
      resourceProvider: _resourceProvider,
      sdkPath: _commandLineOptions!.dartSdkPath,
      configureAnalysisOptionsBuilder: _configureAnalysisOptionsBuilder,
      fileContentCache: _fileContentCache,
      withFineDependencies: true,
    );
    _toDispose.add(_collection!);

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

  Future<void> dispose() async {
    _collection = null;
    var toDispose = _toDispose.toList();
    _toDispose.clear();
    for (var collection in toDispose) {
      await collection.dispose();
    }
  }

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

  void _configureAnalysisOptionsBuilder({
    required AnalysisOptionsBuilder analysisOptionsBuilder,
  }) {
    _commandLineOptions!.configureAnalysisOptionsBuilder(
      analysisOptionsBuilder,
    );
  }

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