// 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, ProcessResult;

import 'package:analysis_server/src/plugin/notification_manager.dart';
import 'package:analyzer/context/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/bazel.dart';
import 'package:analyzer/src/generated/gn.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/workspace.dart';
import 'package:analyzer/src/util/glob.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:path/path.dart' as path;
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,
      NotificationManager notificationManager,
      InstrumentationService instrumentationService)
      : super(notificationManager, instrumentationService);

  @override
  ServerCommunicationChannel _createChannel() {
    return new 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,
      NotificationManager notificationManager,
      InstrumentationService instrumentationService)
      : super(notificationManager, instrumentationService);

  @override
  bool get canBeStarted => executionPath != null;

  @override
  String get pluginId => path;

  @override
  ServerCommunicationChannel _createChannel() {
    return new ServerIsolateChannel.discovered(
        new Uri.file(executionPath, windows: Platform.isWindows),
        new 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;
}

/**
 * Information about a single plugin.
 */
abstract class PluginInfo {
  /**
   * The object used to manage the receiving and sending of notifications.
   */
  final NotificationManager 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 = new HashSet<analyzer.ContextRoot>();

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

  /**
   * 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 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 =>
      new PluginData(pluginId, currentSession?.name, currentSession?.version);

  /**
   * 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) {
    bool changed = false;
    for (analyzer.ContextRoot 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.containsFile(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();
    }
  }

  /**
   * 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 new StateError('Cannot start a plugin that is already running.');
    }
    currentSession = new PluginSession(this);
    bool isRunning = await currentSession.start(byteStorePath, sdkPath);
    if (!isRunning) {
      currentSession = null;
    }
    return currentSession;
  }

  /**
   * Request that the plugin shutdown.
   */
  Future<Null> stop() {
    if (currentSession == null) {
      throw new StateError('Cannot stop a plugin that is not running.');
    }
    Future<Null> 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() {
    if (currentSession != null) {
      AnalysisSetContextRootsParams params = new AnalysisSetContextRootsParams(
          contextRoots
              .map((analyzer.ContextRoot contextRoot) => new ContextRoot(
                  contextRoot.root, contextRoot.exclude,
                  optionsFile: contextRoot.optionsFilePath))
              .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, List<int>>> pluginResponseTimes =
      <PluginInfo, Map<String, List<int>>>{};

  /**
   * 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 NotificationManager 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.
   */
  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.
   */
  Map<String, dynamic> _overlayState = <String, dynamic>{};

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

  /**
   * 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<Null> addPluginToContextRoot(
      analyzer.ContextRoot contextRoot, String path) async {
    PluginInfo plugin = _pluginMap[path];
    bool isNew = plugin == null;
    if (isNew) {
      List<String> pluginPaths;
      try {
        pluginPaths = pathsFor(path);
      } catch (exception, stackTrace) {
        plugin = new DiscoveredPluginInfo(
            path, null, null, notificationManager, instrumentationService);
        plugin.exception = new CaughtException(exception, stackTrace);
        _pluginMap[path] = plugin;
        return;
      }
      plugin = new DiscoveredPluginInfo(path, pluginPaths[0], pluginPaths[1],
          notificationManager, instrumentationService);
      _pluginMap[path] = plugin;
      if (pluginPaths[0] != null) {
        try {
          PluginSession session = await plugin.start(byteStorePath, sdkPath);
          session?.onDone?.then((_) {
            _pluginMap.remove(path);
          });
        } catch (exception, stackTrace) {
          // Record the exception (for debugging purposes) and record the fact
          // that we should not try to communicate with the plugin.
          plugin.exception = new CaughtException(exception, stackTrace);
          isNew = false;
        }
      }
    }
    plugin.addContextRoot(contextRoot);
    if (isNew) {
      if (_analysisSetSubscriptionsParams != null) {
        plugin.sendRequest(_analysisSetSubscriptionsParams);
      }
      if (_overlayState.isNotEmpty) {
        plugin.sendRequest(new AnalysisUpdateContentParams(_overlayState));
      }
      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}) {
    List<PluginInfo> plugins = pluginsForContextRoot(contextRoot);
    Map<PluginInfo, Future<Response>> responseMap =
        <PluginInfo, Future<Response>>{};
    for (PluginInfo plugin in plugins) {
      responseMap[plugin] = plugin.currentSession?.sendRequest(params);
    }
    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 {
    String filePath = watchEvent.path;

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

    WatchEvent event = null;
    List<Future<Response>> responses = <Future<Response>>[];
    for (PluginInfo plugin in _pluginMap.values) {
      PluginSession session = plugin.currentSession;
      if (session != null &&
          plugin.isAnalyzing(filePath) &&
          session.interestingFiles != null &&
          session.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);
        AnalysisHandleWatchEventsParams params =
            new AnalysisHandleWatchEventsParams([event]);
        responses.add(session.sendRequest(params));
      }
    }
    return responses;
  }

  /**
   * Return the execution path and .packages path associated with the plugin at
   * the given [path]. Throw a [PluginException] if there is a problem that
   * prevents the plugin from being executing.
   */
  @visibleForTesting
  List<String> pathsFor(String pluginPath) {
    Folder pluginFolder = resourceProvider.getFolder(pluginPath);
    File pubspecFile = pluginFolder.getChildAssumingFile('pubspec.yaml');
    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 _computePaths(pluginFolder);
    }
    Workspace workspace =
        BazelWorkspace.find(resourceProvider, pluginFolder.path) ??
            GnWorkspace.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 _computePaths(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.
    //
    Folder stateFolder = resourceProvider.getStateLocation('.plugin_manager');
    String stateName = _uniqueDirectoryName(pluginPath);
    Folder parentFolder = stateFolder.getChildAssumingFolder(stateName);
    if (parentFolder.exists) {
      Folder executionFolder =
          parentFolder.getChildAssumingFolder(pluginFolder.shortName);
      return _computePaths(executionFolder);
    }
    Folder executionFolder = pluginFolder.copyTo(parentFolder);
    return _computePaths(executionFolder, runPub: true);
  }

  /**
   * 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();
    }
    List<PluginInfo> plugins = <PluginInfo>[];
    for (PluginInfo plugin in _pluginMap.values) {
      if (plugin.contextRoots.contains(contextRoot)) {
        plugins.add(plugin);
      }
    }
    return plugins;
  }

  /**
   * Record a failure to run the plugin associated with the host package with
   * the given [hostPackageName]. The failure is described by the [message], and
   * is expected to have occurred before a path could be computed, and hence
   * before [addPluginToContextRoot] could be invoked.
   */
  void recordPluginFailure(String hostPackageName, String message) {
    try {
      throw new PluginException(message);
    } catch (exception, stackTrace) {
      String pluginPath =
          path.join(hostPackageName, 'tools', 'analyzer_plugin');
      DiscoveredPluginInfo plugin = new DiscoveredPluginInfo(
          pluginPath, null, null, notificationManager, instrumentationService);
      plugin.exception = new CaughtException(exception, stackTrace);
      _pluginMap[pluginPath] = plugin;
    }
  }

  /**
   * The given [contextRoot] is no longer being analyzed.
   */
  void removedContextRoot(analyzer.ContextRoot contextRoot) {
    List<PluginInfo> plugins = _pluginMap.values.toList();
    for (PluginInfo plugin in plugins) {
      plugin.removeContextRoot(contextRoot);
      if (plugin is DiscoveredPluginInfo && plugin.contextRoots.isEmpty) {
        _pluginMap.remove(plugin.path);
        plugin.stop();
      }
    }
  }

  /**
   * Restart all currently running plugins.
   */
  Future<Null> restartPlugins() async {
    for (PluginInfo plugin in _pluginMap.values.toList()) {
      if (plugin.currentSession != null) {
        //
        // Capture needed state.
        //
        Set<analyzer.ContextRoot> contextRoots = plugin.contextRoots;
        String path = plugin.pluginId;
        //
        // Stop the plugin.
        //
        await plugin.stop();
        //
        // Restart the plugin.
        //
        _pluginMap[path] = plugin;
        PluginSession session = await plugin.start(byteStorePath, sdkPath);
        session?.onDone?.then((_) {
          _pluginMap.remove(path);
        });
        //
        // Re-initialize the plugin.
        //
        plugin.addContextRoots(contextRoots);
        if (_analysisSetSubscriptionsParams != null) {
          plugin.sendRequest(_analysisSetSubscriptionsParams);
        }
        if (_overlayState.isNotEmpty) {
          plugin.sendRequest(new AnalysisUpdateContentParams(_overlayState));
        }
        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 (PluginInfo 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 (PluginInfo 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 (PluginInfo plugin in _pluginMap.values) {
      plugin.sendRequest(params);
    }
    Map<String, dynamic> files = params.files;
    for (String file in files.keys) {
      Object overlay = files[file];
      if (overlay is RemoveContentOverlay) {
        _overlayState.remove(file);
      } else if (overlay is AddContentOverlay) {
        _overlayState[file] = overlay;
      } else if (overlay is ChangeContentOverlay) {
        AddContentOverlay previousOverlay = _overlayState[file];
        String newContent =
            SourceEdit.applySequence(previousOverlay.content, overlay.edits);
        _overlayState[file] = new AddContentOverlay(newContent);
      } else {
        throw new ArgumentError(
            'Invalid class of overlay: ${overlay.runtimeType}');
      }
    }
  }

  /**
   * Stop all of the plugins that are currently running.
   */
  Future<List<Null>> stopAll() {
    return Future.wait(_pluginMap.values.map((PluginInfo info) => info.stop()));
  }

  /**
   * Compute the paths to be returned by the enclosing method given that the
   * plugin should exist in the given [pluginFolder].
   */
  List<String> _computePaths(Folder pluginFolder,
      {bool runPub: false, Workspace workspace}) {
    File pluginFile = pluginFolder
        .getChildAssumingFolder('bin')
        .getChildAssumingFile('plugin.dart');
    if (!pluginFile.exists) {
      throw new PluginException('File "${pluginFile.path}" does not exist.');
    }
    String reason;
    File packagesFile = pluginFolder.getChildAssumingFile('.packages');
    if (!packagesFile.exists) {
      if (runPub) {
        String vmPath = Platform.executable;
        String pubPath = path.join(path.dirname(vmPath), 'pub');
        if (Platform.isWindows) {
          // Process.run requires the `.bat` suffix on Windows
          pubPath = '$pubPath.bat';
        }
        ProcessResult result = Process.runSync(pubPath, <String>['get'],
            stderrEncoding: utf8,
            stdoutEncoding: utf8,
            workingDirectory: pluginFolder.path,
            environment: {_pubEnvironmentKey: _getPubEnvironmentValue()});
        if (result.exitCode != 0) {
          StringBuffer buffer = new StringBuffer();
          buffer.writeln('Failed to run pub get');
          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 (workspace != null) {
        packagesFile =
            _createPackagesFile(pluginFolder, workspace.packageUriResolver);
        if (packagesFile == null) {
          reason = 'Could not create .packages file in workspace $workspace.';
        }
      } else {
        reason = 'Could not create "${packagesFile.path}".';
        packagesFile = null;
      }
    }
    if (packagesFile == null) {
      throw new PluginException(reason);
    }
    return <String>[pluginFile.path, packagesFile.path];
  }

  WatchEventType _convertChangeType(watcher.ChangeType type) {
    switch (type) {
      case watcher.ChangeType.ADD:
        return WatchEventType.ADD;
      case watcher.ChangeType.MODIFY:
        return WatchEventType.MODIFY;
      case watcher.ChangeType.REMOVE:
        return WatchEventType.REMOVE;
      default:
        throw new StateError('Unknown change type: $type');
    }
  }

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

  /**
   * Return a temporary `.packages` 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) {
    String pluginPath = pluginFolder.path;
    Folder stateFolder = resourceProvider.getStateLocation('.plugin_manager');
    String stateName = _uniqueDirectoryName(pluginPath) + '.packages';
    File packagesFile = stateFolder.getChildAssumingFile(stateName);
    if (!packagesFile.exists) {
      File pluginPubspec = pluginFolder.getChildAssumingFile('pubspec.yaml');
      if (!pluginPubspec.exists) {
        return null;
      }

      try {
        Map<String, String> visitedPackages = <String, String>{};
        path.Context context = resourceProvider.pathContext;
        visitedPackages[context.basename(pluginPath)] =
            context.join(pluginFolder.path, 'lib');
        List<File> pubspecFiles = <File>[];
        pubspecFiles.add(pluginPubspec);
        while (pubspecFiles.isNotEmpty) {
          File pubspecFile = pubspecFiles.removeLast();
          for (String packageName in _readDependecies(pubspecFile)) {
            if (!visitedPackages.containsKey(packageName)) {
              Uri uri = Uri.parse('package:$packageName/$packageName.dart');
              Source packageSource = packageUriResolver.resolveAbsolute(uri);
              String libDirPath = context.dirname(packageSource.fullName);
              visitedPackages[packageName] = libDirPath;
              String pubspecPath =
                  context.join(context.dirname(libDirPath), 'pubspec.yaml');
              pubspecFiles.add(resourceProvider.getFile(pubspecPath));
            }
          }
        }

        StringBuffer buffer = new StringBuffer();
        visitedPackages.forEach((String name, String path) {
          buffer.write(name);
          buffer.write(':');
          buffer.writeln(new Uri.file(path));
        });
        packagesFile.writeAsStringSync(buffer.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;
  }

  /**
   * Return the names of packages that are listed as dependencies in the given
   * [pubspecFile].
   */
  Iterable<String> _readDependecies(File pubspecFile) {
    YamlDocument document = loadYamlDocument(pubspecFile.readAsStringSync(),
        sourceUrl: pubspecFile.toUri());
    YamlNode contents = document.contents;
    if (contents is YamlMap) {
      YamlNode dependencies = contents['dependencies'];
      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) {
    List<int> 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, List<int>>{})
        .putIfAbsent(method, () => <int>[])
        .add(time);
  }

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

  /**
   * 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 = const 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 =
      const Duration(seconds: 10);

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

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

  /**
   * 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.
   */
  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<Null> get onDone => pluginStoppedCompleter.future;

  /**
   * Handle the given [notification].
   */
  void handleNotification(Notification notification) {
    if (notification.event == PLUGIN_NOTIFICATION_ERROR) {
      PluginErrorParams params =
          new 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(List<String> errorPair) {
    StackTrace stackTrace = new StackTrace.fromString(errorPair[1]);
    info.exception =
        new CaughtException(new PluginException(errorPair[0]), stackTrace);
    info.instrumentationService
        .logPluginException(info.data, 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) {
    _PendingRequest requestData = pendingRequests.remove(response.id);
    int responseTime = new DateTime.now().millisecondsSinceEpoch;
    int duration = responseTime - requestData.requestTime;
    PluginManager.recordResponseTime(info, requestData.method, duration);
    Completer<Response> completer = requestData.completer;
    if (completer != null) {
      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.
    int cutOffTime = new 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) {
    if (channel == null) {
      throw new StateError(
          'Cannot send a request to a plugin that has stopped.');
    }
    String id = nextRequestId;
    Completer<Response> completer = new Completer();
    int requestTime = new DateTime.now().millisecondsSinceEpoch;
    Request request = parameters.toRequest(id);
    pendingRequests[id] =
        new _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 new StateError('Cannot start a plugin that is already running.');
    }
    if (byteStorePath == null || byteStorePath.isEmpty) {
      throw new StateError('Missing byte store path');
    }
    if (!isCompatible) {
      info.exception = new CaughtException(
          new PluginException('Plugin is not compatible.'), null);
      return false;
    }
    if (!info.canBeStarted) {
      info.exception = new CaughtException(
          new PluginException('Plugin cannot be started.'), null);
      return false;
    }
    channel = info._createChannel();
    await channel.listen(handleResponse, handleNotification,
        onDone: handleOnDone, onError: handleOnError);
    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.exception ??= new CaughtException(
          new PluginException('Unrecorded error while starting the plugin.'),
          null);
      return false;
    }
    Response response = await sendRequest(new PluginVersionCheckParams(
        byteStorePath ?? '', sdkPath, '1.0.0-alpha.0'));
    PluginVersionCheckResult result =
        new PluginVersionCheckResult.fromResponse(response);
    isCompatible = result.isCompatible;
    contactInfo = result.contactInfo;
    interestingFiles = result.interestingFiles;
    name = result.name;
    version = result.version;
    if (!isCompatible) {
      sendRequest(new PluginShutdownParams());
      info.exception = new CaughtException(
          new PluginException('Plugin is not compatible.'), null);
      return false;
    }
    return true;
  }

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

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