// 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].
  PluginException(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;

  PluginFiles(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.
  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].
  PluginManager(
    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.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, 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.getChildAssumingFolder(
        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.getChildAssumingFolder(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.getChildAssumingFile('depfile.txt');
    var aotSnapshotFile = entrypoint.parent.getChildAssumingFile('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
        .getChildAssumingFolder('bin')
        .getChildAssumingFile('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
        .getChildAssumingFolder('bin')
        .getChildAssumingFile('plugin.dart');
    if (!pluginFile.exists) {
      throw PluginException("File '${pluginFile.path}' does not exist.");
    }
    File? packageConfigFile = pluginFolder
        .getChildAssumingFolder(file_paths.dotDartTool)
        .getChildAssumingFile(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.getChildAssumingFile(stateName);
    if (!packageConfigFile.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 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
        .getChildAssumingFolder('bin')
        .getChildAssumingFile('plugin.aot');
    if (!aotSnapshotFile.exists) return null;
    var snapshotModificationStamp = aotSnapshotFile.modificationStamp;

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

    var depfile = pluginFolder
        .getChildAssumingFolder('bin')
        .getChildAssumingFile('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;

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