// 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.

/// @docImport 'package:analysis_server_plugin/src/plugin_server.dart';
/// @docImport 'package:analysis_server/src/plugin/plugin_watcher.dart';
library;

import 'dart:async';
import 'dart:convert';
import 'dart:io' show ProcessResult;

import 'package:analysis_server/src/analytics/percentile_calculator.dart';
import 'package:analysis_server/src/plugin/notification_manager.dart';
import 'package:analysis_server/src/plugin/plugin_isolate.dart';
import 'package:analysis_server/src/session_logger/session_logger.dart';
import 'package:analysis_server/src/utilities/process.dart';
import 'package:analysis_server/src/utilities/sdk.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/source.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/glob.dart';
import 'package:analyzer/src/util/platform_info.dart';
import 'package:analyzer/src/workspace/blaze.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:analyzer_plugin/protocol/protocol.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.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';

const _builtAsAot = bool.fromEnvironment('built_as_aot');

/// 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].
  new(this.message);

  @override
  String toString() => message;
}

/// The necessary files that define an analyzer plugin on disk.
class PluginFiles {
  /// The plugin entry point.
  final File execution;

  /// The plugin package config file.
  final File packageConfig;

  new(this.execution, this.packageConfig);
}

/// 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<PluginIsolate, Map<String, PercentileCalculator>>
  pluginResponseTimes = <PluginIsolate, 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;

  /// The session logger that is being used by the analysis server.
  final SessionLogger sessionLogger;

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

  /// The parameters for the last 'analysis.setAnalysisRoots' 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.
  AnalysisSetAnalysisRootsParams? _analysisSetAnalysisRootsParams;

  /// 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();

  /// Whether plugins are "initialized."
  ///
  /// Plugins are declared to be initialized either (a) when the [PluginWatcher]
  /// has determined no plugins are configured to be run, or (b) when the
  /// plugins are configured and the first status notification is received by
  /// the analysis server.
  ///
  /// It is important that this completer always eventually completes and is not
  /// left dangling (for example if plugins are invalid, fail to load, etc)
  /// because tools like 'dart analyze' may wait on it via the
  /// 'dart/workspace/analysis/complete' request.
  final Completer<void> initializedCompleter = Completer();

  final ProcessRunner _processRunner;

  /// The set of context root paths with no configured _new_ plugins.
  final contextRootsWithNoPlugins = <String>{};

  /// Initializes a newly created plugin manager.
  ///
  /// The notifications from the running plugins will be handled by the given
  /// [_notificationManager].
  new(
    this._resourceProvider,
    this._byteStorePath,
    this._sdkPath,
    this._notificationManager,
    this.instrumentationService,
    this.sessionLogger, {
    this._processRunner = const ProcessRunner(),
  });

  /// All of the legacy plugins that are currently known.
  List<PluginIsolate> get legacyPluginIsolates =>
      pluginIsolates.where((p) => p.isLegacy).toList();

  /// All of the "new" plugins that are currently known.
  List<PluginIsolate> get newPluginIsolates =>
      pluginIsolates.where((p) => !p.isLegacy).toList();

  /// All of the plugins that are currently known.
  List<PluginIsolate> get pluginIsolates => _pluginMap.values.toList();

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

  /// Adds 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.
  ///
  /// Specify whether this is a legacy plugin with [isLegacyPlugin].
  Future<void> addPluginToContextRoot(
    analyzer.ContextRoot contextRoot,
    String path, {
    required bool isLegacyPlugin,
  }) async {
    var pluginIsolate = _pluginMap[path];
    if (pluginIsolate != null) {
      pluginIsolate.addContextRoot(contextRoot);
      return;
    }

    var startedSuccessfully = true;
    PluginFiles pluginFiles;
    try {
      pluginFiles = filesFor(path, isLegacyPlugin: isLegacyPlugin);
    } catch (exception, stackTrace) {
      pluginIsolate = PluginIsolate(
        path,
        null,
        null,
        _notificationManager,
        instrumentationService,
        sessionLogger,
        isLegacy: isLegacyPlugin,
      );
      pluginIsolate.reportException(CaughtException(exception, stackTrace));
      _pluginMap[path] = pluginIsolate;
      return;
    }
    pluginIsolate = PluginIsolate(
      path,
      pluginFiles.execution.path,
      pluginFiles.packageConfig.path,
      _notificationManager,
      instrumentationService,
      sessionLogger,
      isLegacy: isLegacyPlugin,
    );
    try {
      instrumentationService.logInfo('Starting plugin "$pluginIsolate"');
      var session = await pluginIsolate.start(_byteStorePath, _sdkPath);
      unawaited(
        session?.onDone.then((_) {
          if (_pluginMap[path] == pluginIsolate) {
            _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.
      pluginIsolate.reportException(CaughtException(exception, stackTrace));
      startedSuccessfully = false;
    }

    _pluginMap[path] = pluginIsolate;

    _notifyPluginsChanged();

    pluginIsolate.addContextRoot(contextRoot);
    if (startedSuccessfully) {
      // Send these cached requests to the restarted plugin in order to catch it
      // back up to the working state.
      var cachedRequests = [
        ?_analysisSetSubscriptionsParams,
        ?_analysisSetAnalysisRootsParams,
        if (_overlayState.isNotEmpty)
          AnalysisUpdateContentParams(_overlayState),
        ?_analysisSetPriorityFilesParams,
      ];
      for (var cachedRequest in cachedRequests) {
        pluginIsolate.sendRequest(cachedRequest);
      }
    }
  }

  /// 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<PluginIsolate, Future<Response>> broadcastRequest(
    RequestParams params, {
    analyzer.ContextRoot? contextRoot,
  }) {
    var pluginIsolates = pluginsForContextRoot(contextRoot);
    var responseMap = <PluginIsolate, Future<Response>>{};
    for (var pluginIsolate in pluginIsolates) {
      var request = pluginIsolate.currentSession?.sendRequest(params);
      // Only add an entry to the map if we have sent a request.
      if (request != null) {
        responseMap[pluginIsolate] = request;
      }
    }
    return responseMap;
  }

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

    WatchEvent? event;
    var responses = <Future<Response>>[];
    var separator = _resourceProvider.pathContext.separator;
    for (var pluginIsolate in _pluginMap.values) {
      var session = pluginIsolate.currentSession;
      if (session == null) continue;
      if (!pluginIsolate.isAnalyzing(filePath)) continue;
      var interestingGlobs = session.interestingFileGlobs;

      // The list of interesting file globs is `null` if the isolate has not yet
      // responded to the 'plugin.versionCheck' request. If that happens, then
      // the isolate hasn't had a chance to analyze anything yet; hence, it
      // it does not need to get watch events, yet.
      if (interestingGlobs == null) continue;

      // Canonicalize the globs. If a glob does not start with '**/', then
      // prepend '**/' to the glob.
      interestingGlobs = [
        for (var g in interestingGlobs)
          if (g.startsWith('**/')) g else '**/$g',
      ];

      if (!interestingGlobs.any((g) => Glob(separator, g).matches(filePath))) {
        continue;
      }

      event ??= _convertWatchEvent(watchEvent);
      var params = AnalysisHandleWatchEventsParams([event]);
      responses.add(session.sendRequest(params));
    }
    return responses;
  }

  /// Returns the files associated with the plugin at the given [pluginPath].
  ///
  /// In some cases, the plugin's sources are copied to a special directory. If
  /// [pluginPath] does not include a `pubspec.yaml` file, we do not. If
  /// [pluginPath] exists in a [BlazeWorkspace], we do not.
  ///
  /// Throws a [PluginException] if there is a problem that prevents the plugin
  /// from being executing.
  ///
  /// [builtAsAot] can be passed in during a test, to simulate a different flow.
  @visibleForTesting
  PluginFiles filesFor(
    String pluginPath, {
    required bool isLegacyPlugin,
    @visibleForTesting bool builtAsAot = _builtAsAot,
  }) {
    var pluginFolder = _resourceProvider.getFolder(pluginPath);
    var pubspecFile = pluginFolder.getFile(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, builtAsAot: builtAsAot);
    }
    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,
        builtAsAot: builtAsAot,
        workspace: workspace,
      );
    }

    if (!isLegacyPlugin) {
      return _computeFiles(
        pluginFolder,
        builtAsAot: builtAsAot,
        pubCommand: 'upgrade',
      );
    }

    // 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 we
    // copy the plugin contents, and the number of times we run `pub`.

    var parentFolder = pluginStateFolder(pluginPath);
    if (parentFolder.exists) {
      var executionFolder = parentFolder.getFolder(pluginFolder.shortName);
      return _computeFiles(
        executionFolder,
        builtAsAot: builtAsAot,
        pubCommand: 'upgrade',
      );
    }
    var executionFolder = pluginFolder.copyTo(parentFolder);
    return _computeFiles(
      executionFolder,
      builtAsAot: builtAsAot,
      pubCommand: 'get',
    );
  }

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

  /// Returns the "plugin state" folder for a plugin at [pluginPath].
  ///
  /// This is a directory under the state location for '.plugin_manager', named
  /// with a hash based on [pluginPath].
  Folder pluginStateFolder(String pluginPath) {
    var stateFolder = _resourceProvider.getStateLocation('.plugin_manager');
    if (stateFolder == null) {
      throw PluginException('No state location, so plugin could not be copied');
    }
    var stateName = _uniqueDirectoryName(pluginPath);
    return stateFolder.getFolder(stateName);
  }

  /// The path to the "plugin state" folder for a plugin at [pluginPath].
  String pluginStateFolderPath(String pluginPath) =>
      pluginStateFolder(pluginPath).path;

  /// 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.contextRoots.isEmpty) {
        _pluginMap.remove(plugin.pluginId);
        _notifyPluginsChanged();
        try {
          plugin.stop();
        } catch (e, st) {
          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);
        }
      }
    }
  }

  /// Sends a request based on the given [params] to existing _new_ (not legacy)
  /// plugins to set the analysis roots to those specified by [params].
  ///
  /// As a side-effect, records the parameters so that they can be sent to any
  /// newly started plugins.
  void setAnalysisSetAnalysisRootsParams(
    AnalysisSetAnalysisRootsParams params,
  ) {
    for (var isolate in newPluginIsolates) {
      isolate.setAnalysisRoots(params);
    }
    _analysisSetAnalysisRootsParams = params;
  }

  /// Sends 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, records 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;
  }

  /// Sends a request based on the given [params] to existing plugins to set the
  /// subscriptions to those specified by the [params].
  ///
  /// As a side-effect, records 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;
  }

  /// Sends 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, updates the overlay state so that it can be sent to any
  /// newly started plugins.
  void setAnalysisUpdateContentParams(
    AnalysisUpdateContentParams params, {
    String? precomputedNewContentForChange,
  }) {
    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) {
        if (precomputedNewContentForChange != null) {
          _overlayState[file] = AddContentOverlay(
            precomputedNewContentForChange,
          );
        } else {
          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}');
      }
    }
  }

  /// Stops all of the plugin isolates that are currently running.
  Future<List<void>> stopAll() {
    return Future.wait(
      _pluginMap.values.map((pluginIsolate) async {
        try {
          await pluginIsolate.stop();
        } catch (e, st) {
          instrumentationService.logException(e, st);
        }
      }),
    );
  }

  /// Compiles [entrypoint] to an AOT snapshot and records timing to the
  /// instrumentation log.
  ProcessResult _compileAotSnapshot(File entrypoint) {
    instrumentationService.logInfo(
      'Running "dart compile aot-snapshot $entrypoint".',
    );

    var stopwatch = Stopwatch()..start();
    var depfile = entrypoint.parent.getFile('depfile.txt');
    var aotSnapshotFile = entrypoint.parent.getFile('plugin.aot');
    if (aotSnapshotFile.exists) {
      try {
        // Delete any existing AOT snapshot. On MacOS, sometimes this file
        // becomes quarantined due to a race condition with codesigning and
        // overwriting the file.
        aotSnapshotFile.delete();
      } catch (e) {
        instrumentationService.logInfo(
          'Could not delete existing AOT plugin entrypoint at '
          '"$aotSnapshotFile": $e.',
        );
      }
    }
    var result = _processRunner.runSync(
      sdk.dart,
      ['compile', 'aot-snapshot', '--depfile', depfile.path, entrypoint.path],
      stderrEncoding: utf8,
      stdoutEncoding: utf8,
    );
    stopwatch.stop();

    instrumentationService.logInfo(
      'Running "dart compile aot-snapshot" took ${stopwatch.elapsed}.',
    );

    return result;
  }

  /// Compiles [pluginFile], in [pluginFolder], to an AOT snapshot, and returns
  /// the [File] for the snapshot.
  File _compileAsAot({required File pluginFile, required Folder pluginFolder}) {
    try {
      // Potentially use existing snapshot.
      var aotSnapshotFile = _existingAotSnapshot(
        resourceProvider: _resourceProvider,
        pluginFile: pluginFile,
        pluginFolder: pluginFolder,
      );
      if (aotSnapshotFile != null) {
        instrumentationService.logInfo(
          'Using existing plugin AOT snapshot at '
          "'${aotSnapshotFile.path}'",
        );
        return aotSnapshotFile;
      }
    } catch (error, stackTrace) {
      instrumentationService.logException(
        'Exception while checking an existing plugin AOT snapshot: '
        '"$error"\n$stackTrace',
      );
    }

    // When the Dart Analysis Server is built as AOT, then all spawned
    // Isolates must also be built as AOT.
    var aotResult = _compileAotSnapshot(pluginFile);
    if (aotResult.exitCode != 0) {
      var buffer = StringBuffer();
      buffer.writeln(
        'Failed to compile "${pluginFile.path}" to an AOT snapshot.',
      );
      var stderr = aotResult.stderr as String;
      if (stderr.contains('does not support build hooks')) {
        buffer.writeln(
          'One of the plugins uses Dart build hooks (or depends on a package '
          'which uses them); this is currently not supported.',
        );
      }
      buffer.writeln('  pluginFolder = ${pluginFolder.path}');
      buffer.writeln('  exitCode = ${aotResult.exitCode}');
      buffer.writeln('  stdout = ${aotResult.stdout}');
      buffer.writeln('  stderr = $stderr');
      var exceptionReason = buffer.toString();
      instrumentationService.logError(exceptionReason);
      throw PluginException(exceptionReason);
    }

    return pluginFolder.getFolder('bin').getFile('plugin.aot');
  }

  /// Computes the plugin files, given that the plugin should exist in
  /// [pluginFolder].
  ///
  /// Runs `pub <pubCommand>` in [pluginFolder] if [pubCommand] is not `null`.
  PluginFiles _computeFiles(
    Folder pluginFolder, {
    required bool builtAsAot,
    String? pubCommand,
    Workspace? workspace,
  }) {
    var pluginFile = pluginFolder.getFolder('bin').getFile('plugin.dart');
    if (!pluginFile.exists) {
      throw PluginException("File '${pluginFile.path}' does not exist.");
    }
    File? packageConfigFile = pluginFolder
        .getFolder(file_paths.dotDartTool)
        .getFile(file_paths.packageConfigJson);

    if (pubCommand != null) {
      var pubResult = _runPubCommand(
        pubCommand,
        workingDirectory: pluginFolder,
      );
      String? exceptionReason;
      if (pubResult.exitCode != 0) {
        var buffer = StringBuffer();
        buffer.writeln(
          'An error occurred while setting up the analyzer plugin package at '
          "'${pluginFolder.path}'. The `dart pub $pubCommand` command failed:",
        );
        buffer.writeln('  exitCode = ${pubResult.exitCode}');
        buffer.writeln('  stdout = ${pubResult.stdout}');
        buffer.writeln('  stderr = ${pubResult.stderr}');
        throw PluginException(buffer.toString());
      }
      if (!packageConfigFile.exists) {
        exceptionReason ??= 'File "${packageConfigFile.path}" does not exist.';
        throw PluginException(exceptionReason);
      }

      if (builtAsAot) {
        // Update the entrypoint path to be the AOT-compiled file.
        pluginFile = _compileAsAot(
          pluginFile: pluginFile,
          pluginFolder: pluginFolder,
        );
      }

      return PluginFiles(pluginFile, packageConfigFile);
    }

    if (!packageConfigFile.exists) {
      if (workspace == null) {
        throw PluginException('Could not create "${packageConfigFile.path}".');
      }

      packageConfigFile = _createPackageConfigFile(
        pluginFolder,
        workspace.packageUriResolver,
      );
      if (packageConfigFile == null) {
        throw PluginException(
          "Could not create the '${file_paths.packageConfigJson}' file in "
          "the workspace at '$workspace'.",
        );
      }
    }

    if (builtAsAot) {
      // Update the entrypoint path to be the AOT-compiled file.
      pluginFile = _compileAsAot(
        pluginFile: pluginFile,
        pluginFolder: pluginFolder,
      );
    }
    return PluginFiles(pluginFile, packageConfigFile);
  }

  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);
  }

  /// Returns 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 package config file.
  File? _createPackageConfigFile(
    Folder pluginFolder,
    UriResolver packageUriResolver,
  ) {
    var pluginPath = pluginFolder.path;
    var stateFolder = _resourceProvider.getStateLocation('.plugin_manager')!;
    var stateName = '${_uniqueDirectoryName(pluginPath)}.packages';
    var packageConfigFile = stateFolder.getFile(stateName);
    if (!packageConfigFile.exists) {
      var pluginPubspec = pluginFolder.getFile(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.getFile(file_paths.pubspecYaml));
              }
            }
          }
        }

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

        var packageConfigContent = const JsonEncoder.withIndent('  ').convert({
          'configVersion': 2,
          'packages': [
            for (var package in packages)
              {
                'name': package.name,
                'rootUri': '${package.root.toUri()}',
                'packageUri': 'lib/',
              },
          ],
        });
        packageConfigFile.writeAsStringSync('$packageConfigContent\n');
      } catch (exception) {
        // If we are not able to produce a package config file, return `null` so
        // that callers will not try to load the plugin.
        return null;
      }
    }
    return packageConfigFile;
  }

  /// Returns a viable existing plugin AOT snapshot, if it exists and its
  /// modification timestamp is newer than all of its dependencies, and `null`
  /// otherwise.
  ///
  /// The dependencies of an AOT snapshot are the pubspec file, the
  /// entrypoint file, and all of the files referenced in the depfile which
  /// is generated by the `dart compile` command.
  File? _existingAotSnapshot({
    required ResourceProvider resourceProvider,
    required File pluginFile,
    required Folder pluginFolder,
  }) {
    var aotSnapshotFile = pluginFolder.getFolder('bin').getFile('plugin.aot');
    if (!aotSnapshotFile.exists) return null;
    var snapshotModificationStamp = aotSnapshotFile.modificationStamp;

    if (pluginFile.modificationStamp > snapshotModificationStamp) return null;
    var pubspecFile = pluginFolder.getFile(file_paths.pubspecYaml);
    if (pubspecFile.modificationStamp > snapshotModificationStamp) return null;

    var depfile = pluginFolder.getFolder('bin').getFile('depfile.txt');
    if (!depfile.exists) return null;

    var content = depfile.readAsStringSync();
    var dependencies = parseDepfile(content);
    if (dependencies == null) {
      // Malformed depfile content.
      return null;
    }

    for (var dependencyPath in dependencies) {
      var file = _resourceProvider.getFile(dependencyPath);
      if (!file.exists) {
        // Something has certainly changed on disk; do not use the cached
        // snapshot.
        return null;
      }
      if (file.modificationStamp > snapshotModificationStamp) {
        // Snapshot is stale.
        return null;
      }
    }

    return aotSnapshotFile;
  }

  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>[];
  }

  /// Runs (and records timing to the instrumentation log) a Pub command
  /// [pubCommand] in [workingDirectory].
  ProcessResult _runPubCommand(
    String pubCommand, {
    required Folder workingDirectory,
  }) {
    instrumentationService.logInfo(
      'Running "pub $pubCommand" in "${workingDirectory.path}".',
    );

    var stopwatch = Stopwatch()..start();
    var result = _processRunner.runSync(
      sdk.dart,
      ['pub', pubCommand],
      workingDirectory: workingDirectory.path,
      environment: {_pubEnvironmentKey: _getPubEnvironmentValue()},
      stderrEncoding: utf8,
      stdoutEncoding: utf8,
    );
    stopwatch.stop();

    instrumentationService.logInfo(
      'Running "pub $pubCommand" took ${stopwatch.elapsed}.',
    );

    return result;
  }

  /// Returns 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);
  }

  /// Parses Ninja-style depfile content, returning a list of dependency paths.
  ///
  /// Returns `null` if the text is not valid depfile content.
  ///
  /// The format is:
  ///
  ///     target: dependency1 dependency2 ...
  ///
  /// See https://ninja-build.org/manual.html#_depfile.
  @visibleForTesting
  static List<String>? parseDepfile(String content) {
    var colonIndex = content.indexOf(': ');
    if (colonIndex < 0) {
      // Not a valid depfile.
      return null;
    }
    var dependenciesString = content
        .substring(colonIndex + 1)
        .trimLeft()
        .replaceAll(RegExp(r'[\r\n]'), '');
    var dependencies = <String>[];
    var start = 0;
    while (start < dependenciesString.length) {
      var index = start;
      while (index < dependenciesString.length) {
        var char = dependenciesString[index];
        if (char == ' ') {
          break;
        } else if (char == r'\') {
          index++;
        }
        index++;
      }
      dependencies.add(
        dependenciesString
            .substring(start, index)
            .replaceAll(r'\\', r'\')
            .replaceAll(r'\ ', ' '),
      );
      start = index + 1;
    }
    return dependencies.where((p) => p.isNotEmpty).toList();
  }

  /// Record the fact that the given [pluginIsolate] responded to a request with
  /// the given [method] in the given [time].
  static void recordResponseTime(
    PluginIsolate pluginIsolate,
    String method,
    int time,
  ) {
    pluginResponseTimes
        .putIfAbsent(pluginIsolate, () => <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(':');
  }
}

class _Package {
  final String name;
  final Folder root;

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