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

library analysis.server;

import 'dart:async';
import 'dart:collection';
import 'dart:core';
import 'dart:io' as io;
import 'dart:math' show max;

import 'package:analysis_server/plugin/protocol/protocol.dart'
    hide AnalysisOptions, Element;
import 'package:analysis_server/src/analysis_logger.dart';
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/computer/computer_highlights.dart';
import 'package:analysis_server/src/computer/computer_highlights2.dart';
import 'package:analysis_server/src/computer/computer_outline.dart';
import 'package:analysis_server/src/computer/new_notifications.dart';
import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/domains/analysis/navigation.dart';
import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
import 'package:analysis_server/src/domains/analysis/occurrences.dart';
import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
import 'package:analysis_server/src/operation/operation.dart';
import 'package:analysis_server/src/operation/operation_analysis.dart';
import 'package:analysis_server/src/operation/operation_queue.dart';
import 'package:analysis_server/src/plugin/notification_manager.dart';
import 'package:analysis_server/src/plugin/server_plugin.dart';
import 'package:analysis_server/src/protocol_server.dart' as server;
import 'package:analysis_server/src/server/diagnostic_server.dart';
import 'package:analysis_server/src/services/correction/namespace.dart';
import 'package:analysis_server/src/services/index/index.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import 'package:analysis_server/src/services/search/search_engine_internal2.dart';
import 'package:analysis_server/src/single_context_manager.dart';
import 'package:analysis_server/src/utilities/null_string_sink.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/pub_package_map_provider.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/dart/analysis/ast_provider_context.dart';
import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
import 'package:analyzer/src/dart/analysis/file_byte_store.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart' as nd;
import 'package:analyzer/src/dart/analysis/status.dart' as nd;
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/ast_provider.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/src/util/glob.dart';
import 'package:analyzer/task/dart.dart';
import 'package:plugin/plugin.dart';

typedef void OptionUpdater(AnalysisOptionsImpl options);

/**
 * Enum representing reasons why analysis might be done for a given file.
 */
class AnalysisDoneReason {
  /**
   * Analysis of the file completed successfully.
   */
  static const AnalysisDoneReason COMPLETE =
      const AnalysisDoneReason._('COMPLETE');

  /**
   * Analysis of the file was aborted because the context was removed.
   */
  static const AnalysisDoneReason CONTEXT_REMOVED =
      const AnalysisDoneReason._('CONTEXT_REMOVED');

  /**
   * Textual description of this [AnalysisDoneReason].
   */
  final String text;

  const AnalysisDoneReason._(this.text);
}

/**
 * Instances of the class [AnalysisServer] implement a server that listens on a
 * [CommunicationChannel] for analysis requests and process them.
 */
class AnalysisServer {
  /**
   * The version of the analysis server. The value should be replaced
   * automatically during the build.
   */
  static final String VERSION = '1.18.0';

  /**
   * The number of milliseconds to perform operations before inserting
   * a 1 millisecond delay so that the VM and dart:io can deliver content
   * to stdin. This should be removed once the underlying problem is fixed.
   */
  static int performOperationDelayFrequency = 25;

  /**
   * The options of this server instance.
   */
  AnalysisServerOptions options;

  /**
   * The channel from which requests are received and to which responses should
   * be sent.
   */
  final ServerCommunicationChannel channel;

  /**
   * The object used to manage sending a subset of notifications to the client.
   * The subset of notifications are those to which plugins may contribute.
   * This field is `null` when the new plugin support is disabled.
   */
  final NotificationManager notificationManager;

  /**
   * The [ResourceProvider] using which paths are converted into [Resource]s.
   */
  final ResourceProvider resourceProvider;

  /**
   * The [Index] for this server, may be `null` if indexing is disabled.
   */
  final Index index;

  /**
   * The [SearchEngine] for this server, may be `null` if indexing is disabled.
   */
  SearchEngine searchEngine;

  /**
   * The plugin associated with this analysis server.
   */
  final ServerPlugin serverPlugin;

  /**
   * A list of the globs used to determine which files should be analyzed. The
   * list is lazily created and should be accessed using [analyzedFilesGlobs].
   */
  List<Glob> _analyzedFilesGlobs = null;

  /**
   * The [ContextManager] that handles the mapping from analysis roots to
   * context directories.
   */
  ContextManager contextManager;

  /**
   * A flag indicating whether the server is running.  When false, contexts
   * will no longer be added to [contextWorkQueue], and [performOperation] will
   * discard any tasks it finds on [contextWorkQueue].
   */
  bool running;

  /**
   * A flag indicating the value of the 'analyzing' parameter sent in the last
   * status message to the client.
   */
  bool statusAnalyzing = false;

  /**
   * A list of the request handlers used to handle the requests sent to this
   * server.
   */
  List<RequestHandler> handlers;

  /**
   * The object used to manage the SDK's known to this server.
   */
  DartSdkManager sdkManager;

  /**
   * The instrumentation service that is to be used by this analysis server.
   */
  final InstrumentationService instrumentationService;

  /**
   * A queue of the operations to perform in this server.
   */
  ServerOperationQueue operationQueue;

  /**
   * True if there is a pending future which will execute [performOperation].
   */
  bool performOperationPending = false;

  /**
   * A set of the [ServerService]s to send notifications for.
   */
  Set<ServerService> serverServices = new HashSet<ServerService>();

  /**
   * A set of the [GeneralAnalysisService]s to send notifications for.
   */
  Set<GeneralAnalysisService> generalAnalysisServices =
      new HashSet<GeneralAnalysisService>();

  /**
   * A table mapping [AnalysisService]s to the file paths for which these
   * notifications should be sent.
   */
  Map<AnalysisService, Set<String>> analysisServices =
      new HashMap<AnalysisService, Set<String>>();

  /**
   * A table mapping [AnalysisContext]s to the completers that should be
   * completed when analysis of this context is finished.
   */
  Map<AnalysisContext, Completer<AnalysisDoneReason>>
      contextAnalysisDoneCompleters =
      new HashMap<AnalysisContext, Completer<AnalysisDoneReason>>();

  /**
   * Performance information before initial analysis is complete.
   */
  ServerPerformance performanceDuringStartup = new ServerPerformance();

  /**
   * Performance information after initial analysis is complete
   * or `null` if the initial analysis is not yet complete
   */
  ServerPerformance performanceAfterStartup;

  /**
   * The class into which performance information is currently being recorded.
   * During startup, this will be the same as [performanceDuringStartup]
   * and after startup is complete, this switches to [performanceAfterStartup].
   */
  ServerPerformance _performance;

  /**
   * The [Completer] that completes when analysis is complete.
   */
  Completer _onAnalysisCompleteCompleter;

  /**
   * The [Completer] that completes when the next operation is performed.
   */
  Completer _test_onOperationPerformedCompleter;

  /**
   * The controller that is notified when analysis is started.
   */
  StreamController<bool> _onAnalysisStartedController;

  /**
   * The controller that is notified when a single file has been analyzed.
   */
  StreamController<ChangeNotice> _onFileAnalyzedController;

  /**
   * The controller used to notify others when priority sources change.
   */
  StreamController<PriorityChangeEvent> _onPriorityChangeController;

  /**
   * True if any exceptions thrown by analysis should be propagated up the call
   * stack.
   */
  bool rethrowExceptions;

  /**
   * The next time (milliseconds since epoch) after which the analysis server
   * should pause so that pending requests can be fetched by the system.
   */
  // Add 1 sec to prevent delay from impacting short running tests
  int _nextPerformOperationDelayTime =
      new DateTime.now().millisecondsSinceEpoch + 1000;

  /**
   * The content overlay for all analysis drivers.
   */
  final nd.FileContentOverlay fileContentOverlay = new nd.FileContentOverlay();

  /**
   * The current state of overlays from the client.  This is used as the
   * content cache for all contexts.
   */
  final ContentCache overlayState = new ContentCache();

  /**
   * The plugins that are defined outside the analysis_server package.
   */
  List<Plugin> userDefinedPlugins;

  /**
   * If the "analysis.analyzedFiles" notification is currently being subscribed
   * to (see [generalAnalysisServices]), and at least one such notification has
   * been sent since the subscription was enabled, the set of analyzed files
   * that was delivered in the most recently sent notification.  Otherwise
   * `null`.
   */
  Set<String> prevAnalyzedFiles;

  /**
   * The default options used to create new analysis contexts. This object is
   * also referenced by the ContextManager.
   */
  final AnalysisOptionsImpl defaultContextOptions = new AnalysisOptionsImpl();

  /**
   * The controller for sending [ContextsChangedEvent]s.
   */
  StreamController<ContextsChangedEvent> _onContextsChangedController =
      new StreamController<ContextsChangedEvent>.broadcast();

  /**
   * The file resolver provider used to override the way file URI's are
   * resolved in some contexts.
   */
  ResolverProvider fileResolverProvider;

  /**
   * The package resolver provider used to override the way package URI's are
   * resolved in some contexts.
   */
  ResolverProvider packageResolverProvider;

  nd.PerformanceLog _analysisPerformanceLogger;
  ByteStore byteStore;
  nd.AnalysisDriverScheduler analysisDriverScheduler;

  /**
   * This exists as a temporary stopgap for plugins, until the official plugin
   * API is complete.
   */
  StreamController<String> _onFileAddedController;

  /**
   * This exists as a temporary stopgap for plugins, until the official plugin
   * API is complete.
   */
  StreamController<String> _onFileChangedController;

  /**
   * The set of the files that are currently priority.
   */
  final Set<String> priorityFiles = new Set<String>();

  /**
   * The DiagnosticServer for this AnalysisServer. If available, it can be used
   * to start an http diagnostics server or return the port for an existing
   * server.
   */
  DiagnosticServer diagnosticServer;

  /**
   * Initialize a newly created server to receive requests from and send
   * responses to the given [channel].
   *
   * If [rethrowExceptions] is true, then any exceptions thrown by analysis are
   * propagated up the call stack.  The default is true to allow analysis
   * exceptions to show up in unit tests, but it should be set to false when
   * running a full analysis server.
   */
  AnalysisServer(
      this.channel,
      this.resourceProvider,
      PubPackageMapProvider packageMapProvider,
      this.index,
      this.serverPlugin,
      this.options,
      this.sdkManager,
      this.instrumentationService,
      {this.diagnosticServer,
      ResolverProvider fileResolverProvider: null,
      ResolverProvider packageResolverProvider: null,
      bool useSingleContextManager: false,
      this.rethrowExceptions: true})
      : notificationManager =
            new NotificationManager(channel, resourceProvider) {
    _performance = performanceDuringStartup;
    defaultContextOptions.incremental = true;
    defaultContextOptions.incrementalApi =
        options.enableIncrementalResolutionApi;
    defaultContextOptions.incrementalValidation =
        options.enableIncrementalResolutionValidation;
    defaultContextOptions.finerGrainedInvalidation =
        options.finerGrainedInvalidation;
    defaultContextOptions.generateImplicitErrors = false;
    operationQueue = new ServerOperationQueue();

    {
      String name = options.newAnalysisDriverLog;
      StringSink sink = new NullStringSink();
      if (name != null) {
        if (name == 'stdout') {
          sink = io.stdout;
        } else if (name.startsWith('file:')) {
          String path = name.substring('file:'.length);
          sink = new io.File(path).openWrite(mode: io.FileMode.APPEND);
        }
      }
      _analysisPerformanceLogger = new nd.PerformanceLog(sink);
    }
    byteStore = _createByteStore();
    analysisDriverScheduler =
        new nd.AnalysisDriverScheduler(_analysisPerformanceLogger);
    analysisDriverScheduler.status.listen(sendStatusNotificationNew);
    analysisDriverScheduler.start();

    if (useSingleContextManager) {
      contextManager = new SingleContextManager(resourceProvider, sdkManager,
          packageResolverProvider, analyzedFilesGlobs, defaultContextOptions);
    } else {
      contextManager = new ContextManagerImpl(
          resourceProvider,
          sdkManager,
          packageResolverProvider,
          packageMapProvider,
          analyzedFilesGlobs,
          instrumentationService,
          defaultContextOptions,
          options.enableNewAnalysisDriver);
    }
    this.fileResolverProvider = fileResolverProvider;
    this.packageResolverProvider = packageResolverProvider;
    ServerContextManagerCallbacks contextManagerCallbacks =
        new ServerContextManagerCallbacks(this, resourceProvider);
    contextManager.callbacks = contextManagerCallbacks;
    AnalysisEngine.instance.logger = new AnalysisLogger(this);
    _onAnalysisStartedController = new StreamController.broadcast();
    _onFileAnalyzedController = new StreamController.broadcast();
    // temporary plugin support:
    _onFileAddedController = new StreamController.broadcast();
    // temporary plugin support:
    _onFileChangedController = new StreamController.broadcast();
    _onPriorityChangeController =
        new StreamController<PriorityChangeEvent>.broadcast();
    running = true;
    onAnalysisStarted.first.then((_) {
      onAnalysisComplete.then((_) {
        performanceAfterStartup = new ServerPerformance();
        _performance = performanceAfterStartup;
      });
    });
    _setupIndexInvalidation();
    if (options.enableNewAnalysisDriver) {
      searchEngine = new SearchEngineImpl2(driverMap.values);
    } else if (index != null) {
      searchEngine = new SearchEngineImpl(index, getAstProvider);
    }
    Notification notification = new ServerConnectedParams(VERSION, io.pid,
            sessionId: instrumentationService.sessionId)
        .toNotification();
    channel.sendNotification(notification);
    channel.listen(handleRequest, onDone: done, onError: error);
    handlers = serverPlugin.createDomains(this);
  }

  /**
   * Return the [AnalysisContext]s that are being used to analyze the analysis
   * roots.
   */
  Iterable<AnalysisContext> get analysisContexts =>
      contextManager.analysisContexts;

  /**
   * Return a list of the globs used to determine which files should be analyzed.
   */
  List<Glob> get analyzedFilesGlobs {
    if (_analyzedFilesGlobs == null) {
      _analyzedFilesGlobs = <Glob>[];
      List<String> patterns = serverPlugin.analyzedFilePatterns;
      for (String pattern in patterns) {
        try {
          _analyzedFilesGlobs
              .add(new Glob(resourceProvider.pathContext.separator, pattern));
        } catch (exception, stackTrace) {
          AnalysisEngine.instance.logger.logError(
              'Invalid glob pattern: "$pattern"',
              new CaughtException(exception, stackTrace));
        }
      }
    }
    return _analyzedFilesGlobs;
  }

  /**
   * A table mapping [Folder]s to the [AnalysisDriver]s associated with them.
   */
  Map<Folder, nd.AnalysisDriver> get driverMap => contextManager.driverMap;

  /**
   * Return a table mapping [Folder]s to the [AnalysisContext]s associated with
   * them.
   */
  Map<Folder, AnalysisContext> get folderMap => contextManager.folderMap;

  /**
   * The [Future] that completes when analysis is complete.
   */
  Future get onAnalysisComplete {
    if (isAnalysisComplete()) {
      return new Future.value();
    }
    if (_onAnalysisCompleteCompleter == null) {
      _onAnalysisCompleteCompleter = new Completer();
    }
    return _onAnalysisCompleteCompleter.future;
  }

  /**
   * The stream that is notified with `true` when analysis is started.
   */
  Stream<bool> get onAnalysisStarted {
    return _onAnalysisStartedController.stream;
  }

  /**
   * The stream that is notified when contexts are added or removed.
   */
  Stream<ContextsChangedEvent> get onContextsChanged =>
      _onContextsChangedController.stream;

  /**
   * The stream that is notified when a single file has been analyzed.
   */
  Stream get onFileAnalyzed => _onFileAnalyzedController.stream;

  /**
   * The stream that is notified when a single file has been added. This exists
   * as a temporary stopgap for plugins, until the official plugin API is
   * complete.
   */
  Stream get onFileAdded => _onFileAddedController.stream;

  /**
   * The stream that is notified when a single file has been changed. This
   * exists as a temporary stopgap for plugins, until the official plugin API is
   * complete.
   */
  Stream get onFileChanged => _onFileChangedController.stream;

  /**
   * The stream that is notified when priority sources change.
   */
  Stream<PriorityChangeEvent> get onPriorityChange =>
      _onPriorityChangeController.stream;

  /**
   * The [Future] that completes when the next operation is performed.
   */
  Future get test_onOperationPerformed {
    if (_test_onOperationPerformedCompleter == null) {
      _test_onOperationPerformedCompleter = new Completer();
    }
    return _test_onOperationPerformedCompleter.future;
  }

  /**
   * Adds the given [ServerOperation] to the queue, but does not schedule
   * operations execution.
   */
  void addOperation(ServerOperation operation) {
    operationQueue.add(operation);
  }

  /**
   * The socket from which requests are being read has been closed.
   */
  void done() {
    index?.stop();
    running = false;
  }

  /**
   * There was an error related to the socket from which requests are being
   * read.
   */
  void error(argument) {
    running = false;
  }

  /**
   * If the given notice applies to a file contained within an analysis root,
   * notify interested parties that the file has been (at least partially)
   * analyzed.
   */
  void fileAnalyzed(ChangeNotice notice) {
    if (contextManager.isInAnalysisRoot(notice.source.fullName)) {
      _onFileAnalyzedController.add(notice);
    }
  }

  /**
   * Return one of the SDKs that has been created, or `null` if no SDKs have
   * been created yet.
   */
  DartSdk findSdk() {
    DartSdk sdk = sdkManager.anySdk;
    if (sdk != null) {
      return sdk;
    }
    // TODO(brianwilkerson) Should we create an SDK using the default options?
    return null;
  }

  /**
   * Return the preferred [AnalysisContext] for analyzing the given [path].
   * This will be the context that explicitly contains the path, if any such
   * context exists, otherwise it will be the first analysis context that
   * implicitly analyzes it.  Return `null` if no context is analyzing the
   * path.
   */
  AnalysisContext getAnalysisContext(String path) {
    return getContextSourcePair(path).context;
  }

  /**
   * Return any [AnalysisContext] that is analyzing the given [source], either
   * explicitly or implicitly.  Return `null` if there is no such context.
   */
  AnalysisContext getAnalysisContextForSource(Source source) {
    for (AnalysisContext context in analysisContexts) {
      SourceKind kind = context.getKindOf(source);
      if (kind != SourceKind.UNKNOWN) {
        return context;
      }
    }
    return null;
  }

  /**
   * Return an analysis driver to which the file with the given [path] is
   * added if one exists, otherwise a driver in which the file was analyzed if
   * one exists, otherwise the first driver, otherwise `null`.
   */
  nd.AnalysisDriver getAnalysisDriver(String path) {
    Iterable<nd.AnalysisDriver> drivers = driverMap.values;
    if (drivers.isNotEmpty) {
      nd.AnalysisDriver driver = drivers.firstWhere(
          (driver) => driver.addedFiles.contains(path),
          orElse: () => null);
      driver ??= drivers.firstWhere(
          (driver) => driver.knownFiles.contains(path),
          orElse: () => null);
      driver ??= drivers.first;
      return driver;
    }
    return null;
  }

  /**
   * Return the analysis result for the file with the given [path]. The file is
   * analyzed in one of the analysis drivers to which the file was added,
   * otherwise in the first driver, otherwise `null` is returned.
   */
  Future<nd.AnalysisResult> getAnalysisResult(String path) async {
    try {
      nd.AnalysisDriver driver = getAnalysisDriver(path);
      return await driver?.getResult(path);
    } catch (e) {
      // Ignore the exception.
      // We don't want to log the same exception again and again.
      return null;
    }
  }

  /**
   * Return the [AstProvider] for the given [path].
   */
  AstProvider getAstProvider(String path) {
    if (options.enableNewAnalysisDriver) {
      var analysisDriver = getAnalysisDriver(path);
      return new AstProviderForDriver(analysisDriver);
    } else {
      var analysisContext = getAnalysisContext(path);
      return new AstProviderForContext(analysisContext);
    }
  }

  CompilationUnitElement getCompilationUnitElement(String file) {
    ContextSourcePair pair = getContextSourcePair(file);
    if (pair == null) {
      return null;
    }
    // prepare AnalysisContext and Source
    AnalysisContext context = pair.context;
    Source unitSource = pair.source;
    if (context == null || unitSource == null) {
      return null;
    }
    // get element in the first library
    List<Source> librarySources = context.getLibrariesContaining(unitSource);
    if (!librarySources.isNotEmpty) {
      return null;
    }
    Source librarySource = librarySources.first;
    return context.getCompilationUnitElement(unitSource, librarySource);
  }

  /**
   * Return the [AnalysisContext] for the "innermost" context whose associated
   * folder is or contains the given path.  ("innermost" refers to the nesting
   * of contexts, so if there is a context for path /foo and a context for
   * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is
   * the context for /foo/bar.)
   *
   * If no context contains the given path, `null` is returned.
   */
  AnalysisContext getContainingContext(String path) {
    return contextManager.getContextFor(path);
  }

  /**
   * Return the [nd.AnalysisDriver] for the "innermost" context whose associated
   * folder is or contains the given path.  ("innermost" refers to the nesting
   * of contexts, so if there is a context for path /foo and a context for
   * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is
   * the context for /foo/bar.)
   *
   * If no context contains the given path, `null` is returned.
   */
  nd.AnalysisDriver getContainingDriver(String path) {
    return contextManager.getDriverFor(path);
  }

  /**
   * Return the primary [ContextSourcePair] representing the given [path].
   *
   * The [AnalysisContext] of this pair will be the context that explicitly
   * contains the path, if any such context exists, otherwise it will be the
   * first context that implicitly analyzes it.
   *
   * If the [path] is not analyzed by any context, a [ContextSourcePair] with
   * a `null` context and a `file` [Source] is returned.
   *
   * If the [path] doesn't represent a file, a [ContextSourcePair] with a `null`
   * context and `null` [Source] is returned.
   *
   * Does not return `null`.
   */
  ContextSourcePair getContextSourcePair(String path) {
    // try SDK
    {
      DartSdk sdk = findSdk();
      if (sdk != null) {
        Uri uri = resourceProvider.pathContext.toUri(path);
        Source sdkSource = sdk.fromFileUri(uri);
        if (sdkSource != null) {
          return new ContextSourcePair(sdk.context, sdkSource);
        }
      }
    }
    // try to find the deep-most containing context
    Resource resource = resourceProvider.getResource(path);
    if (resource is! File) {
      return new ContextSourcePair(null, null);
    }
    File file = resource;
    {
      AnalysisContext containingContext = getContainingContext(path);
      if (containingContext != null) {
        Source source =
            ContextManagerImpl.createSourceInContext(containingContext, file);
        return new ContextSourcePair(containingContext, source);
      }
    }
    // try to find a context that analysed the file
    for (AnalysisContext context in analysisContexts) {
      Source source = ContextManagerImpl.createSourceInContext(context, file);
      SourceKind kind = context.getKindOf(source);
      if (kind != SourceKind.UNKNOWN) {
        return new ContextSourcePair(context, source);
      }
    }
    // try to find a context for which the file is a priority source
    for (InternalAnalysisContext context in analysisContexts) {
      List<Source> sources = context.getSourcesWithFullName(path);
      if (sources.isNotEmpty) {
        Source source = sources.first;
        return new ContextSourcePair(context, source);
      }
    }
    // file-based source
    Source fileSource = file.createSource();
    return new ContextSourcePair(null, fileSource);
  }

  /**
   * Return a [Future] that completes with the [Element] at the given
   * [offset] of the given [file], or with `null` if there is no node at the
   * [offset] or the node does not have an element.
   */
  Future<Element> getElementAtOffset(String file, int offset) async {
    AstNode node = await getNodeAtOffset(file, offset);
    return getElementOfNode(node);
  }

  /**
   * Return the [Element] of the given [node], or `null` if [node] is `null` or
   * does not have an element.
   */
  Element getElementOfNode(AstNode node) {
    if (node == null) {
      return null;
    }
    if (node is SimpleIdentifier && node.parent is LibraryIdentifier) {
      node = node.parent;
    }
    if (node is LibraryIdentifier) {
      node = node.parent;
    }
    if (node is StringLiteral && node.parent is UriBasedDirective) {
      return null;
    }
    Element element = ElementLocator.locate(node);
    if (node is SimpleIdentifier && element is PrefixElement) {
      element = getImportElement(node);
    }
    return element;
  }

  /**
   * Return an analysis error info containing the array of all of the errors and
   * the line info associated with [file].
   *
   * Returns `null` if [file] does not belong to any [AnalysisContext], or the
   * file does not exist.
   *
   * The array of errors will be empty if there are no errors in [file]. The
   * errors contained in the array can be incomplete.
   *
   * This method does not wait for all errors to be computed, and returns just
   * the current state.
   */
  AnalysisErrorInfo getErrors(String file) {
    ContextSourcePair contextSource = getContextSourcePair(file);
    AnalysisContext context = contextSource.context;
    Source source = contextSource.source;
    if (context == null) {
      return null;
    }
    if (!context.exists(source)) {
      return null;
    }
    return context.getErrors(source);
  }

  /**
   * Return a [Future] that completes with the resolved [AstNode] at the
   * given [offset] of the given [file], or with `null` if there is no node as
   * the [offset].
   */
  Future<AstNode> getNodeAtOffset(String file, int offset) async {
    CompilationUnit unit;
    if (options.enableNewAnalysisDriver) {
      nd.AnalysisResult result = await getAnalysisResult(file);
      unit = result?.unit;
    } else {
      unit = await getResolvedCompilationUnit(file);
    }
    if (unit != null) {
      return new NodeLocator(offset).searchWithin(unit);
    }
    return null;
  }

  /**
   * Return a [Future] that completes with the resolved [CompilationUnit] for
   * the Dart file with the given [path], or with `null` if the file is not a
   * Dart file or cannot be resolved.
   */
  Future<CompilationUnit> getResolvedCompilationUnit(String path) async {
    if (options.enableNewAnalysisDriver) {
      nd.AnalysisResult result = await getAnalysisResult(path);
      return result?.unit;
    }
    ContextSourcePair contextSource = getContextSourcePair(path);
    AnalysisContext context = contextSource.context;
    if (context == null) {
      return null;
    }
    return runWithActiveContext(context, () {
      Source unitSource = contextSource.source;
      List<Source> librarySources = context.getLibrariesContaining(unitSource);
      for (Source librarySource in librarySources) {
        return context.resolveCompilationUnit2(unitSource, librarySource);
      }
      return null;
    });
  }

// TODO(brianwilkerson) Add the following method after 'prioritySources' has
// been added to InternalAnalysisContext.
//  /**
//   * Return a list containing the full names of all of the sources that are
//   * priority sources.
//   */
//  List<String> getPriorityFiles() {
//    List<String> priorityFiles = new List<String>();
//    folderMap.values.forEach((ContextDirectory directory) {
//      InternalAnalysisContext context = directory.context;
//      context.prioritySources.forEach((Source source) {
//        priorityFiles.add(source.fullName);
//      });
//    });
//    return priorityFiles;
//  }

  /**
   * Handle a [request] that was read from the communication channel.
   */
  void handleRequest(Request request) {
    _performance.logRequest(request);
    runZoned(() {
      ServerPerformanceStatistics.serverRequests.makeCurrentWhile(() {
        int count = handlers.length;
        for (int i = 0; i < count; i++) {
          try {
            Response response = handlers[i].handleRequest(request);
            if (response == Response.DELAYED_RESPONSE) {
              return;
            }
            if (response != null) {
              channel.sendResponse(response);
              return;
            }
          } on RequestFailure catch (exception) {
            channel.sendResponse(exception.response);
            return;
          } catch (exception, stackTrace) {
            RequestError error = new RequestError(
                RequestErrorCode.SERVER_ERROR, exception.toString());
            if (stackTrace != null) {
              error.stackTrace = stackTrace.toString();
            }
            Response response = new Response(request.id, error: error);
            channel.sendResponse(response);
            return;
          }
        }
        channel.sendResponse(new Response.unknownRequest(request));
      });
    }, onError: (exception, stackTrace) {
      sendServerErrorNotification(
          'Failed to handle request: ${request.toJson()}',
          exception,
          stackTrace,
          fatal: true);
    });
  }

  /**
   * Returns `true` if there is a subscription for the given [service] and
   * [file].
   */
  bool hasAnalysisSubscription(AnalysisService service, String file) {
    Set<String> files = analysisServices[service];
    return files != null && files.contains(file);
  }

  /**
   * Return `true` if analysis is complete.
   */
  bool isAnalysisComplete() {
    return operationQueue.isEmpty && !analysisDriverScheduler.isAnalyzing;
  }

  /**
   * Return `true` if the given path is a valid `FilePath`.
   *
   * This means that it is absolute and normalized.
   */
  bool isValidFilePath(String path) {
    return resourceProvider.absolutePathContext.isValid(path);
  }

  /**
   * Returns a [Future] completing when [file] has been completely analyzed, in
   * particular, all its errors have been computed.  The future is completed
   * with an [AnalysisDoneReason] indicating what caused the file's analysis to
   * be considered complete.
   *
   * If the given file doesn't belong to any context, null is returned.
   *
   * TODO(scheglov) this method should be improved.
   *
   * 1. The analysis context should be told to analyze this particular file ASAP.
   *
   * 2. We should complete the future as soon as the file is analyzed (not wait
   *    until the context is completely finished)
   */
  Future<AnalysisDoneReason> onFileAnalysisComplete(String file) {
    // prepare AnalysisContext
    AnalysisContext context = getAnalysisContext(file);
    if (context == null) {
      return null;
    }
    // done if everything is already analyzed
    if (isAnalysisComplete()) {
      return new Future.value(AnalysisDoneReason.COMPLETE);
    }
    // schedule context analysis
    schedulePerformAnalysisOperation(context);
    // associate with the context completer
    Completer<AnalysisDoneReason> completer =
        contextAnalysisDoneCompleters[context];
    if (completer == null) {
      completer = new Completer<AnalysisDoneReason>();
      contextAnalysisDoneCompleters[context] = completer;
    }
    return completer.future;
  }

  /**
   * Perform the next available [ServerOperation].
   */
  void performOperation() {
    assert(performOperationPending);
    PerformanceTag.UNKNOWN.makeCurrent();
    performOperationPending = false;
    if (!running) {
      // An error has occurred, or the connection to the client has been
      // closed, since this method was scheduled on the event queue.  So
      // don't do anything.  Instead clear the operation queue.
      operationQueue.clear();
      return;
    }
    // prepare next operation
    ServerOperation operation = operationQueue.take();
    if (operation == null) {
      // This can happen if the operation queue is cleared while the operation
      // loop is in progress.  No problem; we just need to exit the operation
      // loop and wait for the next operation to be added.
      ServerPerformanceStatistics.idle.makeCurrent();
      return;
    }
    sendStatusNotification(operation);
    // perform the operation
    try {
      operation.perform(this);
    } catch (exception, stackTrace) {
      sendServerErrorNotification(
          'Failed to perform operation: $operation', exception, stackTrace,
          fatal: true);
      if (rethrowExceptions) {
        throw new AnalysisException('Unexpected exception during analysis',
            new CaughtException(exception, stackTrace));
      }
      shutdown();
    } finally {
      if (_test_onOperationPerformedCompleter != null) {
        _test_onOperationPerformedCompleter.complete(operation);
        _test_onOperationPerformedCompleter = null;
      }
      if (!operationQueue.isEmpty) {
        ServerPerformanceStatistics.intertask.makeCurrent();
        _schedulePerformOperation();
      } else {
        if (generalAnalysisServices
            .contains(GeneralAnalysisService.ANALYZED_FILES)) {
          sendAnalysisNotificationAnalyzedFiles(this);
        }
        sendStatusNotification(null);
        _scheduleAnalysisImplementedNotification();
        if (_onAnalysisCompleteCompleter != null) {
          _onAnalysisCompleteCompleter.complete();
          _onAnalysisCompleteCompleter = null;
        }
        ServerPerformanceStatistics.idle.makeCurrent();
      }
    }
  }

  /**
   * Trigger reanalysis of all files in the given list of analysis [roots], or
   * everything if the analysis roots is `null`.
   */
  void reanalyze(List<Resource> roots) {
    // Clear any operations that are pending.
    if (roots == null) {
      operationQueue.clear();
    } else {
      for (AnalysisContext context in _getContexts(roots)) {
        operationQueue.contextRemoved(context);
      }
    }
    // Instruct the contextDirectoryManager to rebuild all contexts from
    // scratch.
    contextManager.refresh(roots);
  }

  /**
   * Schedule cache consistency validation in [context].
   * The most of the validation must be done asynchronously.
   */
  void scheduleCacheConsistencyValidation(AnalysisContext context) {
    if (context is InternalAnalysisContext) {
      CacheConsistencyValidator validator = context.cacheConsistencyValidator;
      List<Source> sources = validator.getSourcesToComputeModificationTimes();
      // Compute modification times and notify the validator asynchronously.
      new Future(() async {
        try {
          List<int> modificationTimes =
              await resourceProvider.getModificationTimes(sources);
          bool cacheInconsistencyFixed = validator
              .sourceModificationTimesComputed(sources, modificationTimes);
          if (cacheInconsistencyFixed) {
            scheduleOperation(new PerformAnalysisOperation(context, false));
          }
        } catch (exception, stackTrace) {
          sendServerErrorNotification(
              'Failed to check cache consistency', exception, stackTrace);
        }
      });
    }
  }

  /**
   * Schedules execution of the given [ServerOperation].
   */
  void scheduleOperation(ServerOperation operation) {
    addOperation(operation);
    _schedulePerformOperation();
  }

  /**
   * Schedules analysis of the given context.
   */
  void schedulePerformAnalysisOperation(AnalysisContext context) {
    _onAnalysisStartedController.add(true);
    scheduleOperation(new PerformAnalysisOperation(context, false));
  }

  /**
   * This method is called when analysis of the given [AnalysisContext] is
   * done.
   */
  void sendContextAnalysisDoneNotifications(
      AnalysisContext context, AnalysisDoneReason reason) {
    Completer<AnalysisDoneReason> completer =
        contextAnalysisDoneCompleters.remove(context);
    if (completer != null) {
      completer.complete(reason);
    }
  }

  /**
   * Send the given [notification] to the client.
   */
  void sendNotification(Notification notification) {
    channel.sendNotification(notification);
  }

  /**
   * Send the given [response] to the client.
   */
  void sendResponse(Response response) {
    channel.sendResponse(response);
  }

  /**
   * Sends a `server.error` notification.
   */
  void sendServerErrorNotification(String message, exception, stackTrace,
      {bool fatal: false}) {
    StringBuffer buffer = new StringBuffer();
    if (exception != null) {
      buffer.write(exception);
    } else {
      buffer.write('null exception');
    }
    if (stackTrace != null) {
      buffer.writeln();
      buffer.write(stackTrace);
    } else if (exception is! CaughtException) {
      try {
        throw 'ignored';
      } catch (ignored, stackTrace) {
        buffer.writeln();
        buffer.write(stackTrace);
      }
    }
    // send the notification
    channel.sendNotification(
        new ServerErrorParams(fatal, message, buffer.toString())
            .toNotification());
  }

  /**
   * Send status notification to the client. The `operation` is the operation
   * being performed or `null` if analysis is complete.
   */
  void sendStatusNotification(ServerOperation operation) {
    // Only send status when subscribed.
    if (!serverServices.contains(ServerService.STATUS)) {
      return;
    }
    // Only send status when it changes
    bool isAnalyzing = operation != null;
    if (statusAnalyzing == isAnalyzing) {
      return;
    }
    statusAnalyzing = isAnalyzing;
    AnalysisStatus analysis = new AnalysisStatus(isAnalyzing);
    channel.sendNotification(
        new ServerStatusParams(analysis: analysis).toNotification());
  }

  /**
   * Send status notification to the client. The state of analysis is given by
   * the [status] information.
   */
  void sendStatusNotificationNew(nd.AnalysisStatus status) {
    if (status.isAnalyzing) {
      _onAnalysisStartedController.add(true);
    }
    if (_onAnalysisCompleteCompleter != null && !status.isAnalyzing) {
      _onAnalysisCompleteCompleter.complete();
      _onAnalysisCompleteCompleter = null;
    }
    // Perform on-idle actions.
    if (!status.isAnalyzing) {
      if (generalAnalysisServices
          .contains(GeneralAnalysisService.ANALYZED_FILES)) {
        sendAnalysisNotificationAnalyzedFiles(this);
      }
    }
    // Only send status when subscribed.
    if (!serverServices.contains(ServerService.STATUS)) {
      return;
    }
    // Only send status when it changes
    if (statusAnalyzing == status.isAnalyzing) {
      return;
    }
    statusAnalyzing = status.isAnalyzing;
    AnalysisStatus analysis = new AnalysisStatus(status.isAnalyzing);
    channel.sendNotification(
        new ServerStatusParams(analysis: analysis).toNotification());
  }

  /**
   * Implementation for `analysis.setAnalysisRoots`.
   *
   * TODO(scheglov) implement complete projects/contexts semantics.
   *
   * The current implementation is intentionally simplified and expected
   * that only folders are given each given folder corresponds to the exactly
   * one context.
   *
   * So, we can start working in parallel on adding services and improving
   * projects/contexts support.
   */
  void setAnalysisRoots(String requestId, List<String> includedPaths,
      List<String> excludedPaths, Map<String, String> packageRoots) {
    if (notificationManager != null) {
      notificationManager.setAnalysisRoots(includedPaths, excludedPaths);
    }
    try {
      contextManager.setRoots(includedPaths, excludedPaths, packageRoots);
    } on UnimplementedError catch (e) {
      throw new RequestFailure(
          new Response.unsupportedFeature(requestId, e.message));
    }
  }

  /**
   * Implementation for `analysis.setSubscriptions`.
   */
  void setAnalysisSubscriptions(
      Map<AnalysisService, Set<String>> subscriptions) {
    if (notificationManager != null) {
      notificationManager.setSubscriptions(subscriptions);
    }
    if (options.enableNewAnalysisDriver) {
      this.analysisServices = subscriptions;
      Set<String> allNewFiles =
          subscriptions.values.expand((files) => files).toSet();
      for (String file in allNewFiles) {
        // The result will be produced by the "results" stream with
        // the fully resolved unit, and processed with sending analysis
        // notifications as it happens after content changes.
        if (AnalysisEngine.isDartFileName(file)) {
          getAnalysisResult(file);
        }
      }
      return;
    }
    // send notifications for already analyzed sources
    subscriptions.forEach((service, Set<String> newFiles) {
      Set<String> oldFiles = analysisServices[service];
      Set<String> todoFiles =
          oldFiles != null ? newFiles.difference(oldFiles) : newFiles;
      for (String file in todoFiles) {
        if (contextManager.isIgnored(file)) {
          continue;
        }
        // prepare context
        ContextSourcePair contextSource = getContextSourcePair(file);
        AnalysisContext context = contextSource.context;
        if (context == null) {
          continue;
        }
        Source source = contextSource.source;
        // Ensure that if the AST is flushed / not ready, it will be
        // computed eventually.
        if (AnalysisEngine.isDartFileName(file)) {
          (context as InternalAnalysisContext).ensureResolvedDartUnits(source);
        }
        // Send notifications that don't directly take an AST.
        switch (service) {
          case AnalysisService.NAVIGATION:
            sendAnalysisNotificationNavigation(this, context, source);
            continue;
          case AnalysisService.OCCURRENCES:
            sendAnalysisNotificationOccurrences(this, context, source);
            continue;
        }
        // Dart unit notifications.
        if (AnalysisEngine.isDartFileName(file)) {
          // TODO(scheglov) This way to get resolved information is very Dart
          // specific. OTOH as it is planned now Angular results are not
          // flushable.
          CompilationUnit dartUnit =
              _getResolvedCompilationUnitToResendNotification(context, source);
          if (dartUnit != null) {
            switch (service) {
              case AnalysisService.HIGHLIGHTS:
                sendAnalysisNotificationHighlights(this, file, dartUnit);
                break;
              case AnalysisService.OUTLINE:
                AnalysisContext context = resolutionMap
                    .elementDeclaredByCompilationUnit(dartUnit)
                    .context;
                LineInfo lineInfo = context.getLineInfo(source);
                SourceKind kind = context.getKindOf(source);
                sendAnalysisNotificationOutline(
                    this, file, lineInfo, kind, dartUnit);
                break;
              case AnalysisService.OVERRIDES:
                sendAnalysisNotificationOverrides(this, file, dartUnit);
                break;
            }
          }
        }
      }
    });
    // remember new subscriptions
    this.analysisServices = subscriptions;
    // special case for implemented elements
    if (analysisServices.containsKey(AnalysisService.IMPLEMENTED) &&
        isAnalysisComplete()) {
      _scheduleAnalysisImplementedNotification();
    }
  }

  /**
   * Implementation for `analysis.setGeneralSubscriptions`.
   */
  void setGeneralAnalysisSubscriptions(
      List<GeneralAnalysisService> subscriptions) {
    Set<GeneralAnalysisService> newServices = subscriptions.toSet();
    if (newServices.contains(GeneralAnalysisService.ANALYZED_FILES) &&
        !generalAnalysisServices
            .contains(GeneralAnalysisService.ANALYZED_FILES) &&
        isAnalysisComplete()) {
      sendAnalysisNotificationAnalyzedFiles(this);
    } else if (!newServices.contains(GeneralAnalysisService.ANALYZED_FILES) &&
        generalAnalysisServices
            .contains(GeneralAnalysisService.ANALYZED_FILES)) {
      prevAnalyzedFiles = null;
    }
    generalAnalysisServices = newServices;
  }

  /**
   * Set the priority files to the given [files].
   */
  void setPriorityFiles(String requestId, List<String> files) {
    if (options.enableNewAnalysisDriver) {
      priorityFiles.clear();
      priorityFiles.addAll(files);
      // Set priority files in drivers.
      driverMap.values.forEach((driver) {
        driver.priorityFiles = files;
      });
      return;
    }
    // Note: when a file is a priority file, that information needs to be
    // propagated to all contexts that analyze the file, so that all contexts
    // will be able to do incremental resolution of the file.  See
    // dartbug.com/22209.
    Map<AnalysisContext, List<Source>> sourceMap =
        new HashMap<AnalysisContext, List<Source>>();
    List<String> unanalyzed = new List<String>();
    Source firstSource = null;
    files.forEach((String file) {
      if (contextManager.isIgnored(file)) {
        unanalyzed.add(file);
        return;
      }
      // Prepare the context/source pair.
      ContextSourcePair contextSource = getContextSourcePair(file);
      AnalysisContext preferredContext = contextSource.context;
      Source source = contextSource.source;
      // Try to make the file analyzable.
      // If it is not in any context yet, add it to the first one which
      // could use it, e.g. imports its package, even if not the library.
      if (preferredContext == null) {
        Resource resource = resourceProvider.getResource(file);
        if (resource is File && resource.exists) {
          for (AnalysisContext context in analysisContexts) {
            Uri uri = context.sourceFactory.restoreUri(source);
            if (uri.scheme != 'file') {
              preferredContext = context;
              source =
                  ContextManagerImpl.createSourceInContext(context, resource);
              break;
            }
          }
        }
      }
      // Fill the source map.
      bool contextFound = false;
      if (preferredContext != null) {
        sourceMap.putIfAbsent(preferredContext, () => <Source>[]).add(source);
        contextFound = true;
      }
      for (AnalysisContext context in analysisContexts) {
        if (context != preferredContext &&
            context.getKindOf(source) != SourceKind.UNKNOWN) {
          sourceMap.putIfAbsent(context, () => <Source>[]).add(source);
          contextFound = true;
        }
      }
      if (firstSource == null) {
        firstSource = source;
      }
      if (!contextFound) {
        unanalyzed.add(file);
      }
    });
    if (unanalyzed.isNotEmpty) {
      StringBuffer buffer = new StringBuffer();
      buffer.writeAll(unanalyzed, ', ');
      throw new RequestFailure(
          new Response.unanalyzedPriorityFiles(requestId, buffer.toString()));
    }
    sourceMap.forEach((context, List<Source> sourceList) {
      context.analysisPriorityOrder = sourceList;
      // Schedule the context for analysis so that it has the opportunity to
      // cache the AST's for the priority sources as soon as possible.
      schedulePerformAnalysisOperation(context);
    });
    operationQueue.reschedule();
    _onPriorityChangeController.add(new PriorityChangeEvent(firstSource));
  }

  /**
   * Returns `true` if errors should be reported for [file] with the given
   * absolute path.
   */
  bool shouldSendErrorsNotificationFor(String file) {
    return contextManager.isInAnalysisRoot(file);
  }

  void shutdown() {
    running = false;
    if (index != null) {
      index.stop();
    }
    // Defer closing the channel and shutting down the instrumentation server so
    // that the shutdown response can be sent and logged.
    new Future(() {
      instrumentationService.shutdown();
      channel.close();
    });
  }

  void test_flushAstStructures(String file) {
    if (AnalysisEngine.isDartFileName(file)) {
      ContextSourcePair contextSource = getContextSourcePair(file);
      InternalAnalysisContext context = contextSource.context;
      Source source = contextSource.source;
      context.test_flushAstStructures(source);
    }
  }

  /**
   * Performs all scheduled analysis operations.
   */
  void test_performAllAnalysisOperations() {
    while (true) {
      ServerOperation operation = operationQueue.takeIf((operation) {
        return operation is PerformAnalysisOperation;
      });
      if (operation == null) {
        break;
      }
      operation.perform(this);
    }
  }

  /**
   * Implementation for `analysis.updateContent`.
   */
  void updateContent(String id, Map<String, dynamic> changes) {
    if (options.enableNewAnalysisDriver) {
      changes.forEach((file, change) {
        // Prepare the new contents.
        String oldContents = fileContentOverlay[file];
        String newContents;
        if (change is AddContentOverlay) {
          newContents = change.content;
        } else if (change is ChangeContentOverlay) {
          if (oldContents == null) {
            // The client may only send a ChangeContentOverlay if there is
            // already an existing overlay for the source.
            throw new RequestFailure(new Response(id,
                error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE,
                    'Invalid overlay change')));
          }
          try {
            newContents = SourceEdit.applySequence(oldContents, change.edits);
          } on RangeError {
            throw new RequestFailure(new Response(id,
                error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE,
                    'Invalid overlay change')));
          }
        } else if (change is RemoveContentOverlay) {
          newContents = null;
        } else {
          // Protocol parsing should have ensured that we never get here.
          throw new AnalysisException('Illegal change type');
        }

        fileContentOverlay[file] = newContents;

        driverMap.values.forEach((driver) {
          driver.changeFile(file);
        });

        // temporary plugin support:
        _onFileChangedController.add(file);

        // If the file did not exist, and is "overlay only", it still should be
        // analyzed. Add it to driver to which it should have been added.
        contextManager.getDriverFor(file)?.addFile(file);

        // TODO(scheglov) implement other cases
      });
      return;
    }
    changes.forEach((file, change) {
      ContextSourcePair contextSource = getContextSourcePair(file);
      Source source = contextSource.source;
      operationQueue.sourceAboutToChange(source);
      // Prepare the new contents.
      String oldContents = overlayState.getContents(source);
      String newContents;
      if (change is AddContentOverlay) {
        newContents = change.content;
      } else if (change is ChangeContentOverlay) {
        if (oldContents == null) {
          // The client may only send a ChangeContentOverlay if there is
          // already an existing overlay for the source.
          throw new RequestFailure(new Response(id,
              error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE,
                  'Invalid overlay change')));
        }
        try {
          newContents = SourceEdit.applySequence(oldContents, change.edits);
        } on RangeError {
          throw new RequestFailure(new Response(id,
              error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE,
                  'Invalid overlay change')));
        }
      } else if (change is RemoveContentOverlay) {
        newContents = null;
      } else {
        // Protocol parsing should have ensured that we never get here.
        throw new AnalysisException('Illegal change type');
      }

      AnalysisContext containingContext = getContainingContext(file);

      // Check for an implicitly added but missing source.
      // (For example, the target of an import might not exist yet.)
      // We need to do this before setContents, which changes the stamp.
      bool wasMissing = containingContext?.getModificationStamp(source) == -1;

      overlayState.setContents(source, newContents);
      // If the source does not exist, then it was an overlay-only one.
      // Remove it from contexts.
      if (newContents == null && !source.exists()) {
        for (InternalAnalysisContext context in analysisContexts) {
          List<Source> sources = context.getSourcesWithFullName(file);
          ChangeSet changeSet = new ChangeSet();
          sources.forEach(changeSet.removedSource);
          context.applyChanges(changeSet);
          schedulePerformAnalysisOperation(context);
        }
        return;
      }
      // Update all contexts.
      bool anyContextUpdated = false;
      for (InternalAnalysisContext context in analysisContexts) {
        List<Source> sources = context.getSourcesWithFullName(file);
        sources.forEach((Source source) {
          anyContextUpdated = true;
          if (context == containingContext && wasMissing) {
            // Promote missing source to an explicitly added Source.
            context.applyChanges(new ChangeSet()..addedSource(source));
            schedulePerformAnalysisOperation(context);
          }
          if (context.handleContentsChanged(
              source, oldContents, newContents, true)) {
            schedulePerformAnalysisOperation(context);
          } else {
            // When the client sends any change for a source, we should resend
            // subscribed notifications, even if there were no changes in the
            // source contents.
            // TODO(scheglov) consider checking if there are subscriptions.
            if (AnalysisEngine.isDartFileName(file)) {
              List<CompilationUnit> dartUnits =
                  context.ensureResolvedDartUnits(source);
              if (dartUnits != null) {
                AnalysisErrorInfo errorInfo = context.getErrors(source);
                for (var dartUnit in dartUnits) {
                  scheduleNotificationOperations(
                      this,
                      source,
                      file,
                      errorInfo.lineInfo,
                      context,
                      null,
                      dartUnit,
                      errorInfo.errors);
                  scheduleIndexOperation(this, file, dartUnit);
                }
              } else {
                schedulePerformAnalysisOperation(context);
              }
            }
          }
        });
      }
      // The source is not analyzed by any context, add to the containing one.
      if (!anyContextUpdated) {
        AnalysisContext context = contextSource.context;
        if (context != null && source != null) {
          ChangeSet changeSet = new ChangeSet();
          changeSet.addedSource(source);
          context.applyChanges(changeSet);
          schedulePerformAnalysisOperation(context);
        }
      }
    });
  }

  /**
   * Use the given updaters to update the values of the options in every
   * existing analysis context.
   */
  void updateOptions(List<OptionUpdater> optionUpdaters) {
    if (options.enableNewAnalysisDriver) {
      // TODO(scheglov) implement for the new analysis driver
      return;
    }
    //
    // Update existing contexts.
    //
    for (AnalysisContext context in analysisContexts) {
      AnalysisOptionsImpl options =
          new AnalysisOptionsImpl.from(context.analysisOptions);
      optionUpdaters.forEach((OptionUpdater optionUpdater) {
        optionUpdater(options);
      });
      context.analysisOptions = options;
      // TODO(brianwilkerson) As far as I can tell, this doesn't cause analysis
      // to be scheduled for this context.
    }
    //
    // Update the defaults used to create new contexts.
    //
    optionUpdaters.forEach((OptionUpdater optionUpdater) {
      optionUpdater(defaultContextOptions);
    });
  }

  void _computingPackageMap(bool computing) {
    if (serverServices.contains(ServerService.STATUS)) {
      PubStatus pubStatus = new PubStatus(computing);
      ServerStatusParams params = new ServerStatusParams(pub: pubStatus);
      sendNotification(params.toNotification());
    }
  }

  /**
   * If the state location can be accessed, return the file byte store,
   * otherwise return the memory byte store.
   */
  ByteStore _createByteStore() {
    const int M = 1024 * 1024 /*1 MiB*/;
    const int G = 1024 * 1024 * 1024 /*1 GiB*/;
    if (resourceProvider is PhysicalResourceProvider) {
      Folder stateLocation =
          resourceProvider.getStateLocation('.analysis-driver');
      if (stateLocation != null) {
        return new MemoryCachingByteStore(
            new EvictingFileByteStore(stateLocation.path, G), 64 * M);
      }
    }
    return new MemoryCachingByteStore(new NullByteStore(), 64 * M);
  }

  /**
   * Return a set of all contexts whose associated folder is contained within,
   * or equal to, one of the resources in the given list of [resources].
   */
  Set<AnalysisContext> _getContexts(List<Resource> resources) {
    Set<AnalysisContext> contexts = new HashSet<AnalysisContext>();
    resources.forEach((Resource resource) {
      if (resource is Folder) {
        contexts.addAll(contextManager.contextsInAnalysisRoot(resource));
      }
    });
    return contexts;
  }

  /**
   * Returns the [CompilationUnit] of the Dart file with the given [source] that
   * should be used to resend notifications for already resolved unit.
   * Returns `null` if the file is not a part of any context, library has not
   * been yet resolved, or any problem happened.
   */
  CompilationUnit _getResolvedCompilationUnitToResendNotification(
      AnalysisContext context, Source source) {
    List<Source> librarySources = context.getLibrariesContaining(source);
    if (librarySources.isEmpty) {
      return null;
    }
    // if library has not been resolved yet, the unit will be resolved later
    Source librarySource = librarySources[0];
    if (context.getResult(librarySource, LIBRARY_ELEMENT6) == null) {
      return null;
    }
    // if library has been already resolved, resolve unit
    return runWithActiveContext(context, () {
      return context.resolveCompilationUnit2(source, librarySource);
    });
  }

  bool _hasAnalysisServiceSubscription(AnalysisService service, String file) {
    return analysisServices[service]?.contains(file) ?? false;
  }

  _scheduleAnalysisImplementedNotification() async {
    Set<String> files = analysisServices[AnalysisService.IMPLEMENTED];
    if (files != null) {
      scheduleImplementedNotification(this, files);
    }
  }

  /**
   * Schedules [performOperation] execution.
   */
  void _schedulePerformOperation() {
    if (performOperationPending) {
      return;
    }
    /*
     * TODO (danrubel) Rip out this workaround once the underlying problem
     * is fixed. Currently, the VM and dart:io do not deliver content
     * on stdin in a timely manner if the event loop is busy.
     * To work around this problem, we delay for 1 millisecond
     * every 25 milliseconds.
     *
     * To disable this workaround and see the underlying problem,
     * set performOperationDelayFrequency to zero
     */
    int now = new DateTime.now().millisecondsSinceEpoch;
    if (now > _nextPerformOperationDelayTime &&
        performOperationDelayFrequency > 0) {
      _nextPerformOperationDelayTime = now + performOperationDelayFrequency;
      new Future.delayed(new Duration(milliseconds: 1), performOperation);
    } else {
      new Future(performOperation);
    }
    performOperationPending = true;
  }

  /**
   * Listen for context events and invalidate index.
   *
   * It is possible that this method will do more in the future, e.g. listening
   * for summary information and linking pre-indexed packages into the index,
   * but for now we only invalidate project specific index information.
   */
  void _setupIndexInvalidation() {
    if (index == null) {
      return;
    }
    onContextsChanged.listen((ContextsChangedEvent event) {
      for (AnalysisContext context in event.added) {
        context
            .onResultChanged(RESOLVED_UNIT3)
            .listen((ResultChangedEvent event) {
          if (event.wasComputed) {
            Object value = event.value;
            if (value is CompilationUnit) {
              index.indexDeclarations(value);
            }
          }
        });
        context
            .onResultChanged(RESOLVED_UNIT)
            .listen((ResultChangedEvent event) {
          if (event.wasInvalidated) {
            LibrarySpecificUnit target = event.target;
            index.removeUnit(event.context, target.library, target.unit);
          }
        });
      }
      for (AnalysisContext context in event.removed) {
        index.removeContext(context);
      }
    });
  }
}

class AnalysisServerOptions {
  bool enableIncrementalResolutionApi = false;
  bool enableIncrementalResolutionValidation = false;
  bool enableNewAnalysisDriver = false;
  bool finerGrainedInvalidation = false;
  bool noIndex = false;
  bool useAnalysisHighlight2 = false;
  String fileReadMode = 'as-is';
  String newAnalysisDriverLog;
}

/**
 * Information about a file - an [AnalysisContext] that analyses the file,
 * and the [Source] representing the file in this context.
 */
class ContextSourcePair {
  /**
   * A context that analysis the file.
   * May be `null` if the file is not analyzed by any context.
   */
  final AnalysisContext context;

  /**
   * The source that corresponds to the file.
   * May be `null` if the file is not a regular file.
   * If the file cannot be found in the [context], then it has a `file` uri.
   */
  final Source source;

  ContextSourcePair(this.context, this.source);
}

/**
 * A [PriorityChangeEvent] indicates the set the priority files has changed.
 */
class PriorityChangeEvent {
  final Source firstSource;

  PriorityChangeEvent(this.firstSource);
}

class ServerContextManagerCallbacks extends ContextManagerCallbacks {
  final AnalysisServer analysisServer;

  /**
   * The [ResourceProvider] by which paths are converted into [Resource]s.
   */
  final ResourceProvider resourceProvider;

  ServerContextManagerCallbacks(this.analysisServer, this.resourceProvider);

  @override
  nd.AnalysisDriver addAnalysisDriver(Folder folder, AnalysisOptions options) {
    ContextBuilder builder = createContextBuilder(folder, options);
    nd.AnalysisDriver analysisDriver = builder.buildDriver(folder.path);
    analysisDriver.results.listen((result) {
      NotificationManager notificationManager =
          analysisServer.notificationManager;
      String path = result.path;
      if (analysisServer.shouldSendErrorsNotificationFor(path)) {
        if (notificationManager != null) {
          notificationManager.recordAnalysisErrors(
              NotificationManager.serverId,
              path,
              server.doAnalysisError_listFromEngine(
                  result.driver.analysisOptions,
                  result.lineInfo,
                  result.errors));
        } else {
          new_sendErrorNotification(analysisServer, result);
        }
      }
      CompilationUnit unit = result.unit;
      if (unit != null) {
        if (notificationManager != null) {
          if (analysisServer._hasAnalysisServiceSubscription(
              AnalysisService.HIGHLIGHTS, path)) {
            _runDelayed(() {
              notificationManager.recordHighlightRegions(
                  NotificationManager.serverId,
                  path,
                  _computeHighlightRegions(unit));
            });
          }
          if (analysisServer._hasAnalysisServiceSubscription(
              AnalysisService.NAVIGATION, path)) {
            _runDelayed(() {
              notificationManager.recordNavigationParams(
                  NotificationManager.serverId,
                  path,
                  _computeNavigationParams(path, unit));
            });
          }
          if (analysisServer._hasAnalysisServiceSubscription(
              AnalysisService.OCCURRENCES, path)) {
            _runDelayed(() {
              notificationManager.recordOccurrences(
                  NotificationManager.serverId,
                  path,
                  _computeOccurrences(unit));
            });
          }
//          if (analysisServer._hasAnalysisServiceSubscription(
//              AnalysisService.OUTLINE, path)) {
//            _runDelayed(() {
//              // TODO(brianwilkerson) Change NotificationManager to store params
//              // so that fileKind and libraryName can be recorded / passed along.
//              notificationManager.recordOutlines(NotificationManager.serverId,
//                  path, _computeOutlineParams(path, unit, result.lineInfo));
//            });
//          }
        } else {
          if (analysisServer._hasAnalysisServiceSubscription(
              AnalysisService.HIGHLIGHTS, path)) {
            _runDelayed(() {
              sendAnalysisNotificationHighlights(analysisServer, path, unit);
            });
          }
          if (analysisServer._hasAnalysisServiceSubscription(
              AnalysisService.NAVIGATION, path)) {
            _runDelayed(() {
              new_sendDartNotificationNavigation(analysisServer, result);
            });
          }
          if (analysisServer._hasAnalysisServiceSubscription(
              AnalysisService.OCCURRENCES, path)) {
            _runDelayed(() {
              new_sendDartNotificationOccurrences(analysisServer, result);
            });
          }
        }
        if (analysisServer._hasAnalysisServiceSubscription(
            AnalysisService.OUTLINE, path)) {
          _runDelayed(() {
            SourceKind sourceKind =
                unit.directives.any((d) => d is PartOfDirective)
                    ? SourceKind.PART
                    : SourceKind.LIBRARY;
            sendAnalysisNotificationOutline(
                analysisServer, path, result.lineInfo, sourceKind, unit);
          });
        }
        if (analysisServer._hasAnalysisServiceSubscription(
            AnalysisService.OVERRIDES, path)) {
          _runDelayed(() {
            sendAnalysisNotificationOverrides(analysisServer, path, unit);
          });
        }
        // TODO(scheglov) Implement notifications for AnalysisService.IMPLEMENTED.
      }
    });
    analysisDriver.exceptions.listen((nd.ExceptionResult result) {
      String message = 'Analysis failed: ${result.path}';
      if (result.contextKey != null) {
        message += ' context: ${result.contextKey}';
      }
      AnalysisEngine.instance.logger.logError(message, result.exception);
    });
    analysisServer.driverMap[folder] = analysisDriver;
    return analysisDriver;
  }

  @override
  AnalysisContext addContext(Folder folder, AnalysisOptions options) {
    ContextBuilder builder = createContextBuilder(folder, options);
    AnalysisContext context = builder.buildContext(folder.path);

    analysisServer.folderMap[folder] = context;
    analysisServer._onContextsChangedController
        .add(new ContextsChangedEvent(added: [context]));
    analysisServer.schedulePerformAnalysisOperation(context);

    return context;
  }

  @override
  void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
    if (analysisServer.options.enableNewAnalysisDriver) {
      nd.AnalysisDriver analysisDriver =
          analysisServer.driverMap[contextFolder];
      if (analysisDriver != null) {
        changeSet.addedSources.forEach((source) {
          analysisDriver.addFile(source.fullName);
          // temporary plugin support:
          analysisServer._onFileAddedController.add(source.fullName);
        });
        changeSet.changedSources.forEach((source) {
          analysisDriver.changeFile(source.fullName);
          // temporary plugin support:
          analysisServer._onFileChangedController.add(source.fullName);
        });
        changeSet.removedSources.forEach((source) {
          analysisDriver.removeFile(source.fullName);
        });
      }
    } else {
      AnalysisContext context = analysisServer.folderMap[contextFolder];
      if (context != null) {
        context.applyChanges(changeSet);
        analysisServer.schedulePerformAnalysisOperation(context);
        List<String> flushedFiles = new List<String>();
        for (Source source in changeSet.removedSources) {
          flushedFiles.add(source.fullName);
        }
        sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
      }
    }
  }

  @override
  void applyFileRemoved(nd.AnalysisDriver driver, String file) {
    driver.removeFile(file);
    sendAnalysisNotificationFlushResults(analysisServer, [file]);
  }

  @override
  void computingPackageMap(bool computing) =>
      analysisServer._computingPackageMap(computing);

  @override
  ContextBuilder createContextBuilder(Folder folder, AnalysisOptions options) {
    String defaultPackageFilePath = null;
    String defaultPackagesDirectoryPath = null;
    String path = (analysisServer.contextManager as ContextManagerImpl)
        .normalizedPackageRoots[folder.path];
    if (path != null) {
      Resource resource = resourceProvider.getResource(path);
      if (resource.exists) {
        if (resource is File) {
          defaultPackageFilePath = path;
        } else {
          defaultPackagesDirectoryPath = path;
        }
      }
    }

    ContextBuilderOptions builderOptions = new ContextBuilderOptions();
    builderOptions.defaultOptions = options;
    builderOptions.defaultPackageFilePath = defaultPackageFilePath;
    builderOptions.defaultPackagesDirectoryPath = defaultPackagesDirectoryPath;
    ContextBuilder builder = new ContextBuilder(resourceProvider,
        analysisServer.sdkManager, analysisServer.overlayState,
        options: builderOptions);
    builder.fileResolverProvider = analysisServer.fileResolverProvider;
    builder.packageResolverProvider = analysisServer.packageResolverProvider;
    builder.analysisDriverScheduler = analysisServer.analysisDriverScheduler;
    builder.performanceLog = analysisServer._analysisPerformanceLogger;
    builder.byteStore = analysisServer.byteStore;
    builder.fileContentOverlay = analysisServer.fileContentOverlay;
    return builder;
  }

  @override
  void moveContext(Folder from, Folder to) {
    // There is nothing to do.
    // This method is mostly for tests.
    // Context managers manage folders and contexts themselves.
  }

  @override
  void removeContext(Folder folder, List<String> flushedFiles) {
    if (analysisServer.options.enableNewAnalysisDriver) {
      sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
      nd.AnalysisDriver driver = analysisServer.driverMap.remove(folder);
      driver.dispose();
    } else {
      AnalysisContext context = analysisServer.folderMap.remove(folder);
      sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);

      analysisServer.operationQueue.contextRemoved(context);
      analysisServer._onContextsChangedController
          .add(new ContextsChangedEvent(removed: [context]));
      analysisServer.sendContextAnalysisDoneNotifications(
          context, AnalysisDoneReason.CONTEXT_REMOVED);
      context.dispose();
    }
  }

  @override
  void updateContextPackageUriResolver(AnalysisContext context) {
    analysisServer._onContextsChangedController
        .add(new ContextsChangedEvent(changed: [context]));
    analysisServer.schedulePerformAnalysisOperation(context);
  }

  List<server.HighlightRegion> _computeHighlightRegions(CompilationUnit unit) {
    if (analysisServer.options.useAnalysisHighlight2) {
      return new DartUnitHighlightsComputer2(unit).compute();
    } else {
      return new DartUnitHighlightsComputer(unit).compute();
    }
  }

  String _computeLibraryName(CompilationUnit unit) {
    for (Directive directive in unit.directives) {
      if (directive is LibraryDirective && directive.name != null) {
        return directive.name.name;
      }
    }
    for (Directive directive in unit.directives) {
      if (directive is PartOfDirective && directive.libraryName != null) {
        return directive.libraryName.name;
      }
    }
    return null;
  }

  server.AnalysisNavigationParams _computeNavigationParams(
      String path, CompilationUnit unit) {
    NavigationCollectorImpl collector = new NavigationCollectorImpl();
    computeDartNavigation(collector, unit, null, null);
    collector.createRegions();
    return new server.AnalysisNavigationParams(
        path, collector.regions, collector.targets, collector.files);
  }

  List<Occurrences> _computeOccurrences(CompilationUnit unit) {
    OccurrencesCollectorImpl collector = new OccurrencesCollectorImpl();
    addDartOccurrences(collector, unit);
    return collector.allOccurrences;
  }

  server.AnalysisOutlineParams _computeOutlineParams(
      String path, CompilationUnit unit, LineInfo lineInfo) {
    // compute FileKind
    SourceKind sourceKind = unit.directives.any((d) => d is PartOfDirective)
        ? SourceKind.PART
        : SourceKind.LIBRARY;
    server.FileKind fileKind = server.FileKind.LIBRARY;
    if (sourceKind == SourceKind.LIBRARY) {
      fileKind = server.FileKind.LIBRARY;
    } else if (sourceKind == SourceKind.PART) {
      fileKind = server.FileKind.PART;
    }
    // compute library name
    String libraryName = _computeLibraryName(unit);
    // compute Outline
    DartUnitOutlineComputer computer =
        new DartUnitOutlineComputer(path, lineInfo, unit);
    server.Outline outline = computer.compute();
    return new server.AnalysisOutlineParams(path, fileKind, outline,
        libraryName: libraryName);
  }

  /**
   * Run [f] in a new [Future].
   *
   * This method is used to delay sending notifications. If there is a more
   * important consumer of an analysis results, specifically a code completion
   * computer, we want it to run before spending time of sending notifications.
   *
   * TODO(scheglov) Consider replacing this with full priority based scheduler.
   *
   * TODO(scheglov) Alternatively, if code completion work in a way that does
   * not produce (at first) fully resolved unit, but only part of it - a single
   * method, or a top-level declaration, we would not have this problem - the
   * completion computer would be the only consumer of the partial analysis
   * result.
   */
  void _runDelayed(f()) {
    new Future(f);
  }
}

/**
 * A class used by [AnalysisServer] to record performance information
 * such as request latency.
 */
class ServerPerformance {
  /**
   * The creation time and the time when performance information
   * started to be recorded here.
   */
  int startTime = new DateTime.now().millisecondsSinceEpoch;

  /**
   * The number of requests.
   */
  int requestCount = 0;

  /**
   * The total latency (milliseconds) for all recorded requests.
   */
  int requestLatency = 0;

  /**
   * The maximum latency (milliseconds) for all recorded requests.
   */
  int maxLatency = 0;

  /**
   * The number of requests with latency > 150 milliseconds.
   */
  int slowRequestCount = 0;

  /**
   * Log performance information about the given request.
   */
  void logRequest(Request request) {
    ++requestCount;
    if (request.clientRequestTime != null) {
      int latency =
          new DateTime.now().millisecondsSinceEpoch - request.clientRequestTime;
      requestLatency += latency;
      maxLatency = max(maxLatency, latency);
      if (latency > 150) {
        ++slowRequestCount;
      }
    }
  }
}

/**
 * Container with global [AnalysisServer] performance statistics.
 */
class ServerPerformanceStatistics {
  /**
   * The [PerformanceTag] for time spent in [ExecutionDomainHandler].
   */
  static PerformanceTag executionNotifications =
      new PerformanceTag('executionNotifications');

  /**
   * The [PerformanceTag] for time spent performing a _DartIndexOperation.
   */
  static PerformanceTag indexOperation = new PerformanceTag('indexOperation');

  /**
   * The [PerformanceTag] for time spent between calls to
   * AnalysisServer.performOperation when the server is not idle.
   */
  static PerformanceTag intertask = new PerformanceTag('intertask');

  /**
   * The [PerformanceTag] for time spent between calls to
   * AnalysisServer.performOperation when the server is idle.
   */
  static PerformanceTag idle = new PerformanceTag('idle');

  /**
   * The [PerformanceTag] for time spent in
   * PerformAnalysisOperation._sendNotices.
   */
  static PerformanceTag notices = new PerformanceTag('notices');

  /**
   * The [PerformanceTag] for time spent running pub.
   */
  static PerformanceTag pub = new PerformanceTag('pub');

  /**
   * The [PerformanceTag] for time spent in server communication channels.
   */
  static PerformanceTag serverChannel = new PerformanceTag('serverChannel');

  /**
   * The [PerformanceTag] for time spent in server request handlers.
   */
  static PerformanceTag serverRequests = new PerformanceTag('serverRequests');

  /**
   * The [PerformanceTag] for time spent in split store microtasks.
   */
  static PerformanceTag splitStore = new PerformanceTag('splitStore');
}
