// Copyright (c) 2024, 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.

/// @docImport 'package:analyzer/src/dart/analysis/driver.dart';
library;

import 'dart:async';

import 'package:analysis_server_plugin/edit/assist/assist.dart';
import 'package:analysis_server_plugin/edit/assist/dart_assist_context.dart';
import 'package:analysis_server_plugin/edit/fix/dart_fix_context.dart';
import 'package:analysis_server_plugin/edit/fix/fix.dart';
import 'package:analysis_server_plugin/plugin.dart';
import 'package:analysis_server_plugin/src/correction/assist_processor.dart';
import 'package:analysis_server_plugin/src/correction/dart_change_workspace.dart';
import 'package:analysis_server_plugin/src/correction/fix_processor.dart';
import 'package:analysis_server_plugin/src/registry.dart';
import 'package:analysis_server_plugin/src/utilities/diagnostic_messages.dart';
import 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/diagnostic/diagnostic.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/overlay_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/analysis_options/analysis_options.dart';
import 'package:analyzer/src/analysis_rule/rule_context.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_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/status.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/ignore_comments/ignore_info.dart';
import 'package:analyzer/src/lint/config.dart';
import 'package:analyzer/src/lint/linter_visitor.dart';
import 'package:analyzer/src/lint/registry.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer_plugin/channel/channel.dart';
import 'package:analyzer_plugin/protocol/protocol.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
import 'package:analyzer_plugin/protocol/protocol_constants.dart' as protocol;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as protocol;
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart';
import 'package:meta/meta.dart';

/// A pair, matching a [Diagnostic] with it's equivalent
/// [protocol.AnalysisError].
typedef _DiagnosticAndAnalysisError = ({
  Diagnostic diagnostic,
  protocol.AnalysisError analysisError,
});

typedef _PluginState = ({
  AnalysisContext analysisContext,
  List<_DiagnosticAndAnalysisError> errors,
});

/// The server that communicates with the analysis server, passing requests and
/// responses between the analysis server and individual plugins.
class PluginServer {
  /// The map of registered features for each plugin, for namespacing purposes.
  static final registries = <String, PluginRegistryImpl>{};

  /// The communication channel being used to communicate with the analysis
  /// server.
  late PluginCommunicationChannel _channel;

  final OverlayResourceProvider _resourceProvider;

  late final ByteStore _byteStore = MemoryCachingByteStore(
    NullByteStore(),
    1024 * 1024 * 256,
  );

  AnalysisContextCollectionImpl? _contextCollection;

  String? _sdkPath;

  /// Paths of priority files.
  Set<String> _priorityPaths = {};

  final List<Plugin> _plugins;

  /// The recent state of analysis reults, to be cleared on file changes.
  final _recentState = <String, _PluginState>{};

  /// The map of files currently being analyzed, mapped to their active session.
  final _filesBeingAnalyzed = <String, AnalysisSession>{};

  /// The map of files currently being resolved, mapped to their active session.
  final _filesBeingResolved = <String, AnalysisSession>{};

  /// The next modification stamp for a changed file in the [_resourceProvider].
  int _overlayModificationStamp = 0;

  /// The current subscription of [_contextCollection]'s
  /// [AnalysisDriverScheduler.events] Stream. This must be cancelled when
  /// [_contextCollection] is disposed.
  StreamSubscription<Object>? _eventsSubscription;

  /// The map of configurations for each directory, mapped to plugin names.
  Map<String, Map<String, protocol.PluginConfiguration>> _configurations = {};

  /// The context roots that this plugin is configured for, if received.
  List<protocol.ContextRoot>? _contextRoots;

  /// The analysis roots that the client is analyzing, if received.
  protocol.AnalysisSetAnalysisRootsParams? _analysisRoots;

  /// Whether we have received an 'analysis.setAnalysisRoots' request.
  ///
  /// If we have, we can ignore 'analysis.setContextRoots' requests.
  bool _receivedAnalysisRoots = false;

  /// Whether to fall back to the global [Registry.ruleRegistry] if a plugin
  /// registry is not found by name.
  ///
  /// Only older Dart SDKs call `PluginServer.new`, which sets this to `true`.
  /// Otherwise it is `false`.
  final bool _useGlobalRegistry;

  PluginServer({
    required ResourceProvider resourceProvider,
    required List<Plugin> plugins,
  }) : _resourceProvider = OverlayResourceProvider(resourceProvider),
       _plugins = plugins,
       _useGlobalRegistry = true {
    int i = 0;
    for (var plugin in plugins) {
      var registry = PluginRegistryImpl(plugin.name);
      // For this unnamed (old) constructor, we were not tracking them by name
      // so we do this (use '$i') simply to store the registries uniquely.
      //
      // `registries` was previously only used for the `PLUGIN_REQUEST_DETAILS`
      // request handling.
      //
      // Now, we plan on deprecating this constructor and move to `new2`, since
      // that allows us to track plugins by name and fix issues with ignores and
      // avoiding diagnostic collisions.
      //
      // When initializing with this constructor we can't use `registries` to
      // find them by name, so we use the main `Registry.ruleRegistry` to find
      // the rules instead.
      registries['$i'] = registry;
      plugin.register(registry);
      i++;
    }
    PluginRegistryImpl.registerIgnoreProducerGenerators();
  }

  PluginServer.new2({
    required ResourceProvider resourceProvider,
    required Map<String, Plugin> plugins,
  }) : _resourceProvider = OverlayResourceProvider(resourceProvider),
       _plugins = plugins.values.toList(),
       _useGlobalRegistry = false {
    for (var MapEntry(key: name, value: plugin) in plugins.entries) {
      var registry = PluginRegistryImpl(plugin.name);
      registries[name.toLowerCase()] = registry;
      plugin.register(registry);
    }
    PluginRegistryImpl.registerIgnoreProducerGenerators();
  }

  @visibleForTesting
  AnalysisContextCollectionImpl? get contextCollection => _contextCollection;

  @visibleForTesting
  Set<String> get priorityPaths => {..._priorityPaths};

  /// Handles an 'analysis.setPriorityFiles' request.
  ///
  /// Throws a [RequestFailure] if the request could not be handled.
  Future<protocol.AnalysisSetPriorityFilesResult>
  handleAnalysisSetPriorityFiles(
    protocol.AnalysisSetPriorityFilesParams parameters,
  ) async {
    _priorityPaths = parameters.files.toSet();
    _updatePriorityFiles();
    return protocol.AnalysisSetPriorityFilesResult();
  }

  /// Handles an 'edit.getAssists' request.
  ///
  /// Throws a [RequestFailure] if the request could not be handled.
  Future<protocol.EditGetAssistsResult> handleEditGetAssists(
    protocol.EditGetAssistsParams parameters,
  ) async {
    var path = parameters.file;

    var recentState = _recentState[path];
    if (recentState == null) {
      return protocol.EditGetAssistsResult(const []);
    }

    var (:analysisContext, :errors) = recentState;
    var libraryResult = await analysisContext.currentSession
        .getResolvedLibraryContaining(path);
    if (libraryResult is! ResolvedLibraryResult) {
      return protocol.EditGetAssistsResult(const []);
    }
    var unitResult = libraryResult.unitWithPath(path);
    if (unitResult is! ResolvedUnitResult) {
      return protocol.EditGetAssistsResult(const []);
    }

    var context = DartAssistContext(
      // TODO(srawlins): Use a real instrumentation service. Other
      // implementations get InstrumentationService from AnalysisServer.
      InstrumentationService.NULL_SERVICE,
      DartChangeWorkspace([analysisContext.currentSession]),
      libraryResult,
      unitResult,
      parameters.offset,
      parameters.length,
    );

    List<Assist> assists;
    try {
      assists = await computeAssists(context);
    } on InconsistentAnalysisException {
      // TODO(srawlins): Is it important to at least log this? Or does it
      // happen on the regular?
      assists = [];
    }

    if (assists.isEmpty) {
      return protocol.EditGetAssistsResult(const []);
    }

    var corrections = [
      for (var assist in assists..sort(Assist.compareAssists))
        protocol.PrioritizedSourceChange(assist.kind.priority, assist.change),
    ];
    return protocol.EditGetAssistsResult(corrections);
  }

  /// Handles an 'edit.getFixes' request.
  ///
  /// Throws a [RequestFailure] if the request could not be handled.
  Future<protocol.EditGetFixesResult> handleEditGetFixes(
    protocol.EditGetFixesParams parameters,
  ) async {
    var path = parameters.file;
    var offset = parameters.offset;

    var recentState = _recentState[path];
    if (recentState == null) {
      return protocol.EditGetFixesResult(const []);
    }

    var (:analysisContext, :errors) = recentState;

    var libraryResult = await analysisContext.currentSession
        .getResolvedLibraryContaining(path);
    if (libraryResult is! ResolvedLibraryResult) {
      return protocol.EditGetFixesResult(const []);
    }
    var unitResult = libraryResult.unitWithPath(path);
    if (unitResult is! ResolvedUnitResult) {
      return protocol.EditGetFixesResult(const []);
    }

    var lineInfo = unitResult.lineInfo;
    var requestLine = lineInfo.getLocation(offset).lineNumber;

    var diagnostics = errors.map((e) => e.diagnostic);

    var lintAtOffset = errors.where((error) {
      var errorLine = lineInfo.getLocation(error.diagnostic.offset).lineNumber;
      return errorLine == requestLine;
    });
    if (lintAtOffset.isEmpty) return protocol.EditGetFixesResult(const []);

    var errorFixesList = <protocol.AnalysisErrorFixes>[];

    var workspace = DartChangeWorkspace([analysisContext.currentSession]);
    for (var (:diagnostic, :analysisError) in lintAtOffset) {
      var context = DartFixContext(
        // TODO(srawlins): Use a real instrumentation service. Other
        // implementations get InstrumentationService from AnalysisServer.
        instrumentationService: InstrumentationService.NULL_SERVICE,
        workspace: workspace,
        libraryResult: libraryResult,
        unitResult: unitResult,
        error: diagnostic,
      );

      List<Fix> fixes;
      try {
        // TODO(srawlins): Somehow wrap each ProducerGenerator invocation in a
        // zone, to support `print` capturing per-plugin.
        fixes = await computeFixes(context, diagnostics: diagnostics);
      } on InconsistentAnalysisException {
        // TODO(srawlins): Is it important to at least log this? Or does it
        // happen on the regular?
        fixes = [];
      }

      if (fixes.isNotEmpty) {
        fixes.sort(Fix.compareFixes);
        var errorFixes = protocol.AnalysisErrorFixes(analysisError);
        errorFixesList.add(errorFixes);
        for (var fix in fixes) {
          errorFixes.fixes.add(protocol.PrioritizedSourceChange(1, fix.change));
        }
      }
    }

    return protocol.EditGetFixesResult(errorFixesList);
  }

  /// Handles a 'plugin.versionCheck' request.
  Future<protocol.PluginVersionCheckResult> handlePluginVersionCheck(
    protocol.PluginVersionCheckParams parameters,
  ) async {
    // TODO(srawlins): It seems improper for _this_ method to be the point where
    // the SDK path is configured...
    _sdkPath = parameters.sdkPath;
    return protocol.PluginVersionCheckResult(true, 'Plugin Server', '0.0.1', [
      '*.dart',
    ]);
  }

  /// Initializes each of the registered plugins.
  Future<void> initialize() async {
    await Future.wait(
      _plugins.map((p) => p.start()).whereType<Future<Object?>>(),
    );
  }

  /// Starts this plugin by listening to the given communication [channel].
  void start(PluginCommunicationChannel channel) {
    _channel = channel;
    _channel.listen(
      _handleRequestZoned,
      // TODO(srawlins): Implement.
      onDone: () {},
    );
  }

  /// Waits until all background drivers in the context collection are idle.
  @visibleForTesting
  Future<void> waitForIdle() async {
    if (_contextCollection case var contextCollection?) {
      await Future.wait([
        for (var analysisContext in contextCollection.contexts)
          analysisContext.driver.scheduler.waitForIdle(),
      ]);
    }
  }

  /// This method is invoked when a new instance of [AnalysisContextCollection]
  /// is created, so the plugin can perform initial analysis of analyzed files.
  Future<void> _analyzeAllFilesInContextCollection({
    required AnalysisContextCollectionImpl contextCollection,
  }) async {
    await _forAnalysisContexts(contextCollection, (analysisContext) async {
      final driver = analysisContext.driver;
      var paths = analysisContext.contextRoot
          .analyzedFiles()
          // TODO(srawlins): Enable analysis on other files, even if only
          // YAML files for analysis options and pubspec analysis and quick
          // fixes.
          .where((p) => file_paths.isDart(_resourceProvider.pathContext, p))
          .toSet();

      for (var path in paths) {
        driver.addFile(path);
      }
    });
  }

  /// Analyzes the compilation units in [diagnosticsContext] with the enabled
  /// plugin rules and sends analysis error notifications for each compilation
  /// unit.
  Future<void> _analyzeAndSendDiagnostics({
    required AnalysisContext analysisContext,
    required AnalysisOptionsImpl analysisOptions,
    required _LibraryDiagnosticsContext diagnosticsContext,
  }) async {
    var context = diagnosticsContext.ruleContext;
    var allUnits = diagnosticsContext.allUnits;
    var diagnosticListeners = diagnosticsContext.diagnosticListeners;

    // A mapping from each diagnostic code to its corresponding plugin.
    var pluginCodeMapping = <DiagnosticCode, String>{};

    // A mapping from each diagnostic code to its configured severity.
    var severityMapping = <DiagnosticCode, protocol.AnalysisErrorSeverity?>{};

    var protocolConfigs = _getConfigurationsForFile(
      context.definingUnit.file.path,
    );
    var configurations = [
      if (protocolConfigs != null)
        for (var entry in protocolConfigs.entries)
          _toAnalyzerConfiguration(entry.key, entry.value)
      else
        ...analysisOptions.pluginConfigurations,
    ];

    for (var configuration in configurations) {
      // TODO(srawlins): Enable timing similar to what the linter package's
      // `benchmark.dart` script does.
      var ruleVisitorRegistry = RuleVisitorRegistryImpl(enableTiming: false);
      runZonedGuarded(
        () => _computeDiagnosticsFromPlugin(
          configuration,
          analysisContext: analysisContext,
          allUnits: allUnits,
          ruleVisitorRegistry: ruleVisitorRegistry,
          context: context,
          pluginCodeMapping: pluginCodeMapping,
          severityMapping: severityMapping,
        ),
        _zoneOnErrorHandler,
        zoneSpecification: ZoneSpecification(
          print: (_, _, _, line) => _print(configuration.name, line),
        ),
      );
    }

    // The list of the `AnalysisError`s and their associated
    // `protocol.AnalysisError`s.
    var diagnosticsAndAnalysisErrors =
        <({Diagnostic diagnostic, protocol.AnalysisError analysisError})>[];

    diagnosticListeners.forEach((unitContext, listener) {
      var ignoreInfo = IgnoreInfo.forDart(
        unitContext.unit,
        unitContext.content,
      );
      var diagnostics = listener.diagnostics.where((e) {
        var pluginName = pluginCodeMapping[e.diagnosticCode];
        if (pluginName == null) {
          // If [e] is somehow not mapped, something is wrong; but don't mark it
          // as ignored.
          return true;
        }
        return !ignoreInfo.ignored(e, pluginName: pluginName);
      });

      // The list of the `AnalysisError`s and their associated
      // `protocol.AnalysisError`s.
      var unitDiagnosticsAndAnalysisErrors =
          <({Diagnostic diagnostic, protocol.AnalysisError analysisError})>[];

      for (var diagnostic in diagnostics) {
        unitDiagnosticsAndAnalysisErrors.add((
          diagnostic: diagnostic,
          analysisError: protocol.AnalysisError(
            severityMapping[diagnostic.diagnosticCode] ??
                protocol.AnalysisErrorSeverity.INFO,
            protocol.AnalysisErrorType.STATIC_WARNING,
            _locationFor(unitContext.unit, unitContext.file.path, diagnostic),
            diagnostic.message,
            diagnostic.diagnosticCode.lowerCaseName,
            correction: diagnostic.correctionMessage,
            contextMessages: diagnostic.contextMessages
                .map(
                  (message) => newDiagnosticMessage(
                    message,
                    analysisContext.currentSession,
                    lineInfo: message.filePath == unitContext.file.path
                        ? unitContext.unit.lineInfo
                        : null,
                  ),
                )
                .nonNulls
                .toList(),
            // TODO(srawlins): Use a valid value here.
            hasFix: true,
          ),
        ));
      }

      _recentState[unitContext.file.path] = (
        analysisContext: analysisContext,
        errors: [...unitDiagnosticsAndAnalysisErrors],
      );

      diagnosticsAndAnalysisErrors.addAll(unitDiagnosticsAndAnalysisErrors);
    });

    // A map that has a key for each unit's path. It is important to collect the
    // analysis errors for each unit, even if it has none. We must send a
    // notification for each unit, even if there are no analysis errors to
    // report.
    var analysisErrorsByPath = <String, List<protocol.AnalysisError>>{
      for (var unit in allUnits) unit.file.path: [],
    };
    for (var (diagnostic: _, :analysisError) in diagnosticsAndAnalysisErrors) {
      analysisErrorsByPath[analysisError.location.file]!.add(analysisError);
    }
    for (var MapEntry(key: path, value: analysisErrors)
        in analysisErrorsByPath.entries) {
      _channel.sendNotification(
        protocol.AnalysisErrorsParams(path, analysisErrors).toNotification(),
      );
    }
  }

  /// Whether this plugin isolate can rely on _parsed_ analysis results to
  /// analyze [libraryPath], such that none of the enabled rules require full
  /// resolution.
  bool _canUseParsedResult(
    AnalysisOptionsImpl analysisOptions,
    String libraryPath,
  ) {
    var protocolConfigs = _getConfigurationsForFile(libraryPath);
    var configurations = [
      if (protocolConfigs != null)
        for (var entry in protocolConfigs.entries)
          _toAnalyzerConfiguration(entry.key, entry.value)
      else
        ...analysisOptions.pluginConfigurations,
    ];

    for (var configuration in configurations) {
      if (!configuration.isEnabled) continue;
      RegistryBase? registry = registries[configuration.name.toLowerCase()];
      if (registry == null) {
        if (!_useGlobalRegistry) continue;
        registry = Registry.ruleRegistry;
      }
      var rules = registry.enabled({
        for (var entry in configuration.diagnosticConfigs.entries)
          entry.key.toLowerCase(): entry.value,
      });
      if (rules.any((r) => !r.canUseParsedResult)) return false;
    }
    return true;
  }

  /// Computes diagnostics for the plugin configured with [configuration].
  ///
  /// [pluginCodeMapping] and [severityMapping] are output parameters; this
  /// function adds mappings, which can be used at the call-site outside of the
  /// [Zone].
  void _computeDiagnosticsFromPlugin(
    PluginConfiguration configuration, {
    required AnalysisContext analysisContext,
    required List<RuleContextUnit> allUnits,
    required RuleVisitorRegistryImpl ruleVisitorRegistry,
    required RuleContext context,
    required Map<DiagnosticCode, String> pluginCodeMapping,
    required Map<DiagnosticCode, protocol.AnalysisErrorSeverity?>
    severityMapping,
  }) {
    if (!configuration.isEnabled) return;
    RegistryBase? registry = registries[configuration.name.toLowerCase()];
    if (registry == null) {
      if (!_useGlobalRegistry) {
        return;
      }
      // Only use the global registry if the `.new` constructor was used (by
      // older Dart SDKs). We'll remove this when we break from that API.
      registry = Registry.ruleRegistry;
    }
    var rules = registry.enabled({
      for (var entry in configuration.diagnosticConfigs.entries)
        entry.key.toLowerCase(): entry.value,
    });

    for (var code in rules.expand((r) => r.diagnosticCodes)) {
      pluginCodeMapping.putIfAbsent(code, () => configuration.name);
      severityMapping.putIfAbsent(
        code,
        () => _configuredSeverity(configuration, code),
      );
    }

    for (var rule in rules) {
      // TODO(srawlins): Enable timing similar to what the linter package's
      // `benchmark.dart` script does.
      rule.registerNodeProcessors(ruleVisitorRegistry, context);
    }

    // Now to perform the actual analysis.
    for (var currentUnit in allUnits) {
      if (!analysisContext.contextRoot.isAnalyzed(currentUnit.file.path)) {
        // If the file isn't analyzed, then we shouldn't be running any rules
        // on it. This can happen when the library has parts that aren't
        // analyzed (e.g. because they are excluded via analysis options).
        continue;
      }
      for (var rule in rules) {
        rule.reporter = currentUnit.diagnosticReporter;
      }

      if (context is RuleContextWithResolvedResults) {
        context.currentUnit = currentUnit;
      } else if (context is RuleContextWithParsedResults) {
        context.currentUnit = currentUnit;
      }
      currentUnit.unit.accept(
        AnalysisRuleVisitor(
          ruleVisitorRegistry,
          shouldPropagateExceptions: true,
        ),
      );
    }

    // Now that all lint rules have visited the code in each of the compilation
    // units, we can accept each lint rule's `afterLibrary` hook.
    if (context is RuleContextWithResolvedResults) {
      context.currentUnit = context.definingUnit;
    } else if (context is RuleContextWithParsedResults) {
      context.currentUnit = context.definingUnit;
    }
    AnalysisRuleVisitor(ruleVisitorRegistry).afterLibrary();
  }

  /// Converts the severity of [code] into a [protocol.AnalysisErrorSeverity].
  protocol.AnalysisErrorSeverity? _configuredSeverity(
    PluginConfiguration configuration,
    DiagnosticCode code,
  ) {
    var configuredSeverity =
        configuration.diagnosticConfigs[code.lowerCaseName]?.severity;
    if (configuredSeverity != null &&
        configuredSeverity != ConfiguredSeverity.enable) {
      var severityName = configuredSeverity.name.toUpperCase();
      var severity = protocol.AnalysisErrorSeverity.values
          .asNameMap()[severityName];
      assert(
        severity != null,
        'Invalid configured severity: ${configuredSeverity.name}',
      );
      return severity;
    }

    // Fall back to the declared severity of [code].
    var severityName = code.severity.name.toUpperCase();
    var severity = protocol.AnalysisErrorSeverity.values
        .asNameMap()[code.severity.name];
    assert(severity != null, 'Invalid severity: $severityName');
    return severity;
  }

  Future<void> _createContextCollection(List<String> includedPaths) async {
    if (_contextCollection case var contextCollection?) {
      _contextCollection = null;
      await contextCollection.dispose();
    }
    if (_eventsSubscription case var eventsSubscription?) {
      _eventsSubscription = null;
      await eventsSubscription.cancel();
    }

    var contextCollection = AnalysisContextCollectionImpl(
      resourceProvider: _resourceProvider,
      includedPaths: includedPaths,
      byteStore: _byteStore,
      sdkPath: _sdkPath,
      fileContentCache: FileContentCache(_resourceProvider),
      configureAnalysisOptionsBuilder:
          // Disable extra warning computation and lint computation, because
          // these are reported in the main analysis server isolate, not in the
          // plugins isolate.
          ({required analysisOptionsBuilder}) => analysisOptionsBuilder
            ..warning = false
            ..lint = false,
      withFineDependencies: true,
      drainStreams: false,
    );
    _contextCollection = contextCollection;
    _updatePriorityFiles();
    _eventsSubscription = contextCollection.scheduler.events.listen((event) {
      if (event is ResolvedUnitResult) {
        _handleResolvedUnit(event);
      } else if (event is AnalysisStatus) {
        _handleAnalysisStatus(event);
      } else if (event is ErrorsResult) {
        _handleErrorsResult(event);
      }
    });
    await _analyzeAllFilesInContextCollection(
      contextCollection: contextCollection,
    );
  }

  /// Invokes [fn] first for priority analysis contexts, then for the rest.
  Future<void> _forAnalysisContexts(
    AnalysisContextCollectionImpl contextCollection,
    Future<void> Function(DriverBasedAnalysisContext analysisContext) fn,
  ) async {
    var nonPriorityAnalysisContexts = <DriverBasedAnalysisContext>[];
    for (var analysisContext in contextCollection.contexts) {
      if (_isPriorityAnalysisContext(analysisContext)) {
        await fn(analysisContext);
      } else {
        nonPriorityAnalysisContexts.add(analysisContext);
      }
    }

    for (var analysisContext in nonPriorityAnalysisContexts) {
      await fn(analysisContext);
    }
  }

  /// Returns the map of plugin configurations for the given [filePath].
  ///
  /// Since there could be nested directories with different configuration sets,
  /// we find the "best matching" directory in [_configurations].
  ///
  /// The best matching path is the most specific one (i.e., the longest path)
  /// that is either identical to [filePath] or contains [filePath].
  Map<String, protocol.PluginConfiguration>? _getConfigurationsForFile(
    String filePath,
  ) {
    String? bestMatchingPath;
    for (var path in _configurations.keys) {
      if (path == filePath ||
          _resourceProvider.pathContext.isWithin(path, filePath)) {
        if (bestMatchingPath == null || path.length > bestMatchingPath.length) {
          bestMatchingPath = path;
        }
      }
    }
    if (bestMatchingPath != null) {
      return _configurations[bestMatchingPath];
    }
    return null;
  }

  /// Computes the response for the given [request].
  Future<Response?> _getResponse(Request request, int requestTime) async {
    ResponseResult? result;
    switch (request.method) {
      case protocol.ANALYSIS_REQUEST_HANDLE_WATCH_EVENTS:
        var params = protocol.AnalysisHandleWatchEventsParams.fromRequest(
          request,
        );
        result = await _handleAnalysisWatchEvents(params);

      case protocol.ANALYSIS_REQUEST_SET_CONTEXT_ROOTS:
        var params = protocol.AnalysisSetContextRootsParams.fromRequest(
          request,
        );
        result = await _handleAnalysisSetContextRoots(params);

      case protocol.ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS:
        var params = protocol.AnalysisSetAnalysisRootsParams.fromRequest(
          request,
        );
        result = await _handleAnalysisSetAnalysisRoots(params);

      case protocol.ANALYSIS_REQUEST_SET_PRIORITY_FILES:
        var params = protocol.AnalysisSetPriorityFilesParams.fromRequest(
          request,
        );
        result = await handleAnalysisSetPriorityFiles(params);

      case protocol.ANALYSIS_REQUEST_UPDATE_CONTENT:
        var params = protocol.AnalysisUpdateContentParams.fromRequest(request);
        result = await _handleAnalysisUpdateContent(params);

      case protocol.EDIT_REQUEST_GET_ASSISTS:
        var params = protocol.EditGetAssistsParams.fromRequest(request);
        result = await handleEditGetAssists(params);

      case protocol.EDIT_REQUEST_GET_FIXES:
        var params = protocol.EditGetFixesParams.fromRequest(request);
        result = await handleEditGetFixes(params);

      case protocol.PLUGIN_REQUEST_DETAILS:
        var details = <protocol.PluginDetails>[];
        for (var pluginRegistry in registries.values) {
          var assists = [
            for (var assistKind in pluginRegistry.assistKinds)
              protocol.AssistDescription(assistKind.id, assistKind.message),
          ];
          var fixes = [
            for (var MapEntry(key: fixKind, value: codes)
                in pluginRegistry.fixKinds.entries)
              protocol.FixDescription(fixKind.id, fixKind.message, codes),
          ];
          details.add(
            protocol.PluginDetails(
              pluginRegistry.pluginName,
              pluginRegistry.lintRules.keys.toList(),
              pluginRegistry.warningRules.keys.toList(),
              assists,
              fixes,
            ),
          );
        }
        result = protocol.PluginDetailsResult(details);

      case protocol.PLUGIN_REQUEST_SHUTDOWN:
        await Future.wait(
          _plugins.map((p) => p.shutDown()).whereType<Future<Object?>>(),
        );
        _channel.sendResponse(
          protocol.PluginShutdownResult().toResponse(request.id, requestTime),
        );
        _channel.close();
        return null;

      case protocol.PLUGIN_REQUEST_VERSION_CHECK:
        var params = protocol.PluginVersionCheckParams.fromRequest(request);
        result = await handlePluginVersionCheck(params);

      case protocol.ANALYSIS_REQUEST_SET_CONFIGURATIONS:
        var params = protocol.AnalysisSetConfigurationsParams.fromRequest(
          request,
        );
        result = await _handleAnalysisSetConfigurations(params);

      default:
        // Anything else is unsupported.
        result = null;
    }
    if (result == null) {
      return Response(
        request.id,
        requestTime,
        error: RequestErrorFactory.unknownRequest(request.method),
      );
    }
    return result.toResponse(request.id, requestTime);
  }

  /// Computes the effective included paths for this plugin by intersecting
  /// any client-specified [_analysisRoots] with [_contextRoots].
  List<String> _computeEffectiveIncludedPaths() {
    var contextRoots = _contextRoots;
    var analysisRoots = _analysisRoots;

    if (contextRoots == null) {
      return analysisRoots?.included ?? const [];
    }

    if (analysisRoots == null) {
      return [for (var root in contextRoots) root.root];
    }

    var pathContext = _resourceProvider.pathContext;
    var effectiveIncluded = <String>{};

    for (var contextRoot in contextRoots) {
      var contextPath = contextRoot.root;

      // Skip if the context root is completely excluded by client excluded
      // paths.
      var isContextExcluded = analysisRoots.excluded.any(
        (e) => pathContext.isWithin(e, contextPath) || e == contextPath,
      );
      if (isContextExcluded) continue;

      // Check if any client included path contains this context root.
      var isContextCovered = analysisRoots.included.any(
        (i) => pathContext.isWithin(i, contextPath) || i == contextPath,
      );
      if (isContextCovered) {
        effectiveIncluded.add(contextPath);
      } else {
        // Check for client included subpaths within this context root.
        for (var clientIncluded in analysisRoots.included) {
          if (pathContext.isWithin(contextPath, clientIncluded)) {
            effectiveIncluded.add(clientIncluded);
          }
        }
      }
    }

    return effectiveIncluded.toList();
  }

  /// Handles an 'analysis.setAnalysisRoots' request.
  Future<protocol.AnalysisSetAnalysisRootsResult>
  _handleAnalysisSetAnalysisRoots(
    protocol.AnalysisSetAnalysisRootsParams parameters,
  ) async {
    _receivedAnalysisRoots = true;
    _analysisRoots = parameters;
    await _createContextCollection(_computeEffectiveIncludedPaths());
    return protocol.AnalysisSetAnalysisRootsResult();
  }

  Future<ResponseResult?> _handleAnalysisSetConfigurations(
    protocol.AnalysisSetConfigurationsParams params,
  ) async {
    _configurations = params.configurations;
    if (_contextCollection case var contextCollection?) {
      var includedPaths = contextCollection.contexts
          .map((e) => e.contextRoot.root.path)
          .toList();
      await _createContextCollection(includedPaths);
    }
    return protocol.AnalysisSetConfigurationsResult();
  }

  /// Handles an 'analysis.setContextRoots' request.
  Future<protocol.AnalysisSetContextRootsResult> _handleAnalysisSetContextRoots(
    protocol.AnalysisSetContextRootsParams parameters,
  ) async {
    _contextRoots = parameters.roots;
    // Allow any "simultaneous" requests to be processed.
    await Future<void>.delayed(Duration.zero);
    if (_receivedAnalysisRoots) {
      return protocol.AnalysisSetContextRootsResult();
    }

    await _createContextCollection(_computeEffectiveIncludedPaths());
    return protocol.AnalysisSetContextRootsResult();
  }

  void _handleAnalysisStatus(AnalysisStatus status) {
    _channel.sendNotification(
      protocol.PluginStatusParams(
        analysis: protocol.AnalysisStatus(status.isWorking),
      ).toNotification(),
    );
  }

  /// Handles an 'analysis.updateContent' request.
  ///
  /// Throws a [RequestFailure] if the request could not be handled.
  Future<protocol.AnalysisUpdateContentResult> _handleAnalysisUpdateContent(
    protocol.AnalysisUpdateContentParams parameters,
  ) async {
    var changedPaths = <String>{};
    var paths = parameters.files;
    paths.forEach((String path, Object overlay) {
      // Prepare the old overlay contents.
      String? oldContent;
      try {
        oldContent = _resourceProvider.getFile(path).readAsStringSync();
      } catch (_) {
        // Leave `oldContent` empty.
      }

      // Prepare the new contents.
      String? newContent;
      if (overlay is protocol.AddContentOverlay) {
        newContent = overlay.content;
      } else if (overlay is protocol.ChangeContentOverlay) {
        if (oldContent == null) {
          // The server should only send a ChangeContentOverlay if there is
          // already an existing overlay for the source.
          throw RequestFailure(
            RequestErrorFactory.invalidOverlayChangeNoContent(),
          );
        }
        try {
          newContent = protocol.SourceEdit.applySequence(
            oldContent,
            overlay.edits,
          );
        } on RangeError {
          throw RequestFailure(
            RequestErrorFactory.invalidOverlayChangeInvalidEdit(),
          );
        }
      } else if (overlay is protocol.RemoveContentOverlay) {
        newContent = null;
      }

      if (newContent != null) {
        if (newContent != oldContent) {
          _resourceProvider.setOverlay(
            path,
            content: newContent,
            modificationStamp: _overlayModificationStamp++,
          );
          changedPaths.add(path);
        }
      } else {
        if (_resourceProvider.hasOverlay(path)) {
          _resourceProvider.removeOverlay(path);
          changedPaths.add(path);
        }
      }
    });
    await _handleContentChanged(modifiedPaths: changedPaths.toList());
    return protocol.AnalysisUpdateContentResult();
  }

  /// Handles an 'analysis.handleWatchEvents' request.
  Future<protocol.AnalysisHandleWatchEventsResult> _handleAnalysisWatchEvents(
    protocol.AnalysisHandleWatchEventsParams parameters,
  ) async {
    final addedPaths = parameters.events
        .where((e) => e.type == protocol.WatchEventType.ADD)
        .map((e) => e.path)
        .toList();
    final modifiedPaths = parameters.events
        .where((e) => e.type == protocol.WatchEventType.MODIFY)
        .map((e) => e.path)
        .toList();
    final removedPaths = parameters.events
        .where((e) => e.type == protocol.WatchEventType.REMOVE)
        .map((e) => e.path)
        .toList();

    await _handleContentChanged(
      addedPaths: addedPaths,
      modifiedPaths: modifiedPaths,
      removedPaths: removedPaths,
    );

    return protocol.AnalysisHandleWatchEventsResult();
  }

  /// Handles added files, modified files, and removed files.
  Future<void> _handleContentChanged({
    List<String> addedPaths = const [],
    List<String> modifiedPaths = const [],
    List<String> removedPaths = const [],
  }) async {
    if (_contextCollection case var contextCollection?) {
      _filesBeingAnalyzed.clear();
      _filesBeingResolved.clear();
      await _forAnalysisContexts(contextCollection, (analysisContext) async {
        final driver = analysisContext.driver;
        for (var path in modifiedPaths) {
          driver.changeFile(path);
        }
        for (var path in removedPaths) {
          driver.removeFile(path);
        }
        for (var path in addedPaths) {
          driver.addFile(path);
        }
      });
      for (var path in removedPaths) {
        _channel.sendNotification(
          protocol.AnalysisErrorsParams(path, []).toNotification(),
        );
      }
    }
  }

  void _handleErrorsResult(ErrorsResult event) {
    var path = event.path;
    var session = event.session;
    var analysisContext = session.analysisContext;
    if (analysisContext is! DriverBasedAnalysisContext) return;
    if (!analysisContext.contextRoot.isAnalyzed(path)) return;

    var file = _resourceProvider.getFile(path);
    var analysisOptions =
        analysisContext.getAnalysisOptionsForFile(file) as AnalysisOptionsImpl;
    if (_canUseParsedResult(analysisOptions, path)) {
      var fileState = analysisContext.driver.fsState.getFileForPath(path);
      var libraryPath = switch (fileState.kind) {
        PartFileKind(:var library?) => library.file.path,
        _ => path,
      };
      var diagnosticsContext = _LibraryDiagnosticsContext.forParsedLibrary(
        analysisContext,
        libraryPath,
        _resourceProvider,
      );
      if (diagnosticsContext != null) {
        _analyzeAndSendDiagnostics(
          analysisContext: analysisContext,
          analysisOptions: analysisOptions,
          diagnosticsContext: diagnosticsContext,
        );
      }
      return;
    }
    var activeSession = _filesBeingResolved[path];
    if (activeSession != session) {
      _filesBeingResolved[path] = session;
      analysisContext.driver.getResolvedUnit(path);
    }
  }

  Future<void> _handleRequest(Request request) async {
    var requestTime = DateTime.now().millisecondsSinceEpoch;
    var id = request.id;
    Response? response;
    try {
      response = await _getResponse(request, requestTime);
    } on RequestFailure catch (exception) {
      response = Response(id, requestTime, error: exception.error);
    } catch (exception, stackTrace) {
      response = Response(
        id,
        requestTime,
        error: protocol.RequestError(
          protocol.RequestErrorCode.PLUGIN_ERROR,
          exception.toString(),
          stackTrace: stackTrace.toString(),
        ),
      );
    }
    if (response != null) {
      _channel.sendResponse(response);
    }
  }

  Future<void> _handleRequestZoned(Request request) async {
    await runZonedGuarded(
      () => _handleRequest(request),
      _zoneOnErrorHandler,
      zoneSpecification: ZoneSpecification(
        print: (_, _, _, line) => _print('<shared plugin code>', line),
      ),
    );
  }

  Future<void> _handleResolvedUnit(ResolvedUnitResult unitResult) async {
    var analysisContext = unitResult.session.analysisContext;
    if (!analysisContext.contextRoot.isAnalyzed(unitResult.path)) {
      return;
    }
    if (unitResult.unit.declaredFragment !=
        unitResult.libraryElement.firstFragment) {
      return;
    }
    var session = unitResult.session;
    var activeSession = _filesBeingAnalyzed[unitResult.path];
    if (activeSession == session) {
      return;
    }
    _filesBeingAnalyzed[unitResult.path] = session;
    try {
      var file = _resourceProvider.getFile(unitResult.path);
      var analysisOptions = analysisContext.getAnalysisOptionsForFile(file);
      var libraryResult = await analysisContext.currentSession
          .getResolvedLibrary(unitResult.path);
      if (libraryResult is! ResolvedLibraryResult) return;

      var diagnosticsContext = _LibraryDiagnosticsContext.forResolvedLibrary(
        analysisContext,
        libraryResult,
      );
      if (diagnosticsContext != null) {
        await _analyzeAndSendDiagnostics(
          analysisContext: analysisContext,
          analysisOptions: analysisOptions as AnalysisOptionsImpl,
          diagnosticsContext: diagnosticsContext,
        );
      }
    } on InconsistentAnalysisException {
      // State changed during resolution; a subsequent pass will handle it.
    }
  }

  bool _isPriorityAnalysisContext(AnalysisContext analysisContext) =>
      _priorityPaths.any(analysisContext.contextRoot.isAnalyzed);

  void _print(String pluginName, String message) {
    _channel.sendNotification(
      protocol.PluginPrintParams(
        protocol.PluginPrint(
          pluginName,
          message,
          DateTime.now().millisecondsSinceEpoch,
        ),
      ).toNotification(),
    );
  }

  PluginConfiguration _toAnalyzerConfiguration(
    String name,
    protocol.PluginConfiguration protocolConfig,
  ) {
    var diagnosticConfigs = <String, DiagnosticConfig>{};
    for (var entry in protocolConfig.diagnosticSeverities.entries) {
      var severityStr = entry.value.toLowerCase();
      var severity = switch (severityStr) {
        'error' => ConfiguredSeverity.error,
        'warning' => ConfiguredSeverity.warning,
        'info' => ConfiguredSeverity.info,
        'ignore' => ConfiguredSeverity.disable,
        'disable' => ConfiguredSeverity.disable,
        'enable' => ConfiguredSeverity.enable,
        _ => null,
      };
      if (severity != null) {
        diagnosticConfigs[entry.key] = DiagnosticConfig(
          name: entry.key,
          severity: severity,
        );
      }
    }

    return PluginConfiguration(
      name: name,
      source: VersionedPluginSource(constraint: ''),
      isEnabled: protocolConfig.enabled,
      diagnosticConfigs: diagnosticConfigs,
    );
  }

  void _updatePriorityFiles() {
    if (_contextCollection case var contextCollection?) {
      for (var analysisContext in contextCollection.contexts) {
        analysisContext.driver.priorityFiles = _priorityPaths.toList();
      }
    }
  }

  /// The `onError` handler for use in [runZonedGuarded].
  void _zoneOnErrorHandler(Object error, StackTrace stackTrace) {
    _channel.sendNotification(
      protocol.PluginErrorParams(
        false /* isFatal */,
        error.toString(),
        stackTrace.toString(),
      ).toNotification(),
    );
  }

  static protocol.Location _locationFor(
    CompilationUnit unit,
    String path,
    Diagnostic diagnostic,
  ) {
    var lineInfo = unit.lineInfo;
    var startLocation = lineInfo.getLocation(diagnostic.offset);
    var endLocation = lineInfo.getLocation(
      diagnostic.offset + diagnostic.length,
    );
    return protocol.Location(
      path,
      diagnostic.offset,
      diagnostic.length,
      startLocation.lineNumber,
      startLocation.columnNumber,
      endLine: endLocation.lineNumber,
      endColumn: endLocation.columnNumber,
    );
  }
}

/// Encapsulates the compilation units, diagnostic listeners, and [RuleContext]
/// for analyzing a library in [PluginServer].
final class _LibraryDiagnosticsContext {
  final RuleContext ruleContext;
  final List<RuleContextUnit> allUnits;
  final Map<RuleContextUnit, RecordingDiagnosticListener> diagnosticListeners;

  _LibraryDiagnosticsContext._({
    required this.ruleContext,
    required this.allUnits,
    required this.diagnosticListeners,
  });

  /// Builds a [_LibraryDiagnosticsContext] using parsed (unresolved)
  /// compilation units.
  static _LibraryDiagnosticsContext? forParsedLibrary(
    DriverBasedAnalysisContext analysisContext,
    String libraryPath,
    ResourceProvider resourceProvider,
  ) {
    var fileState = analysisContext.driver.fsState.getFileForPath(libraryPath);
    var libraryKind = fileState.kind.library ?? fileState.kind.asLibrary;

    var allUnits = <RuleContextUnit>[];
    var diagnosticListeners = <RuleContextUnit, RecordingDiagnosticListener>{};
    RuleContextUnit? definingContextUnit;

    for (var fileKind in libraryKind.fileKinds) {
      var path = fileKind.file.path;
      var file = resourceProvider.getFile(path);
      String content;
      try {
        content = file.readAsStringSync();
      } catch (_) {
        continue;
      }
      var parsedUnitResult = analysisContext.currentSession.getParsedUnit(path);
      if (parsedUnitResult is! ParsedUnitResult) continue;

      var listener = RecordingDiagnosticListener();
      var contextUnit = RuleContextUnit(
        file: file,
        content: content,
        diagnosticReporter: DiagnosticReporter(listener, fileKind.file.source),
        unit: parsedUnitResult.unit,
      );
      diagnosticListeners[contextUnit] = listener;
      allUnits.add(contextUnit);
      if (path == libraryPath) {
        definingContextUnit = contextUnit;
      }
    }
    definingContextUnit ??= allUnits.firstOrNull;
    if (definingContextUnit == null) return null;

    var package = analysisContext.contextRoot.workspace.findPackageFor(
      libraryPath,
    );
    return _LibraryDiagnosticsContext._(
      ruleContext: RuleContextWithParsedResults(
        allUnits,
        definingContextUnit,
        package,
      ),
      allUnits: allUnits,
      diagnosticListeners: diagnosticListeners,
    );
  }

  /// Builds a diagnostics context using a resolved library.
  static _LibraryDiagnosticsContext? forResolvedLibrary(
    AnalysisContext analysisContext,
    ResolvedLibraryResult libraryResult,
  ) {
    var allUnits = <RuleContextUnit>[];
    var diagnosticListeners = <RuleContextUnit, RecordingDiagnosticListener>{};
    RuleContextUnit? definingContextUnit;
    var definingUnit =
        (libraryResult.element as LibraryElementImpl).firstFragment;

    for (var unitResult in libraryResult.units) {
      var listener = RecordingDiagnosticListener();
      var contextUnit = RuleContextUnit(
        file: unitResult.file,
        content: unitResult.content,
        diagnosticReporter: DiagnosticReporter(
          listener,
          unitResult.libraryElement.firstFragment.source,
        ),
        unit: unitResult.unit,
      );
      diagnosticListeners[contextUnit] = listener;
      allUnits.add(contextUnit);
      if (unitResult.unit.declaredFragment == definingUnit) {
        definingContextUnit = contextUnit;
      }
    }
    definingContextUnit ??= allUnits.firstOrNull;
    if (definingContextUnit == null) return null;

    var definingPath = libraryResult.element.firstFragment.source.fullName;
    var package = analysisContext.contextRoot.workspace.findPackageFor(
      definingPath,
    );
    return _LibraryDiagnosticsContext._(
      ruleContext: RuleContextWithResolvedResults(
        allUnits,
        definingContextUnit,
        libraryResult.element.typeProvider,
        libraryResult.element.typeSystem as TypeSystemImpl,
        package,
      ),
      allUnits: allUnits,
      diagnosticListeners: diagnosticListeners,
    );
  }
}
