// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io' show Platform, Process;

import 'package:analysis_server/src/analytics/percentile_calculator.dart';
import 'package:analysis_server/src/plugin/notification_manager.dart';
import 'package:analyzer/dart/analysis/context_root.dart' as analyzer;
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/glob.dart';
import 'package:analyzer/src/workspace/blaze.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:analyzer_plugin/channel/channel.dart';
import 'package:analyzer_plugin/protocol/protocol.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_constants.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/src/channel/isolate_channel.dart';
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:meta/meta.dart';
import 'package:watcher/watcher.dart' as watcher;
import 'package:yaml/yaml.dart';

/// Information about a plugin that is built-in.
class BuiltInPluginInfo extends PluginInfo {
  /// The entry point function that will be executed in the plugin's isolate.
  final EntryPoint entryPoint;

  @override
  final String pluginId;

  /// Initialize a newly created built-in plugin.
  BuiltInPluginInfo(
      this.entryPoint,
      this.pluginId,
      AbstractNotificationManager notificationManager,
      InstrumentationService instrumentationService)
      : super(notificationManager, instrumentationService);

  @override
  ServerCommunicationChannel _createChannel() {
    return ServerIsolateChannel.builtIn(
        entryPoint, pluginId, instrumentationService);
  }
}

/// Information about a plugin that was discovered.
class DiscoveredPluginInfo extends PluginInfo {
  /// The path to the root directory of the definition of the plugin on disk
  /// (the directory containing the 'pubspec.yaml' file and the 'bin'
  /// directory).
  final String path;

  /// The path to the 'plugin.dart' file that will be executed in an isolate.
  final String executionPath;

  /// The path to the '.packages' file used to control the resolution of
  /// 'package:' URIs.
  final String packagesPath;

  /// Initialize the newly created information about a plugin.
  DiscoveredPluginInfo(
      this.path,
      this.executionPath,
      this.packagesPath,
      AbstractNotificationManager notificationManager,
      InstrumentationService instrumentationService)
      : super(notificationManager, instrumentationService);

  @override
  bool get canBeStarted => executionPath.isNotEmpty;

  @override
  String get pluginId => path;

  @override
  ServerCommunicationChannel _createChannel() {
    return ServerIsolateChannel.discovered(
        Uri.file(executionPath, windows: Platform.isWindows),
        Uri.file(packagesPath, windows: Platform.isWindows),
        instrumentationService);
  }
}

/// An indication of a problem with the execution of a plugin that occurs prior
/// to the execution of the plugin's entry point in an isolate.
class PluginException implements Exception {
  /// A message describing the problem.
  final String message;

  /// Initialize a newly created exception to have the given [message].
  PluginException(this.message);

  @override
  String toString() => message;
}

class PluginFiles {
  final File execution;
  final File packages;

  PluginFiles(this.execution, this.packages);
}

/// Information about a single plugin.
abstract class PluginInfo {
  /// The object used to manage the receiving and sending of notifications.
  final AbstractNotificationManager notificationManager;

  /// The instrumentation service that is being used by the analysis server.
  final InstrumentationService instrumentationService;

  /// The context roots that are currently using the results produced by the
  /// plugin.
  Set<analyzer.ContextRoot> contextRoots = HashSet<analyzer.ContextRoot>();

  /// The current execution of the plugin, or `null` if the plugin is not
  /// currently being executed.
  PluginSession? currentSession;

  CaughtException? _exception;

  /// Initialize the newly created information about a plugin.
  PluginInfo(this.notificationManager, this.instrumentationService);

  /// Return `true` if this plugin can be started, or `false` if there is a
  /// reason why it cannot be started. For example, a plugin cannot be started
  /// if there was an error with a previous attempt to start running it or if
  /// the plugin is not correctly configured.
  bool get canBeStarted => true;

  /// Return the data known about this plugin.
  PluginData get data =>
      PluginData(pluginId, currentSession?.name, currentSession?.version);

  /// The exception that occurred that prevented the plugin from being started,
  /// or `null` if there was no exception (possibly because no attempt has yet
  /// been made to start the plugin).
  CaughtException? get exception => _exception;

  /// Return the id of this plugin, used to identify the plugin to users.
  String get pluginId;

  /// Add the given [contextRoot] to the set of context roots being analyzed by
  /// this plugin.
  void addContextRoot(analyzer.ContextRoot contextRoot) {
    if (contextRoots.add(contextRoot)) {
      _updatePluginRoots();
    }
  }

  /// Add the given context [roots] to the set of context roots being analyzed
  /// by this plugin.
  void addContextRoots(Iterable<analyzer.ContextRoot> roots) {
    var changed = false;
    for (var contextRoot in roots) {
      if (contextRoots.add(contextRoot)) {
        changed = true;
      }
    }
    if (changed) {
      _updatePluginRoots();
    }
  }

  /// Return `true` if at least one of the context roots being analyzed contains
  /// the file with the given [filePath].
  bool isAnalyzing(String filePath) {
    for (var contextRoot in contextRoots) {
      if (contextRoot.isAnalyzed(filePath)) {
        return true;
      }
    }
    return false;
  }

  /// Remove the given [contextRoot] from the set of context roots being
  /// analyzed by this plugin.
  void removeContextRoot(analyzer.ContextRoot contextRoot) {
    if (contextRoots.remove(contextRoot)) {
      _updatePluginRoots();
    }
  }

  void reportException(CaughtException exception) {
    // If a previous exception has been reported, do not replace it here; the
    //first should have more "root cause" information.
    _exception ??= exception;
    instrumentationService.logPluginException(
        data, exception.exception, exception.stackTrace);
  }

  /// If the plugin is currently running, send a request based on the given
  /// [params] to the plugin. If the plugin is not running, the request will
  /// silently be dropped.
  void sendRequest(RequestParams params) {
    currentSession?.sendRequest(params);
  }

  /// Start a new isolate that is running the plugin. Return the state object
  /// used to interact with the plugin, or `null` if the plugin could not be
  /// run.
  Future<PluginSession?> start(String? byteStorePath, String sdkPath) async {
    if (currentSession != null) {
      throw StateError('Cannot start a plugin that is already running.');
    }
    currentSession = PluginSession(this);
    var isRunning = await currentSession!.start(byteStorePath, sdkPath);
    if (!isRunning) {
      currentSession = null;
    }
    return currentSession;
  }

  /// Request that the plugin shutdown.
  Future<void> stop() {
    if (currentSession == null) {
      if (_exception != null) {
        // Plugin crashed, nothing to do.
        return Future<void>.value();
      }
      throw StateError('Cannot stop a plugin that is not running.');
    }
    var doneFuture = currentSession!.stop();
    currentSession = null;
    return doneFuture;
  }

  /// Create and return the channel used to communicate with the server.
  ServerCommunicationChannel _createChannel();

  /// Update the context roots that the plugin should be analyzing.
  void _updatePluginRoots() {
    final currentSession = this.currentSession;
    if (currentSession != null) {
      var params = AnalysisSetContextRootsParams(contextRoots
          .map((analyzer.ContextRoot contextRoot) => ContextRoot(
              contextRoot.root.path, contextRoot.excludedPaths.toList(),
              optionsFile: contextRoot.optionsFile?.path))
          .toList());
      currentSession.sendRequest(params);
    }
  }
}

/// An object used to manage the currently running plugins.
class PluginManager {
  /// A table, keyed by both a plugin and a request method, to a list of the
  /// times that it took the plugin to return a response to requests with the
  /// method.
  static Map<PluginInfo, Map<String, PercentileCalculator>>
      pluginResponseTimes = <PluginInfo, Map<String, PercentileCalculator>>{};

  /// The console environment key used by the pub tool.
  static const String _pubEnvironmentKey = 'PUB_ENVIRONMENT';

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

  /// The absolute path of the directory containing the on-disk byte store, or
  /// `null` if there is no on-disk store.
  final String? byteStorePath;

  /// The absolute path of the directory containing the SDK.
  final String sdkPath;

  /// The object used to manage the receiving and sending of notifications.
  final AbstractNotificationManager notificationManager;

  /// The instrumentation service that is being used by the analysis server.
  final InstrumentationService instrumentationService;

  /// A table mapping the paths of plugins to information about those plugins.
  final Map<String, PluginInfo> _pluginMap = <String, PluginInfo>{};

  /// The parameters for the last 'analysis.setPriorityFiles' request that was
  /// received from the client. Because plugins are lazily discovered, this
  /// needs to be retained so that it can be sent after a plugin has been
  /// started.
  AnalysisSetPriorityFilesParams? _analysisSetPriorityFilesParams;

  /// The parameters for the last 'analysis.setSubscriptions' request that was
  /// received from the client. Because plugins are lazily discovered, this
  /// needs to be retained so that it can be sent after a plugin has been
  /// started.
  AnalysisSetSubscriptionsParams? _analysisSetSubscriptionsParams;

  /// The current state of content overlays. Because plugins are lazily
  /// discovered, the state needs to be retained so that it can be sent after a
  /// plugin has been started.
  final Map<String, AddContentOverlay> _overlayState = {};

  final StreamController<void> _pluginsChanged = StreamController.broadcast();

  /// Initialize a newly created plugin manager. The notifications from the
  /// running plugins will be handled by the given [notificationManager].
  PluginManager(this.resourceProvider, this.byteStorePath, this.sdkPath,
      this.notificationManager, this.instrumentationService);

  /// Return a list of all of the plugins that are currently known.
  List<PluginInfo> get plugins => _pluginMap.values.toList();

  /// Stream emitting an event when known [plugins] change.
  Stream<void> get pluginsChanged => _pluginsChanged.stream;

  /// Add the plugin with the given [path] to the list of plugins that should be
  /// used when analyzing code for the given [contextRoot]. If the plugin had
  /// not yet been started, then it will be started by this method.
  Future<void> addPluginToContextRoot(
      analyzer.ContextRoot contextRoot, String path) async {
    var plugin = _pluginMap[path];
    var isNew = false;
    if (plugin == null) {
      isNew = true;
      PluginFiles pluginFiles;
      try {
        pluginFiles = filesFor(path);
      } catch (exception, stackTrace) {
        plugin = DiscoveredPluginInfo(
            path, '', '', notificationManager, instrumentationService);
        plugin.reportException(CaughtException(exception, stackTrace));
        _pluginMap[path] = plugin;
        return;
      }
      plugin = DiscoveredPluginInfo(
          path,
          pluginFiles.execution.path,
          pluginFiles.packages.path,
          notificationManager,
          instrumentationService);
      _pluginMap[path] = plugin;
      try {
        var session = await plugin.start(byteStorePath, sdkPath);
        unawaited(session?.onDone.then((_) {
          if (_pluginMap[path] == plugin) {
            _pluginMap.remove(path);
            _notifyPluginsChanged();
          }
        }));
      } catch (exception, stackTrace) {
        // Record the exception (for debugging purposes) and record the fact
        // that we should not try to communicate with the plugin.
        plugin.reportException(CaughtException(exception, stackTrace));
        isNew = false;
      }

      _notifyPluginsChanged();
    }
    plugin.addContextRoot(contextRoot);
    if (isNew) {
      var analysisSetSubscriptionsParams = _analysisSetSubscriptionsParams;
      if (analysisSetSubscriptionsParams != null) {
        plugin.sendRequest(analysisSetSubscriptionsParams);
      }
      if (_overlayState.isNotEmpty) {
        plugin.sendRequest(AnalysisUpdateContentParams(_overlayState));
      }
      var analysisSetPriorityFilesParams = _analysisSetPriorityFilesParams;
      if (analysisSetPriorityFilesParams != null) {
        plugin.sendRequest(analysisSetPriorityFilesParams);
      }
    }
  }

  /// Broadcast a request built from the given [params] to all of the plugins
  /// that are currently associated with the given [contextRoot]. Return a list
  /// containing futures that will complete when each of the plugins have sent a
  /// response.
  Map<PluginInfo, Future<Response>> broadcastRequest(RequestParams params,
      {analyzer.ContextRoot? contextRoot}) {
    var plugins = pluginsForContextRoot(contextRoot);
    var responseMap = <PluginInfo, Future<Response>>{};
    for (var plugin in plugins) {
      var request = plugin.currentSession?.sendRequest(params);
      // Only add an entry to the map if we have sent a request.
      if (request != null) {
        responseMap[plugin] = request;
      }
    }
    return responseMap;
  }

  /// Broadcast the given [watchEvent] to all of the plugins that are analyzing
  /// in contexts containing the file associated with the event. Return a list
  /// containing futures that will complete when each of the plugins have sent a
  /// response.
  Future<List<Future<Response>>> broadcastWatchEvent(
      watcher.WatchEvent watchEvent) async {
    var filePath = watchEvent.path;

    /// Return `true` if the given glob [pattern] matches the file being
    /// watched.
    bool matches(String pattern) =>
        Glob(resourceProvider.pathContext.separator, pattern).matches(filePath);

    WatchEvent? event;
    var responses = <Future<Response>>[];
    for (var plugin in _pluginMap.values) {
      var session = plugin.currentSession;
      var interestingFiles = session?.interestingFiles;
      if (session != null &&
          plugin.isAnalyzing(filePath) &&
          interestingFiles != null &&
          interestingFiles.any(matches)) {
        // The list of interesting file globs is `null` if the plugin has not
        // yet responded to the plugin.versionCheck request. If that happens
        // then the plugin hasn't had a chance to analyze anything yet, and
        // hence it does not needed to get watch events.
        event ??= _convertWatchEvent(watchEvent);
        var params = AnalysisHandleWatchEventsParams([event]);
        responses.add(session.sendRequest(params));
      }
    }
    return responses;
  }

  /// Return the files associated with the plugin at the given [pluginPath].
  /// Throw a [PluginException] if there is a problem that prevents the plugin
  /// from being executing.
  @visibleForTesting
  PluginFiles filesFor(String pluginPath) {
    var pluginFolder = resourceProvider.getFolder(pluginPath);
    var pubspecFile = pluginFolder.getChildAssumingFile(file_paths.pubspecYaml);
    if (!pubspecFile.exists) {
      // If there's no pubspec file, then we don't need to copy the package
      // because we won't be running pub.
      return _computeFiles(pluginFolder);
    }
    var workspace = BlazeWorkspace.find(resourceProvider, pluginFolder.path);
    if (workspace != null) {
      // Similarly, we won't be running pub if we're in a workspace because
      // there is exactly one version of each package.
      return _computeFiles(pluginFolder, workspace: workspace);
    }
    //
    // Copy the plugin directory to a unique subdirectory of the plugin
    // manager's state location. The subdirectory's name is selected such that
    // it will be invariant across sessions, reducing the number of times the
    // plugin will need to be copied and pub will need to be run.
    //
    var stateFolder = resourceProvider.getStateLocation('.plugin_manager');
    if (stateFolder == null) {
      throw PluginException('No state location, so plugin could not be copied');
    }
    var stateName = _uniqueDirectoryName(pluginPath);
    var parentFolder = stateFolder.getChildAssumingFolder(stateName);
    if (parentFolder.exists) {
      var executionFolder =
          parentFolder.getChildAssumingFolder(pluginFolder.shortName);
      return _computeFiles(executionFolder, pubCommand: 'upgrade');
    }
    var executionFolder = pluginFolder.copyTo(parentFolder);
    return _computeFiles(executionFolder, pubCommand: 'get');
  }

  /// Return a list of all of the plugins that are currently associated with the
  /// given [contextRoot].
  @visibleForTesting
  List<PluginInfo> pluginsForContextRoot(analyzer.ContextRoot? contextRoot) {
    if (contextRoot == null) {
      return _pluginMap.values.toList();
    }
    var plugins = <PluginInfo>[];
    for (var plugin in _pluginMap.values) {
      if (plugin.contextRoots.contains(contextRoot)) {
        plugins.add(plugin);
      }
    }
    return plugins;
  }

  /// The given [contextRoot] is no longer being analyzed.
  void removedContextRoot(analyzer.ContextRoot contextRoot) {
    var plugins = _pluginMap.values.toList();
    for (var plugin in plugins) {
      plugin.removeContextRoot(contextRoot);
      if (plugin is DiscoveredPluginInfo && plugin.contextRoots.isEmpty) {
        _pluginMap.remove(plugin.path);
        _notifyPluginsChanged();
        try {
          plugin.stop();
        } catch (e, st) {
          AnalysisEngine.instance.instrumentationService
              .logException(SilentException('Issue stopping a plugin', e, st));
        }
      }
    }
  }

  /// Restart all currently running plugins.
  Future<void> restartPlugins() async {
    for (var plugin in _pluginMap.values.toList()) {
      if (plugin.currentSession != null) {
        //
        // Capture needed state.
        //
        var contextRoots = plugin.contextRoots;
        var path = plugin.pluginId;
        //
        // Stop the plugin.
        //
        await plugin.stop();
        //
        // Restart the plugin.
        //
        _pluginMap[path] = plugin;
        var session = await plugin.start(byteStorePath, sdkPath);
        unawaited(session?.onDone.then((_) {
          _pluginMap.remove(path);
        }));
        //
        // Re-initialize the plugin.
        //
        plugin.addContextRoots(contextRoots);
        var analysisSetSubscriptionsParams = _analysisSetSubscriptionsParams;
        if (analysisSetSubscriptionsParams != null) {
          plugin.sendRequest(analysisSetSubscriptionsParams);
        }
        if (_overlayState.isNotEmpty) {
          plugin.sendRequest(AnalysisUpdateContentParams(_overlayState));
        }
        var analysisSetPriorityFilesParams = _analysisSetPriorityFilesParams;
        if (analysisSetPriorityFilesParams != null) {
          plugin.sendRequest(analysisSetPriorityFilesParams);
        }
      }
    }
  }

  /// Send a request based on the given [params] to existing plugins to set the
  /// priority files to those specified by the [params]. As a side-effect,
  /// record the parameters so that they can be sent to any newly started
  /// plugins.
  void setAnalysisSetPriorityFilesParams(
      AnalysisSetPriorityFilesParams params) {
    for (var plugin in _pluginMap.values) {
      plugin.sendRequest(params);
    }
    _analysisSetPriorityFilesParams = params;
  }

  /// Send a request based on the given [params] to existing plugins to set the
  /// subscriptions to those specified by the [params]. As a side-effect, record
  /// the parameters so that they can be sent to any newly started plugins.
  void setAnalysisSetSubscriptionsParams(
      AnalysisSetSubscriptionsParams params) {
    for (var plugin in _pluginMap.values) {
      plugin.sendRequest(params);
    }
    _analysisSetSubscriptionsParams = params;
  }

  /// Send a request based on the given [params] to existing plugins to set the
  /// content overlays to those specified by the [params]. As a side-effect,
  /// update the overlay state so that it can be sent to any newly started
  /// plugins.
  void setAnalysisUpdateContentParams(AnalysisUpdateContentParams params) {
    for (var plugin in _pluginMap.values) {
      plugin.sendRequest(params);
    }
    var files = params.files;
    for (var file in files.keys) {
      var overlay = files[file];
      if (overlay is RemoveContentOverlay) {
        _overlayState.remove(file);
      } else if (overlay is AddContentOverlay) {
        _overlayState[file] = overlay;
      } else if (overlay is ChangeContentOverlay) {
        var previousOverlay = _overlayState[file]!;
        var newContent =
            SourceEdit.applySequence(previousOverlay.content, overlay.edits);
        _overlayState[file] = AddContentOverlay(newContent);
      } else {
        throw ArgumentError('Invalid class of overlay: ${overlay.runtimeType}');
      }
    }
  }

  /// Stop all of the plugins that are currently running.
  Future<List<void>> stopAll() {
    return Future.wait(_pluginMap.values.map((PluginInfo info) async {
      try {
        await info.stop();
      } catch (e, st) {
        AnalysisEngine.instance.instrumentationService.logException(e, st);
      }
    }));
  }

  /// Compute the files to be returned by the enclosing method given that the
  /// plugin should exist in the given [pluginFolder].
  ///
  /// Runs pub if [pubCommand] is provided and not null.
  PluginFiles _computeFiles(Folder pluginFolder,
      {String? pubCommand, Workspace? workspace}) {
    var pluginFile = pluginFolder
        .getChildAssumingFolder('bin')
        .getChildAssumingFile('plugin.dart');
    if (!pluginFile.exists) {
      throw PluginException('File "${pluginFile.path}" does not exist.');
    }
    String? reason;
    File? packagesFile = pluginFolder
        .getChildAssumingFolder(file_paths.dotDartTool)
        .getChildAssumingFile(file_paths.packageConfigJson);
    if (pubCommand != null) {
      var result = Process.runSync(
          Platform.executable, <String>['pub', pubCommand],
          stderrEncoding: utf8,
          stdoutEncoding: utf8,
          workingDirectory: pluginFolder.path,
          environment: {_pubEnvironmentKey: _getPubEnvironmentValue()});
      if (result.exitCode != 0) {
        var buffer = StringBuffer();
        buffer.writeln('Failed to run pub $pubCommand');
        buffer.writeln('  pluginFolder = ${pluginFolder.path}');
        buffer.writeln('  exitCode = ${result.exitCode}');
        buffer.writeln('  stdout = ${result.stdout}');
        buffer.writeln('  stderr = ${result.stderr}');
        reason = buffer.toString();
        instrumentationService.logError(reason);
      }
      if (!packagesFile.exists) {
        reason ??= 'File "${packagesFile.path}" does not exist.';
        packagesFile = null;
      }
    } else if (!packagesFile.exists) {
      if (workspace != null) {
        packagesFile =
            _createPackagesFile(pluginFolder, workspace.packageUriResolver);
        if (packagesFile == null) {
          var name = file_paths.packageConfigJson;
          reason = 'Could not create $name file in workspace $workspace.';
        }
      } else {
        reason = 'Could not create "${packagesFile.path}".';
        packagesFile = null;
      }
    }
    if (packagesFile == null) {
      reason ??= 'Could not create packages file for an unknown reason.';
      throw PluginException(reason);
    }
    return PluginFiles(pluginFile, packagesFile);
  }

  WatchEventType _convertChangeType(watcher.ChangeType type) {
    return switch (type) {
      watcher.ChangeType.ADD => WatchEventType.ADD,
      watcher.ChangeType.MODIFY => WatchEventType.MODIFY,
      watcher.ChangeType.REMOVE => WatchEventType.REMOVE,
      _ => throw StateError('Unknown change type: $type')
    };
  }

  WatchEvent _convertWatchEvent(watcher.WatchEvent watchEvent) {
    return WatchEvent(_convertChangeType(watchEvent.type), watchEvent.path);
  }

  /// Return a temporary `package_config.json` file that is appropriate for
  /// the plugin in the given [pluginFolder]. The [packageUriResolver] is
  /// used to determine the location of the packages that need to be included
  /// in the packages file.
  File? _createPackagesFile(
      Folder pluginFolder, UriResolver packageUriResolver) {
    var pluginPath = pluginFolder.path;
    var stateFolder = resourceProvider.getStateLocation('.plugin_manager')!;
    var stateName = '${_uniqueDirectoryName(pluginPath)}.packages';
    var packagesFile = stateFolder.getChildAssumingFile(stateName);
    if (!packagesFile.exists) {
      var pluginPubspec =
          pluginFolder.getChildAssumingFile(file_paths.pubspecYaml);
      if (!pluginPubspec.exists) {
        return null;
      }

      try {
        var visitedPackageNames = <String>{};
        var packages = <_Package>[];
        var context = resourceProvider.pathContext;
        packages.add(
          _Package(
            context.basename(pluginPath),
            pluginFolder,
          ),
        );
        var pubspecFiles = <File>[];
        pubspecFiles.add(pluginPubspec);
        while (pubspecFiles.isNotEmpty) {
          var pubspecFile = pubspecFiles.removeLast();
          for (var packageName in _readDependencies(pubspecFile)) {
            if (visitedPackageNames.add(packageName)) {
              var uri = Uri.parse('package:$packageName/$packageName.dart');
              var packageSource = packageUriResolver.resolveAbsolute(uri);
              if (packageSource != null) {
                var packageRoot = resourceProvider
                    .getFile(packageSource.fullName)
                    .parent
                    .parent;
                packages.add(
                  _Package(packageName, packageRoot),
                );
                pubspecFiles.add(
                  packageRoot.getChildAssumingFile(file_paths.pubspecYaml),
                );
              }
            }
          }
        }

        packages.sort((a, b) => a.name.compareTo(b.name));

        var packageConfigBuilder = PackageConfigFileBuilder();
        for (var package in packages) {
          packageConfigBuilder.add(
            name: package.name,
            rootPath: package.root.path,
          );
        }
        packagesFile.writeAsStringSync(
          packageConfigBuilder.toContent(
            toUriStr: (path) {
              return resourceProvider.pathContext.toUri(path).toString();
            },
          ),
        );
      } catch (exception) {
        // If we are not able to produce a .packages file, return null so that
        // callers will not try to load the plugin.
        return null;
      }
    }
    return packagesFile;
  }

  void _notifyPluginsChanged() => _pluginsChanged.add(null);

  /// Return the names of packages that are listed as dependencies in the given
  /// [pubspecFile].
  Iterable<String> _readDependencies(File pubspecFile) {
    var document = loadYamlDocument(pubspecFile.readAsStringSync(),
        sourceUrl: pubspecFile.toUri());
    var contents = document.contents;
    if (contents is YamlMap) {
      var dependencies = contents['dependencies'] as YamlNode?;
      if (dependencies is YamlMap) {
        return dependencies.keys.cast<String>();
      }
    }
    return const <String>[];
  }

  /// Return a hex-encoded MD5 signature of the given file [path].
  String _uniqueDirectoryName(String path) {
    var bytes = md5.convert(path.codeUnits).bytes;
    return hex.encode(bytes);
  }

  /// Record the fact that the given [plugin] responded to a request with the
  /// given [method] in the given [time].
  static void recordResponseTime(PluginInfo plugin, String method, int time) {
    pluginResponseTimes
        .putIfAbsent(plugin, () => <String, PercentileCalculator>{})
        .putIfAbsent(method, () => PercentileCalculator())
        .addValue(time);
  }

  /// Returns the environment value that should be used when running pub.
  ///
  /// Includes any existing environment value, if one exists.
  static String _getPubEnvironmentValue() {
    // DO NOT update this function without contacting kevmoo.
    // We have server-side tooling that assumes the values are consistent.
    var values = <String>[];

    var existing = Platform.environment[_pubEnvironmentKey];

    // If there is an existing value for this var, make sure to include it.
    if ((existing != null) && existing.isNotEmpty) {
      values.add(existing);
    }

    values.add('analysis_server.plugin_manager');

    return values.join(':');
  }
}

/// Information about the execution a single plugin.
@visibleForTesting
class PluginSession {
  /// The maximum number of milliseconds that server should wait for a response
  /// from a plugin before deciding that the plugin is hung.
  static const Duration MAXIMUM_RESPONSE_TIME = Duration(minutes: 2);

  /// The length of time to wait after sending a 'plugin.shutdown' request
  /// before a failure to terminate will cause the isolate to be killed.
  static const Duration WAIT_FOR_SHUTDOWN_DURATION = Duration(seconds: 10);

  /// The information about the plugin being executed.
  final PluginInfo info;

  /// The completer used to signal when the plugin has stopped.
  Completer<void> pluginStoppedCompleter = Completer<void>();

  /// The channel used to communicate with the plugin.
  ServerCommunicationChannel? channel;

  /// The index of the next request to be sent to the plugin.
  int requestId = 0;

  /// A table mapping the id's of requests to the functions used to handle the
  /// response to those requests.
  @visibleForTesting
  // ignore: library_private_types_in_public_api
  Map<String, _PendingRequest> pendingRequests = <String, _PendingRequest>{};

  /// A boolean indicating whether the plugin is compatible with the version of
  /// the plugin API being used by this server.
  bool isCompatible = true;

  /// The contact information to include when reporting problems related to the
  /// plugin.
  String? contactInfo;

  /// The glob patterns of files that the plugin is interested in knowing about.
  List<String>? interestingFiles;

  /// The name to be used when reporting problems related to the plugin.
  String? name;

  /// The version number to be used when reporting problems related to the
  /// plugin.
  String? version;

  /// Initialize the newly created information about the execution of a plugin.
  PluginSession(this.info);

  /// Return the next request id, encoded as a string and increment the id so
  /// that a different result will be returned on each invocation.
  String get nextRequestId => (requestId++).toString();

  /// Return a future that will complete when the plugin has stopped.
  Future<void> get onDone => pluginStoppedCompleter.future;

  /// Handle the given [notification].
  void handleNotification(Notification notification) {
    if (notification.event == PLUGIN_NOTIFICATION_ERROR) {
      var params = PluginErrorParams.fromNotification(notification);
      if (params.isFatal) {
        info.stop();
        stop();
      }
    }
    info.notificationManager
        .handlePluginNotification(info.pluginId, notification);
  }

  /// Handle the fact that the plugin has stopped.
  void handleOnDone() {
    if (channel != null) {
      channel!.close();
      channel = null;
    }
    pluginStoppedCompleter.complete(null);
  }

  /// Handle the fact that an unhandled error has occurred in the plugin.
  void handleOnError(dynamic error) {
    var errorPair = (error as List).cast<String>();
    var stackTrace = StackTrace.fromString(errorPair[1]);
    info.reportException(
        CaughtException(PluginException(errorPair[0]), stackTrace));
  }

  /// Handle a [response] from the plugin by completing the future that was
  /// created when the request was sent.
  void handleResponse(Response response) {
    var requestData = pendingRequests.remove(response.id);
    if (requestData != null) {
      var responseTime = DateTime.now().millisecondsSinceEpoch;
      var duration = responseTime - requestData.requestTime;
      PluginManager.recordResponseTime(info, requestData.method, duration);
      var completer = requestData.completer;
      completer.complete(response);
    }
  }

  /// Return `true` if there are any requests that have not been responded to
  /// within the maximum allowed amount of time.
  bool isNonResponsive() {
    // TODO(brianwilkerson): Figure out when to invoke this method in order to
    // identify non-responsive plugins and kill them.
    var cutOffTime = DateTime.now().millisecondsSinceEpoch -
        MAXIMUM_RESPONSE_TIME.inMilliseconds;
    for (var requestData in pendingRequests.values) {
      if (requestData.requestTime < cutOffTime) {
        return true;
      }
    }
    return false;
  }

  /// Send a request, based on the given [parameters]. Return a future that will
  /// complete when a response is received.
  Future<Response> sendRequest(RequestParams parameters) {
    final channel = this.channel;
    if (channel == null) {
      throw StateError('Cannot send a request to a plugin that has stopped.');
    }
    var id = nextRequestId;
    var completer = Completer<Response>();
    var requestTime = DateTime.now().millisecondsSinceEpoch;
    var request = parameters.toRequest(id);
    pendingRequests[id] =
        _PendingRequest(request.method, requestTime, completer);
    channel.sendRequest(request);
    return completer.future;
  }

  /// Start a new isolate that is running this plugin. The plugin will be sent
  /// the given [byteStorePath]. Return `true` if the plugin is compatible and
  /// running.
  Future<bool> start(String? byteStorePath, String sdkPath) async {
    if (channel != null) {
      throw StateError('Cannot start a plugin that is already running.');
    }
    if (byteStorePath == null || byteStorePath.isEmpty) {
      throw StateError('Missing byte store path');
    }
    if (!isCompatible) {
      info.reportException(CaughtException(
          PluginException('Plugin is not compatible.'), StackTrace.current));
      return false;
    }
    if (!info.canBeStarted) {
      info.reportException(CaughtException(
          PluginException('Plugin cannot be started.'), StackTrace.current));
      return false;
    }
    channel = info._createChannel();
    // TODO(brianwilkerson): Determine if await is necessary, if so, change the
    // return type of `channel.listen` to `Future<void>`.
    await (channel!.listen(handleResponse, handleNotification,
        onDone: handleOnDone, onError: handleOnError) as dynamic);
    if (channel == null) {
      // If there is an error when starting the isolate, the channel will invoke
      // `handleOnDone`, which will cause `channel` to be set to `null`.
      info.reportException(CaughtException(
          PluginException('Unrecorded error while starting the plugin.'),
          StackTrace.current));
      return false;
    }
    var response = await sendRequest(
        PluginVersionCheckParams(byteStorePath, sdkPath, '1.0.0-alpha.0'));
    var result = PluginVersionCheckResult.fromResponse(response);
    isCompatible = result.isCompatible;
    contactInfo = result.contactInfo;
    interestingFiles = result.interestingFiles;
    name = result.name;
    version = result.version;
    if (!isCompatible) {
      unawaited(sendRequest(PluginShutdownParams()));
      info.reportException(CaughtException(
          PluginException('Plugin is not compatible.'), StackTrace.current));
      return false;
    }
    return true;
  }

  /// Request that the plugin shutdown.
  Future<void> stop() {
    if (channel == null) {
      throw StateError('Cannot stop a plugin that is not running.');
    }
    sendRequest(PluginShutdownParams());
    Future.delayed(WAIT_FOR_SHUTDOWN_DURATION, () {
      if (channel != null) {
        channel?.kill();
        channel = null;
      }
    });
    return pluginStoppedCompleter.future;
  }
}

class _Package {
  final String name;
  final Folder root;

  _Package(this.name, this.root);
}

/// Information about a request that has been sent but for which a response has
/// not yet been received.
class _PendingRequest {
  /// The method of the request.
  final String method;

  /// The time at which the request was sent to the plugin.
  final int requestTime;

  /// The completer that will be used to complete the future when the response
  /// is received from the plugin.
  final Completer<Response> completer;

  /// Initialize a pending request.
  _PendingRequest(this.method, this.requestTime, this.completer);
}
