// 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.
//
// This file has been automatically generated. Please do not edit it manually.
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".

/**
 * Convenience methods for running integration tests
 */
import 'dart:async';

import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart';
import 'package:test/test.dart';

import 'integration_tests.dart';
import 'protocol_matchers.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';

/**
 * Convenience methods for running integration tests
 */
abstract class IntegrationTestMixin {
  Server get server;

  /**
   * Return the version number of the analysis server.
   *
   * Returns
   *
   * version: String
   *
   *   The version number of the analysis server.
   */
  Future<ServerGetVersionResult> sendServerGetVersion() async {
    var result = await server.send("server.getVersion", null);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new ServerGetVersionResult.fromJson(decoder, 'result', result);
  }

  /**
   * Cleanly shutdown the analysis server. Requests that are received after
   * this request will not be processed. Requests that were received before
   * this request, but for which a response has not yet been sent, will not be
   * responded to. No further responses or notifications will be sent after the
   * response to this request has been sent.
   */
  Future sendServerShutdown() async {
    var result = await server.send("server.shutdown", null);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Subscribe for services. All previous subscriptions are replaced by the
   * given set of services.
   *
   * It is an error if any of the elements in the list are not valid services.
   * If there is an error, then the current subscriptions will remain
   * unchanged.
   *
   * Parameters
   *
   * subscriptions: List<ServerService>
   *
   *   A list of the services being subscribed to.
   */
  Future sendServerSetSubscriptions(List<ServerService> subscriptions) async {
    var params = new ServerSetSubscriptionsParams(subscriptions).toJson();
    var result = await server.send("server.setSubscriptions", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Reports that the server is running. This notification is issued once after
   * the server has started running but before any requests are processed to
   * let the client know that it started correctly.
   *
   * It is not possible to subscribe to or unsubscribe from this notification.
   *
   * Parameters
   *
   * version: String
   *
   *   The version number of the analysis server.
   *
   * pid: int
   *
   *   The process id of the analysis server process.
   *
   * sessionId: String (optional)
   *
   *   The session id for this session.
   */
  Stream<ServerConnectedParams> onServerConnected;

  /**
   * Stream controller for [onServerConnected].
   */
  StreamController<ServerConnectedParams> _onServerConnected;

  /**
   * Reports that an unexpected error has occurred while executing the server.
   * This notification is not used for problems with specific requests (which
   * are returned as part of the response) but is used for exceptions that
   * occur while performing other tasks, such as analysis or preparing
   * notifications.
   *
   * It is not possible to subscribe to or unsubscribe from this notification.
   *
   * Parameters
   *
   * isFatal: bool
   *
   *   True if the error is a fatal error, meaning that the server will
   *   shutdown automatically after sending this notification.
   *
   * message: String
   *
   *   The error message indicating what kind of error was encountered.
   *
   * stackTrace: String
   *
   *   The stack trace associated with the generation of the error, used for
   *   debugging the server.
   */
  Stream<ServerErrorParams> onServerError;

  /**
   * Stream controller for [onServerError].
   */
  StreamController<ServerErrorParams> _onServerError;

  /**
   * Reports the current status of the server. Parameters are omitted if there
   * has been no change in the status represented by that parameter.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "STATUS" in the list of services passed in a
   * server.setSubscriptions request.
   *
   * Parameters
   *
   * analysis: AnalysisStatus (optional)
   *
   *   The current status of analysis, including whether analysis is being
   *   performed and if so what is being analyzed.
   *
   * pub: PubStatus (optional)
   *
   *   The current status of pub execution, indicating whether we are currently
   *   running pub.
   *
   *   Note: this status type is deprecated, and is no longer sent by the
   *   server.
   */
  Stream<ServerStatusParams> onServerStatus;

  /**
   * Stream controller for [onServerStatus].
   */
  StreamController<ServerStatusParams> _onServerStatus;

  /**
   * Return the errors associated with the given file. If the errors for the
   * given file have not yet been computed, or the most recently computed
   * errors for the given file are out of date, then the response for this
   * request will be delayed until they have been computed. If some or all of
   * the errors for the file cannot be computed, then the subset of the errors
   * that can be computed will be returned and the response will contain an
   * error to indicate why the errors could not be computed. If the content of
   * the file changes after this request was received but before a response
   * could be sent, then an error of type CONTENT_MODIFIED will be generated.
   *
   * This request is intended to be used by clients that cannot asynchronously
   * apply updated error information. Clients that can apply error information
   * as it becomes available should use the information provided by the
   * 'analysis.errors' notification.
   *
   * If a request is made for a file which does not exist, or which is not
   * currently subject to analysis (e.g. because it is not associated with any
   * analysis root specified to analysis.setAnalysisRoots), an error of type
   * GET_ERRORS_INVALID_FILE will be generated.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file for which errors are being requested.
   *
   * Returns
   *
   * errors: List<AnalysisError>
   *
   *   The errors associated with the file.
   */
  Future<AnalysisGetErrorsResult> sendAnalysisGetErrors(String file) async {
    var params = new AnalysisGetErrorsParams(file).toJson();
    var result = await server.send("analysis.getErrors", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new AnalysisGetErrorsResult.fromJson(decoder, 'result', result);
  }

  /**
   * Return the hover information associate with the given location. If some or
   * all of the hover information is not available at the time this request is
   * processed the information will be omitted from the response.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file in which hover information is being requested.
   *
   * offset: int
   *
   *   The offset for which hover information is being requested.
   *
   * Returns
   *
   * hovers: List<HoverInformation>
   *
   *   The hover information associated with the location. The list will be
   *   empty if no information could be determined for the location. The list
   *   can contain multiple items if the file is being analyzed in multiple
   *   contexts in conflicting ways (such as a part that is included in
   *   multiple libraries).
   */
  Future<AnalysisGetHoverResult> sendAnalysisGetHover(
      String file, int offset) async {
    var params = new AnalysisGetHoverParams(file, offset).toJson();
    var result = await server.send("analysis.getHover", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new AnalysisGetHoverResult.fromJson(decoder, 'result', result);
  }

  /**
   * Return a description of all of the elements referenced in a given region
   * of a given file that come from imported libraries.
   *
   * If a request is made for a file that does not exist, or that is not
   * currently subject to analysis (e.g. because it is not associated with any
   * analysis root specified via analysis.setAnalysisRoots), an error of type
   * GET_IMPORTED_ELEMENTS_INVALID_FILE will be generated.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file in which import information is being requested.
   *
   * offset: int
   *
   *   The offset of the region for which import information is being
   *   requested.
   *
   * length: int
   *
   *   The length of the region for which import information is being
   *   requested.
   *
   * Returns
   *
   * elements: List<ImportedElements>
   *
   *   The information about the elements that are referenced in the specified
   *   region of the specified file that come from imported libraries.
   */
  Future<AnalysisGetImportedElementsResult> sendAnalysisGetImportedElements(
      String file, int offset, int length) async {
    var params =
        new AnalysisGetImportedElementsParams(file, offset, length).toJson();
    var result = await server.send("analysis.getImportedElements", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new AnalysisGetImportedElementsResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Return library dependency information for use in client-side indexing and
   * package URI resolution.
   *
   * Clients that are only using the libraries field should consider using the
   * analyzedFiles notification instead.
   *
   * Returns
   *
   * libraries: List<FilePath>
   *
   *   A list of the paths of library elements referenced by files in existing
   *   analysis roots.
   *
   * packageMap: Map<String, Map<String, List<FilePath>>>
   *
   *   A mapping from context source roots to package maps which map package
   *   names to source directories for use in client-side package URI
   *   resolution.
   */
  Future<AnalysisGetLibraryDependenciesResult>
      sendAnalysisGetLibraryDependencies() async {
    var result = await server.send("analysis.getLibraryDependencies", null);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new AnalysisGetLibraryDependenciesResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Return the navigation information associated with the given region of the
   * given file. If the navigation information for the given file has not yet
   * been computed, or the most recently computed navigation information for
   * the given file is out of date, then the response for this request will be
   * delayed until it has been computed. If the content of the file changes
   * after this request was received but before a response could be sent, then
   * an error of type CONTENT_MODIFIED will be generated.
   *
   * If a navigation region overlaps (but extends either before or after) the
   * given region of the file it will be included in the result. This means
   * that it is theoretically possible to get the same navigation region in
   * response to multiple requests. Clients can avoid this by always choosing a
   * region that starts at the beginning of a line and ends at the end of a
   * (possibly different) line in the file.
   *
   * If a request is made for a file which does not exist, or which is not
   * currently subject to analysis (e.g. because it is not associated with any
   * analysis root specified to analysis.setAnalysisRoots), an error of type
   * GET_NAVIGATION_INVALID_FILE will be generated.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file in which navigation information is being requested.
   *
   * offset: int
   *
   *   The offset of the region for which navigation information is being
   *   requested.
   *
   * length: int
   *
   *   The length of the region for which navigation information is being
   *   requested.
   *
   * Returns
   *
   * files: List<FilePath>
   *
   *   A list of the paths of files that are referenced by the navigation
   *   targets.
   *
   * targets: List<NavigationTarget>
   *
   *   A list of the navigation targets that are referenced by the navigation
   *   regions.
   *
   * regions: List<NavigationRegion>
   *
   *   A list of the navigation regions within the requested region of the
   *   file.
   */
  Future<AnalysisGetNavigationResult> sendAnalysisGetNavigation(
      String file, int offset, int length) async {
    var params = new AnalysisGetNavigationParams(file, offset, length).toJson();
    var result = await server.send("analysis.getNavigation", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new AnalysisGetNavigationResult.fromJson(decoder, 'result', result);
  }

  /**
   * Return the transitive closure of reachable sources for a given file.
   *
   * If a request is made for a file which does not exist, or which is not
   * currently subject to analysis (e.g. because it is not associated with any
   * analysis root specified to analysis.setAnalysisRoots), an error of type
   * GET_REACHABLE_SOURCES_INVALID_FILE will be generated.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file for which reachable source information is being requested.
   *
   * Returns
   *
   * sources: Map<String, List<String>>
   *
   *   A mapping from source URIs to directly reachable source URIs. For
   *   example, a file "foo.dart" that imports "bar.dart" would have the
   *   corresponding mapping { "file:///foo.dart" : ["file:///bar.dart"] }. If
   *   "bar.dart" has further imports (or exports) there will be a mapping from
   *   the URI "file:///bar.dart" to them. To check if a specific URI is
   *   reachable from a given file, clients can check for its presence in the
   *   resulting key set.
   */
  @deprecated
  Future<AnalysisGetReachableSourcesResult> sendAnalysisGetReachableSources(
      String file) async {
    var params = new AnalysisGetReachableSourcesParams(file).toJson();
    var result = await server.send("analysis.getReachableSources", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new AnalysisGetReachableSourcesResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Return the signature information associated with the given location in the
   * given file. If the signature information for the given file has not yet
   * been computed, or the most recently computed signature information for the
   * given file is out of date, then the response for this request will be
   * delayed until it has been computed. If a request is made for a file which
   * does not exist, or which is not currently subject to analysis (e.g.
   * because it is not associated with any analysis root specified to
   * analysis.setAnalysisRoots), an error of type GET_SIGNATURE_INVALID_FILE
   * will be generated. If the location given is not inside the argument list
   * for a function (including method and constructor) invocation, then an
   * error of type GET_SIGNATURE_INVALID_OFFSET will be generated. If the
   * location is inside an argument list but the function is not defined or
   * cannot be determined (such as a method invocation where the target has
   * type 'dynamic') then an error of type GET_SIGNATURE_UNKNOWN_FUNCTION will
   * be generated.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file in which signature information is being requested.
   *
   * offset: int
   *
   *   The location for which signature information is being requested.
   *
   * Returns
   *
   * name: String
   *
   *   The name of the function being invoked at the given offset.
   *
   * parameters: List<ParameterInfo>
   *
   *   A list of information about each of the parameters of the function being
   *   invoked.
   *
   * dartdoc: String (optional)
   *
   *   The dartdoc associated with the function being invoked. Other than the
   *   removal of the comment delimiters, including leading asterisks in the
   *   case of a block comment, the dartdoc is unprocessed markdown. This data
   *   is omitted if there is no referenced element, or if the element has no
   *   dartdoc.
   */
  Future<AnalysisGetSignatureResult> sendAnalysisGetSignature(
      String file, int offset) async {
    var params = new AnalysisGetSignatureParams(file, offset).toJson();
    var result = await server.send("analysis.getSignature", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new AnalysisGetSignatureResult.fromJson(decoder, 'result', result);
  }

  /**
   * Force the re-analysis of everything contained in the specified analysis
   * roots. This will cause all previously computed analysis results to be
   * discarded and recomputed, and will cause all subscribed notifications to
   * be re-sent.
   *
   * If no analysis roots are provided, then all current analysis roots will be
   * re-analyzed. If an empty list of analysis roots is provided, then nothing
   * will be re-analyzed. If the list contains one or more paths that are not
   * currently analysis roots, then an error of type INVALID_ANALYSIS_ROOT will
   * be generated.
   *
   * Parameters
   *
   * roots: List<FilePath> (optional)
   *
   *   A list of the analysis roots that are to be re-analyzed.
   */
  Future sendAnalysisReanalyze({List<String> roots}) async {
    var params = new AnalysisReanalyzeParams(roots: roots).toJson();
    var result = await server.send("analysis.reanalyze", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Sets the root paths used to determine which files to analyze. The set of
   * files to be analyzed are all of the files in one of the root paths that
   * are not either explicitly or implicitly excluded. A file is explicitly
   * excluded if it is in one of the excluded paths. A file is implicitly
   * excluded if it is in a subdirectory of one of the root paths where the
   * name of the subdirectory starts with a period (that is, a hidden
   * directory).
   *
   * Note that this request determines the set of requested analysis roots. The
   * actual set of analysis roots at any given time is the intersection of this
   * set with the set of files and directories actually present on the
   * filesystem. When the filesystem changes, the actual set of analysis roots
   * is automatically updated, but the set of requested analysis roots is
   * unchanged. This means that if the client sets an analysis root before the
   * root becomes visible to server in the filesystem, there is no error; once
   * the server sees the root in the filesystem it will start analyzing it.
   * Similarly, server will stop analyzing files that are removed from the file
   * system but they will remain in the set of requested roots.
   *
   * If an included path represents a file, then server will look in the
   * directory containing the file for a pubspec.yaml file. If none is found,
   * then the parents of the directory will be searched until such a file is
   * found or the root of the file system is reached. If such a file is found,
   * it will be used to resolve package: URI’s within the file.
   *
   * Parameters
   *
   * included: List<FilePath>
   *
   *   A list of the files and directories that should be analyzed.
   *
   * excluded: List<FilePath>
   *
   *   A list of the files and directories within the included directories that
   *   should not be analyzed.
   *
   * packageRoots: Map<FilePath, FilePath> (optional)
   *
   *   A mapping from source directories to package roots that should override
   *   the normal package: URI resolution mechanism.
   *
   *   If a package root is a directory, then the analyzer will behave as
   *   though the associated source directory in the map contains a special
   *   pubspec.yaml file which resolves any package: URI to the corresponding
   *   path within that package root directory. The effect is the same as
   *   specifying the package root directory as a "--package_root" parameter to
   *   the Dart VM when executing any Dart file inside the source directory.
   *
   *   If a package root is a file, then the analyzer will behave as though
   *   that file is a ".packages" file in the source directory. The effect is
   *   the same as specifying the file as a "--packages" parameter to the Dart
   *   VM when executing any Dart file inside the source directory.
   *
   *   Files in any directories that are not overridden by this mapping have
   *   their package: URI's resolved using the normal pubspec.yaml mechanism.
   *   If this field is absent, or the empty map is specified, that indicates
   *   that the normal pubspec.yaml mechanism should always be used.
   */
  Future sendAnalysisSetAnalysisRoots(
      List<String> included, List<String> excluded,
      {Map<String, String> packageRoots}) async {
    var params = new AnalysisSetAnalysisRootsParams(included, excluded,
            packageRoots: packageRoots)
        .toJson();
    var result = await server.send("analysis.setAnalysisRoots", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Subscribe for general services (that is, services that are not specific to
   * individual files). All previous subscriptions are replaced by the given
   * set of services.
   *
   * It is an error if any of the elements in the list are not valid services.
   * If there is an error, then the current subscriptions will remain
   * unchanged.
   *
   * Parameters
   *
   * subscriptions: List<GeneralAnalysisService>
   *
   *   A list of the services being subscribed to.
   */
  Future sendAnalysisSetGeneralSubscriptions(
      List<GeneralAnalysisService> subscriptions) async {
    var params =
        new AnalysisSetGeneralSubscriptionsParams(subscriptions).toJson();
    var result = await server.send("analysis.setGeneralSubscriptions", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Set the priority files to the files in the given list. A priority file is
   * a file that is given priority when scheduling which analysis work to do
   * first. The list typically contains those files that are visible to the
   * user and those for which analysis results will have the biggest impact on
   * the user experience. The order of the files within the list is
   * significant: the first file will be given higher priority than the second,
   * the second higher priority than the third, and so on.
   *
   * Note that this request determines the set of requested priority files. The
   * actual set of priority files is the intersection of the requested set of
   * priority files with the set of files currently subject to analysis. (See
   * analysis.setSubscriptions for a description of files that are subject to
   * analysis.)
   *
   * If a requested priority file is a directory it is ignored, but remains in
   * the set of requested priority files so that if it later becomes a file it
   * can be included in the set of actual priority files.
   *
   * Parameters
   *
   * files: List<FilePath>
   *
   *   The files that are to be a priority for analysis.
   */
  Future sendAnalysisSetPriorityFiles(List<String> files) async {
    var params = new AnalysisSetPriorityFilesParams(files).toJson();
    var result = await server.send("analysis.setPriorityFiles", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Subscribe for services that are specific to individual files. All previous
   * subscriptions are replaced by the current set of subscriptions. If a given
   * service is not included as a key in the map then no files will be
   * subscribed to the service, exactly as if the service had been included in
   * the map with an explicit empty list of files.
   *
   * Note that this request determines the set of requested subscriptions. The
   * actual set of subscriptions at any given time is the intersection of this
   * set with the set of files currently subject to analysis. The files
   * currently subject to analysis are the set of files contained within an
   * actual analysis root but not excluded, plus all of the files transitively
   * reachable from those files via import, export and part directives. (See
   * analysis.setAnalysisRoots for an explanation of how the actual analysis
   * roots are determined.) When the actual analysis roots change, the actual
   * set of subscriptions is automatically updated, but the set of requested
   * subscriptions is unchanged.
   *
   * If a requested subscription is a directory it is ignored, but remains in
   * the set of requested subscriptions so that if it later becomes a file it
   * can be included in the set of actual subscriptions.
   *
   * It is an error if any of the keys in the map are not valid services. If
   * there is an error, then the existing subscriptions will remain unchanged.
   *
   * Parameters
   *
   * subscriptions: Map<AnalysisService, List<FilePath>>
   *
   *   A table mapping services to a list of the files being subscribed to the
   *   service.
   */
  Future sendAnalysisSetSubscriptions(
      Map<AnalysisService, List<String>> subscriptions) async {
    var params = new AnalysisSetSubscriptionsParams(subscriptions).toJson();
    var result = await server.send("analysis.setSubscriptions", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Update the content of one or more files. Files that were previously
   * updated but not included in this update remain unchanged. This effectively
   * represents an overlay of the filesystem. The files whose content is
   * overridden are therefore seen by server as being files with the given
   * content, even if the files do not exist on the filesystem or if the file
   * path represents the path to a directory on the filesystem.
   *
   * Parameters
   *
   * files: Map<FilePath, AddContentOverlay | ChangeContentOverlay |
   * RemoveContentOverlay>
   *
   *   A table mapping the files whose content has changed to a description of
   *   the content change.
   *
   * Returns
   */
  Future<AnalysisUpdateContentResult> sendAnalysisUpdateContent(
      Map<String, dynamic> files) async {
    var params = new AnalysisUpdateContentParams(files).toJson();
    var result = await server.send("analysis.updateContent", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new AnalysisUpdateContentResult.fromJson(decoder, 'result', result);
  }

  /**
   * Deprecated: all of the options can be set by users in an analysis options
   * file.
   *
   * Update the options controlling analysis based on the given set of options.
   * Any options that are not included in the analysis options will not be
   * changed. If there are options in the analysis options that are not valid,
   * they will be silently ignored.
   *
   * Parameters
   *
   * options: AnalysisOptions
   *
   *   The options that are to be used to control analysis.
   */
  @deprecated
  Future sendAnalysisUpdateOptions(AnalysisOptions options) async {
    var params = new AnalysisUpdateOptionsParams(options).toJson();
    var result = await server.send("analysis.updateOptions", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Reports the paths of the files that are being analyzed.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "ANALYZED_FILES" in the list of services passed in
   * an analysis.setGeneralSubscriptions request.
   *
   * Parameters
   *
   * directories: List<FilePath>
   *
   *   A list of the paths of the files that are being analyzed.
   */
  Stream<AnalysisAnalyzedFilesParams> onAnalysisAnalyzedFiles;

  /**
   * Stream controller for [onAnalysisAnalyzedFiles].
   */
  StreamController<AnalysisAnalyzedFilesParams> _onAnalysisAnalyzedFiles;

  /**
   * Reports closing labels relevant to a given file.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "CLOSING_LABELS" in the list of services passed in
   * an analysis.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file the closing labels relate to.
   *
   * labels: List<ClosingLabel>
   *
   *   Closing labels relevant to the file. Each item represents a useful label
   *   associated with some range with may be useful to display to the user
   *   within the editor at the end of the range to indicate what construct is
   *   closed at that location. Closing labels include constructor/method calls
   *   and List arguments that span multiple lines. Note that the ranges that
   *   are returned can overlap each other because they may be associated with
   *   constructs that can be nested.
   */
  Stream<AnalysisClosingLabelsParams> onAnalysisClosingLabels;

  /**
   * Stream controller for [onAnalysisClosingLabels].
   */
  StreamController<AnalysisClosingLabelsParams> _onAnalysisClosingLabels;

  /**
   * Reports the errors associated with a given file. The set of errors
   * included in the notification is always a complete list that supersedes any
   * previously reported errors.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the errors.
   *
   * errors: List<AnalysisError>
   *
   *   The errors contained in the file.
   */
  Stream<AnalysisErrorsParams> onAnalysisErrors;

  /**
   * Stream controller for [onAnalysisErrors].
   */
  StreamController<AnalysisErrorsParams> _onAnalysisErrors;

  /**
   * Reports that any analysis results that were previously associated with the
   * given files should be considered to be invalid because those files are no
   * longer being analyzed, either because the analysis root that contained it
   * is no longer being analyzed or because the file no longer exists.
   *
   * If a file is included in this notification and at some later time a
   * notification with results for the file is received, clients should assume
   * that the file is once again being analyzed and the information should be
   * processed.
   *
   * It is not possible to subscribe to or unsubscribe from this notification.
   *
   * Parameters
   *
   * files: List<FilePath>
   *
   *   The files that are no longer being analyzed.
   */
  Stream<AnalysisFlushResultsParams> onAnalysisFlushResults;

  /**
   * Stream controller for [onAnalysisFlushResults].
   */
  StreamController<AnalysisFlushResultsParams> _onAnalysisFlushResults;

  /**
   * Reports the folding regions associated with a given file. Folding regions
   * can be nested, but will not be overlapping. Nesting occurs when a foldable
   * element, such as a method, is nested inside another foldable element such
   * as a class.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "FOLDING" in the list of services passed in an
   * analysis.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the folding regions.
   *
   * regions: List<FoldingRegion>
   *
   *   The folding regions contained in the file.
   */
  Stream<AnalysisFoldingParams> onAnalysisFolding;

  /**
   * Stream controller for [onAnalysisFolding].
   */
  StreamController<AnalysisFoldingParams> _onAnalysisFolding;

  /**
   * Reports the highlight regions associated with a given file.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "HIGHLIGHTS" in the list of services passed in an
   * analysis.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the highlight regions.
   *
   * regions: List<HighlightRegion>
   *
   *   The highlight regions contained in the file. Each highlight region
   *   represents a particular syntactic or semantic meaning associated with
   *   some range. Note that the highlight regions that are returned can
   *   overlap other highlight regions if there is more than one meaning
   *   associated with a particular region.
   */
  Stream<AnalysisHighlightsParams> onAnalysisHighlights;

  /**
   * Stream controller for [onAnalysisHighlights].
   */
  StreamController<AnalysisHighlightsParams> _onAnalysisHighlights;

  /**
   * Reports the classes that are implemented or extended and class members
   * that are implemented or overridden in a file.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "IMPLEMENTED" in the list of services passed in an
   * analysis.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file with which the implementations are associated.
   *
   * classes: List<ImplementedClass>
   *
   *   The classes defined in the file that are implemented or extended.
   *
   * members: List<ImplementedMember>
   *
   *   The member defined in the file that are implemented or overridden.
   */
  Stream<AnalysisImplementedParams> onAnalysisImplemented;

  /**
   * Stream controller for [onAnalysisImplemented].
   */
  StreamController<AnalysisImplementedParams> _onAnalysisImplemented;

  /**
   * Reports that the navigation information associated with a region of a
   * single file has become invalid and should be re-requested.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "INVALIDATE" in the list of services passed in an
   * analysis.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file whose information has been invalidated.
   *
   * offset: int
   *
   *   The offset of the invalidated region.
   *
   * length: int
   *
   *   The length of the invalidated region.
   *
   * delta: int
   *
   *   The delta to be applied to the offsets in information that follows the
   *   invalidated region in order to update it so that it doesn't need to be
   *   re-requested.
   */
  Stream<AnalysisInvalidateParams> onAnalysisInvalidate;

  /**
   * Stream controller for [onAnalysisInvalidate].
   */
  StreamController<AnalysisInvalidateParams> _onAnalysisInvalidate;

  /**
   * Reports the navigation targets associated with a given file.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "NAVIGATION" in the list of services passed in an
   * analysis.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the navigation regions.
   *
   * regions: List<NavigationRegion>
   *
   *   The navigation regions contained in the file. The regions are sorted by
   *   their offsets. Each navigation region represents a list of targets
   *   associated with some range. The lists will usually contain a single
   *   target, but can contain more in the case of a part that is included in
   *   multiple libraries or in Dart code that is compiled against multiple
   *   versions of a package. Note that the navigation regions that are
   *   returned do not overlap other navigation regions.
   *
   * targets: List<NavigationTarget>
   *
   *   The navigation targets referenced in the file. They are referenced by
   *   NavigationRegions by their index in this array.
   *
   * files: List<FilePath>
   *
   *   The files containing navigation targets referenced in the file. They are
   *   referenced by NavigationTargets by their index in this array.
   */
  Stream<AnalysisNavigationParams> onAnalysisNavigation;

  /**
   * Stream controller for [onAnalysisNavigation].
   */
  StreamController<AnalysisNavigationParams> _onAnalysisNavigation;

  /**
   * Reports the occurrences of references to elements within a single file.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "OCCURRENCES" in the list of services passed in an
   * analysis.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file in which the references occur.
   *
   * occurrences: List<Occurrences>
   *
   *   The occurrences of references to elements within the file.
   */
  Stream<AnalysisOccurrencesParams> onAnalysisOccurrences;

  /**
   * Stream controller for [onAnalysisOccurrences].
   */
  StreamController<AnalysisOccurrencesParams> _onAnalysisOccurrences;

  /**
   * Reports the outline associated with a single file.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "OUTLINE" in the list of services passed in an
   * analysis.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file with which the outline is associated.
   *
   * kind: FileKind
   *
   *   The kind of the file.
   *
   * libraryName: String (optional)
   *
   *   The name of the library defined by the file using a "library" directive,
   *   or referenced by a "part of" directive. If both "library" and "part of"
   *   directives are present, then the "library" directive takes precedence.
   *   This field will be omitted if the file has neither "library" nor "part
   *   of" directives.
   *
   * outline: Outline
   *
   *   The outline associated with the file.
   */
  Stream<AnalysisOutlineParams> onAnalysisOutline;

  /**
   * Stream controller for [onAnalysisOutline].
   */
  StreamController<AnalysisOutlineParams> _onAnalysisOutline;

  /**
   * Reports the overriding members in a file.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "OVERRIDES" in the list of services passed in an
   * analysis.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file with which the overrides are associated.
   *
   * overrides: List<Override>
   *
   *   The overrides associated with the file.
   */
  Stream<AnalysisOverridesParams> onAnalysisOverrides;

  /**
   * Stream controller for [onAnalysisOverrides].
   */
  StreamController<AnalysisOverridesParams> _onAnalysisOverrides;

  /**
   * Request that completion suggestions for the given offset in the given file
   * be returned.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the point at which suggestions are to be made.
   *
   * offset: int
   *
   *   The offset within the file at which suggestions are to be made.
   *
   * Returns
   *
   * id: CompletionId
   *
   *   The identifier used to associate results with this completion request.
   */
  Future<CompletionGetSuggestionsResult> sendCompletionGetSuggestions(
      String file, int offset) async {
    var params = new CompletionGetSuggestionsParams(file, offset).toJson();
    var result = await server.send("completion.getSuggestions", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new CompletionGetSuggestionsResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Reports the completion suggestions that should be presented to the user.
   * The set of suggestions included in the notification is always a complete
   * list that supersedes any previously reported suggestions.
   *
   * Parameters
   *
   * id: CompletionId
   *
   *   The id associated with the completion.
   *
   * replacementOffset: int
   *
   *   The offset of the start of the text to be replaced. This will be
   *   different than the offset used to request the completion suggestions if
   *   there was a portion of an identifier before the original offset. In
   *   particular, the replacementOffset will be the offset of the beginning of
   *   said identifier.
   *
   * replacementLength: int
   *
   *   The length of the text to be replaced if the remainder of the identifier
   *   containing the cursor is to be replaced when the suggestion is applied
   *   (that is, the number of characters in the existing identifier).
   *
   * results: List<CompletionSuggestion>
   *
   *   The completion suggestions being reported. The notification contains all
   *   possible completions at the requested cursor position, even those that
   *   do not match the characters the user has already typed. This allows the
   *   client to respond to further keystrokes from the user without having to
   *   make additional requests.
   *
   * isLast: bool
   *
   *   True if this is that last set of results that will be returned for the
   *   indicated completion.
   */
  Stream<CompletionResultsParams> onCompletionResults;

  /**
   * Stream controller for [onCompletionResults].
   */
  StreamController<CompletionResultsParams> _onCompletionResults;

  /**
   * Perform a search for references to the element defined or referenced at
   * the given offset in the given file.
   *
   * An identifier is returned immediately, and individual results will be
   * returned via the search.results notification as they become available.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the declaration of or reference to the element used
   *   to define the search.
   *
   * offset: int
   *
   *   The offset within the file of the declaration of or reference to the
   *   element.
   *
   * includePotential: bool
   *
   *   True if potential matches are to be included in the results.
   *
   * Returns
   *
   * id: SearchId (optional)
   *
   *   The identifier used to associate results with this search request.
   *
   *   If no element was found at the given location, this field will be
   *   absent, and no results will be reported via the search.results
   *   notification.
   *
   * element: Element (optional)
   *
   *   The element referenced or defined at the given offset and whose
   *   references will be returned in the search results.
   *
   *   If no element was found at the given location, this field will be
   *   absent.
   */
  Future<SearchFindElementReferencesResult> sendSearchFindElementReferences(
      String file, int offset, bool includePotential) async {
    var params =
        new SearchFindElementReferencesParams(file, offset, includePotential)
            .toJson();
    var result = await server.send("search.findElementReferences", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new SearchFindElementReferencesResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Perform a search for declarations of members whose name is equal to the
   * given name.
   *
   * An identifier is returned immediately, and individual results will be
   * returned via the search.results notification as they become available.
   *
   * Parameters
   *
   * name: String
   *
   *   The name of the declarations to be found.
   *
   * Returns
   *
   * id: SearchId
   *
   *   The identifier used to associate results with this search request.
   */
  Future<SearchFindMemberDeclarationsResult> sendSearchFindMemberDeclarations(
      String name) async {
    var params = new SearchFindMemberDeclarationsParams(name).toJson();
    var result = await server.send("search.findMemberDeclarations", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new SearchFindMemberDeclarationsResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Perform a search for references to members whose name is equal to the
   * given name. This search does not check to see that there is a member
   * defined with the given name, so it is able to find references to undefined
   * members as well.
   *
   * An identifier is returned immediately, and individual results will be
   * returned via the search.results notification as they become available.
   *
   * Parameters
   *
   * name: String
   *
   *   The name of the references to be found.
   *
   * Returns
   *
   * id: SearchId
   *
   *   The identifier used to associate results with this search request.
   */
  Future<SearchFindMemberReferencesResult> sendSearchFindMemberReferences(
      String name) async {
    var params = new SearchFindMemberReferencesParams(name).toJson();
    var result = await server.send("search.findMemberReferences", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new SearchFindMemberReferencesResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Perform a search for declarations of top-level elements (classes,
   * typedefs, getters, setters, functions and fields) whose name matches the
   * given pattern.
   *
   * An identifier is returned immediately, and individual results will be
   * returned via the search.results notification as they become available.
   *
   * Parameters
   *
   * pattern: String
   *
   *   The regular expression used to match the names of the declarations to be
   *   found.
   *
   * Returns
   *
   * id: SearchId
   *
   *   The identifier used to associate results with this search request.
   */
  Future<SearchFindTopLevelDeclarationsResult>
      sendSearchFindTopLevelDeclarations(String pattern) async {
    var params = new SearchFindTopLevelDeclarationsParams(pattern).toJson();
    var result = await server.send("search.findTopLevelDeclarations", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new SearchFindTopLevelDeclarationsResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Return top-level and class member declarations.
   *
   * Parameters
   *
   * file: FilePath (optional)
   *
   *   If this field is provided, return only declarations in this file. If
   *   this field is missing, return declarations in all files.
   *
   * pattern: String (optional)
   *
   *   The regular expression used to match the names of declarations. If this
   *   field is missing, return all declarations.
   *
   * maxResults: int (optional)
   *
   *   The maximum number of declarations to return. If this field is missing,
   *   return all matching declarations.
   *
   * Returns
   *
   * declarations: List<ElementDeclaration>
   *
   *   The list of declarations.
   *
   * files: List<FilePath>
   *
   *   The list of the paths of files with declarations.
   */
  Future<SearchGetElementDeclarationsResult> sendSearchGetElementDeclarations(
      {String file, String pattern, int maxResults}) async {
    var params = new SearchGetElementDeclarationsParams(
            file: file, pattern: pattern, maxResults: maxResults)
        .toJson();
    var result = await server.send("search.getElementDeclarations", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new SearchGetElementDeclarationsResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Return the type hierarchy of the class declared or referenced at the given
   * location.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the declaration or reference to the type for which a
   *   hierarchy is being requested.
   *
   * offset: int
   *
   *   The offset of the name of the type within the file.
   *
   * superOnly: bool (optional)
   *
   *   True if the client is only requesting superclasses and interfaces
   *   hierarchy.
   *
   * Returns
   *
   * hierarchyItems: List<TypeHierarchyItem> (optional)
   *
   *   A list of the types in the requested hierarchy. The first element of the
   *   list is the item representing the type for which the hierarchy was
   *   requested. The index of other elements of the list is unspecified, but
   *   correspond to the integers used to reference supertype and subtype items
   *   within the items.
   *
   *   This field will be absent if the code at the given file and offset does
   *   not represent a type, or if the file has not been sufficiently analyzed
   *   to allow a type hierarchy to be produced.
   */
  Future<SearchGetTypeHierarchyResult> sendSearchGetTypeHierarchy(
      String file, int offset,
      {bool superOnly}) async {
    var params =
        new SearchGetTypeHierarchyParams(file, offset, superOnly: superOnly)
            .toJson();
    var result = await server.send("search.getTypeHierarchy", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new SearchGetTypeHierarchyResult.fromJson(decoder, 'result', result);
  }

  /**
   * Reports some or all of the results of performing a requested search.
   * Unlike other notifications, this notification contains search results that
   * should be added to any previously received search results associated with
   * the same search id.
   *
   * Parameters
   *
   * id: SearchId
   *
   *   The id associated with the search.
   *
   * results: List<SearchResult>
   *
   *   The search results being reported.
   *
   * isLast: bool
   *
   *   True if this is that last set of results that will be returned for the
   *   indicated search.
   */
  Stream<SearchResultsParams> onSearchResults;

  /**
   * Stream controller for [onSearchResults].
   */
  StreamController<SearchResultsParams> _onSearchResults;

  /**
   * Format the contents of a single file. The currently selected region of
   * text is passed in so that the selection can be preserved across the
   * formatting operation. The updated selection will be as close to matching
   * the original as possible, but whitespace at the beginning or end of the
   * selected region will be ignored. If preserving selection information is
   * not required, zero (0) can be specified for both the selection offset and
   * selection length.
   *
   * If a request is made for a file which does not exist, or which is not
   * currently subject to analysis (e.g. because it is not associated with any
   * analysis root specified to analysis.setAnalysisRoots), an error of type
   * FORMAT_INVALID_FILE will be generated. If the source contains syntax
   * errors, an error of type FORMAT_WITH_ERRORS will be generated.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the code to be formatted.
   *
   * selectionOffset: int
   *
   *   The offset of the current selection in the file.
   *
   * selectionLength: int
   *
   *   The length of the current selection in the file.
   *
   * lineLength: int (optional)
   *
   *   The line length to be used by the formatter.
   *
   * Returns
   *
   * edits: List<SourceEdit>
   *
   *   The edit(s) to be applied in order to format the code. The list will be
   *   empty if the code was already formatted (there are no changes).
   *
   * selectionOffset: int
   *
   *   The offset of the selection after formatting the code.
   *
   * selectionLength: int
   *
   *   The length of the selection after formatting the code.
   */
  Future<EditFormatResult> sendEditFormat(
      String file, int selectionOffset, int selectionLength,
      {int lineLength}) async {
    var params = new EditFormatParams(file, selectionOffset, selectionLength,
            lineLength: lineLength)
        .toJson();
    var result = await server.send("edit.format", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditFormatResult.fromJson(decoder, 'result', result);
  }

  /**
   * Return the set of assists that are available at the given location. An
   * assist is distinguished from a refactoring primarily by the fact that it
   * affects a single file and does not require user input in order to be
   * performed.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the code for which assists are being requested.
   *
   * offset: int
   *
   *   The offset of the code for which assists are being requested.
   *
   * length: int
   *
   *   The length of the code for which assists are being requested.
   *
   * Returns
   *
   * assists: List<SourceChange>
   *
   *   The assists that are available at the given location.
   */
  Future<EditGetAssistsResult> sendEditGetAssists(
      String file, int offset, int length) async {
    var params = new EditGetAssistsParams(file, offset, length).toJson();
    var result = await server.send("edit.getAssists", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditGetAssistsResult.fromJson(decoder, 'result', result);
  }

  /**
   * Get a list of the kinds of refactorings that are valid for the given
   * selection in the given file.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the code on which the refactoring would be based.
   *
   * offset: int
   *
   *   The offset of the code on which the refactoring would be based.
   *
   * length: int
   *
   *   The length of the code on which the refactoring would be based.
   *
   * Returns
   *
   * kinds: List<RefactoringKind>
   *
   *   The kinds of refactorings that are valid for the given selection.
   */
  Future<EditGetAvailableRefactoringsResult> sendEditGetAvailableRefactorings(
      String file, int offset, int length) async {
    var params =
        new EditGetAvailableRefactoringsParams(file, offset, length).toJson();
    var result = await server.send("edit.getAvailableRefactorings", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditGetAvailableRefactoringsResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Analyze the specified sources for recommended changes and return a set of
   * suggested edits for those sources. These edits may include changes to
   * sources outside the set of specified sources if a change in a specified
   * source requires it.
   *
   * Parameters
   *
   * included: List<FilePath>
   *
   *   A list of the files and directories for which edits should be suggested.
   *
   *   If a request is made with a path that is invalid, e.g. is not absolute
   *   and normalized, an error of type INVALID_FILE_PATH_FORMAT will be
   *   generated. If a request is made for a file which does not exist, or
   *   which is not currently subject to analysis (e.g. because it is not
   *   associated with any analysis root specified to
   *   analysis.setAnalysisRoots), an error of type FILE_NOT_ANALYZED will be
   *   generated.
   *
   * Returns
   *
   * suggestions: List<DartFixSuggestion>
   *
   *   A list of recommended changes that can be automatically made by applying
   *   the 'edits' included in this response.
   *
   * otherSuggestions: List<DartFixSuggestion>
   *
   *   A list of recommended changes that could not be automatically made.
   *
   * hasErrors: bool
   *
   *   True if the analyzed source contains errors that might impact the
   *   correctness of the recommended changes that can be automatically
   *   applied.
   *
   * edits: List<SourceFileEdit>
   *
   *   A list of source edits to apply the recommended changes.
   */
  Future<EditDartfixResult> sendEditDartfix(List<String> included) async {
    var params = new EditDartfixParams(included).toJson();
    var result = await server.send("edit.dartfix", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditDartfixResult.fromJson(decoder, 'result', result);
  }

  /**
   * Return the set of fixes that are available for the errors at a given
   * offset in a given file.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the errors for which fixes are being requested.
   *
   * offset: int
   *
   *   The offset used to select the errors for which fixes will be returned.
   *
   * Returns
   *
   * fixes: List<AnalysisErrorFixes>
   *
   *   The fixes that are available for the errors at the given offset.
   */
  Future<EditGetFixesResult> sendEditGetFixes(String file, int offset) async {
    var params = new EditGetFixesParams(file, offset).toJson();
    var result = await server.send("edit.getFixes", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditGetFixesResult.fromJson(decoder, 'result', result);
  }

  /**
   * Get the changes required to convert the postfix template at the given
   * location into the template's expanded form.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the postfix template to be expanded.
   *
   * key: String
   *
   *   The unique name that identifies the template in use.
   *
   * offset: int
   *
   *   The offset used to identify the code to which the template will be
   *   applied.
   *
   * Returns
   *
   * change: SourceChange
   *
   *   The change to be applied in order to complete the statement.
   */
  Future<EditGetPostfixCompletionResult> sendEditGetPostfixCompletion(
      String file, String key, int offset) async {
    var params = new EditGetPostfixCompletionParams(file, key, offset).toJson();
    var result = await server.send("edit.getPostfixCompletion", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditGetPostfixCompletionResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Get the changes required to perform a refactoring.
   *
   * If another refactoring request is received during the processing of this
   * one, an error of type REFACTORING_REQUEST_CANCELLED will be generated.
   *
   * Parameters
   *
   * kind: RefactoringKind
   *
   *   The kind of refactoring to be performed.
   *
   * file: FilePath
   *
   *   The file containing the code involved in the refactoring.
   *
   * offset: int
   *
   *   The offset of the region involved in the refactoring.
   *
   * length: int
   *
   *   The length of the region involved in the refactoring.
   *
   * validateOnly: bool
   *
   *   True if the client is only requesting that the values of the options be
   *   validated and no change be generated.
   *
   * options: RefactoringOptions (optional)
   *
   *   Data used to provide values provided by the user. The structure of the
   *   data is dependent on the kind of refactoring being performed. The data
   *   that is expected is documented in the section titled Refactorings,
   *   labeled as "Options". This field can be omitted if the refactoring does
   *   not require any options or if the values of those options are not known.
   *
   * Returns
   *
   * initialProblems: List<RefactoringProblem>
   *
   *   The initial status of the refactoring, i.e. problems related to the
   *   context in which the refactoring is requested. The array will be empty
   *   if there are no known problems.
   *
   * optionsProblems: List<RefactoringProblem>
   *
   *   The options validation status, i.e. problems in the given options, such
   *   as light-weight validation of a new name, flags compatibility, etc. The
   *   array will be empty if there are no known problems.
   *
   * finalProblems: List<RefactoringProblem>
   *
   *   The final status of the refactoring, i.e. problems identified in the
   *   result of a full, potentially expensive validation and / or change
   *   creation. The array will be empty if there are no known problems.
   *
   * feedback: RefactoringFeedback (optional)
   *
   *   Data used to provide feedback to the user. The structure of the data is
   *   dependent on the kind of refactoring being created. The data that is
   *   returned is documented in the section titled Refactorings, labeled as
   *   "Feedback".
   *
   * change: SourceChange (optional)
   *
   *   The changes that are to be applied to affect the refactoring. This field
   *   will be omitted if there are problems that prevent a set of changes from
   *   being computed, such as having no options specified for a refactoring
   *   that requires them, or if only validation was requested.
   *
   * potentialEdits: List<String> (optional)
   *
   *   The ids of source edits that are not known to be valid. An edit is not
   *   known to be valid if there was insufficient type information for the
   *   server to be able to determine whether or not the code needs to be
   *   modified, such as when a member is being renamed and there is a
   *   reference to a member from an unknown type. This field will be omitted
   *   if the change field is omitted or if there are no potential edits for
   *   the refactoring.
   */
  Future<EditGetRefactoringResult> sendEditGetRefactoring(RefactoringKind kind,
      String file, int offset, int length, bool validateOnly,
      {RefactoringOptions options}) async {
    var params = new EditGetRefactoringParams(
            kind, file, offset, length, validateOnly,
            options: options)
        .toJson();
    var result = await server.send("edit.getRefactoring", params);
    ResponseDecoder decoder = new ResponseDecoder(kind);
    return new EditGetRefactoringResult.fromJson(decoder, 'result', result);
  }

  /**
   * Get the changes required to convert the partial statement at the given
   * location into a syntactically valid statement. If the current statement is
   * already valid the change will insert a newline plus appropriate
   * indentation at the end of the line containing the offset. If a change that
   * makes the statement valid cannot be determined (perhaps because it has not
   * yet been implemented) the statement will be considered already valid and
   * the appropriate change returned.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the statement to be completed.
   *
   * offset: int
   *
   *   The offset used to identify the statement to be completed.
   *
   * Returns
   *
   * change: SourceChange
   *
   *   The change to be applied in order to complete the statement.
   *
   * whitespaceOnly: bool
   *
   *   Will be true if the change contains nothing but whitespace characters,
   *   or is empty.
   */
  Future<EditGetStatementCompletionResult> sendEditGetStatementCompletion(
      String file, int offset) async {
    var params = new EditGetStatementCompletionParams(file, offset).toJson();
    var result = await server.send("edit.getStatementCompletion", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditGetStatementCompletionResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Determine if the request postfix completion template is applicable at the
   * given location in the given file.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the postfix template to be expanded.
   *
   * key: String
   *
   *   The unique name that identifies the template in use.
   *
   * offset: int
   *
   *   The offset used to identify the code to which the template will be
   *   applied.
   *
   * Returns
   *
   * value: bool
   *
   *   True if the template can be expanded at the given location.
   */
  Future<EditIsPostfixCompletionApplicableResult>
      sendEditIsPostfixCompletionApplicable(
          String file, String key, int offset) async {
    var params =
        new EditIsPostfixCompletionApplicableParams(file, key, offset).toJson();
    var result =
        await server.send("edit.isPostfixCompletionApplicable", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditIsPostfixCompletionApplicableResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Return a list of all postfix templates currently available.
   *
   * Returns
   *
   * templates: List<PostfixTemplateDescriptor>
   *
   *   The list of available templates.
   */
  Future<EditListPostfixCompletionTemplatesResult>
      sendEditListPostfixCompletionTemplates() async {
    var result = await server.send("edit.listPostfixCompletionTemplates", null);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditListPostfixCompletionTemplatesResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Return a list of edits that would need to be applied in order to ensure
   * that all of the elements in the specified list of imported elements are
   * accessible within the library.
   *
   * If a request is made for a file that does not exist, or that is not
   * currently subject to analysis (e.g. because it is not associated with any
   * analysis root specified via analysis.setAnalysisRoots), an error of type
   * IMPORT_ELEMENTS_INVALID_FILE will be generated.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file in which the specified elements are to be made accessible.
   *
   * elements: List<ImportedElements>
   *
   *   The elements to be made accessible in the specified file.
   *
   * Returns
   *
   * edit: SourceFileEdit (optional)
   *
   *   The edits to be applied in order to make the specified elements
   *   accessible. The file to be edited will be the defining compilation unit
   *   of the library containing the file specified in the request, which can
   *   be different than the file specified in the request if the specified
   *   file is a part file. This field will be omitted if there are no edits
   *   that need to be applied.
   */
  Future<EditImportElementsResult> sendEditImportElements(
      String file, List<ImportedElements> elements) async {
    var params = new EditImportElementsParams(file, elements).toJson();
    var result = await server.send("edit.importElements", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditImportElementsResult.fromJson(decoder, 'result', result);
  }

  /**
   * Sort all of the directives, unit and class members of the given Dart file.
   *
   * If a request is made for a file that does not exist, does not belong to an
   * analysis root or is not a Dart file, SORT_MEMBERS_INVALID_FILE will be
   * generated.
   *
   * If the Dart file has scan or parse errors, SORT_MEMBERS_PARSE_ERRORS will
   * be generated.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The Dart file to sort.
   *
   * Returns
   *
   * edit: SourceFileEdit
   *
   *   The file edit that is to be applied to the given file to effect the
   *   sorting.
   */
  Future<EditSortMembersResult> sendEditSortMembers(String file) async {
    var params = new EditSortMembersParams(file).toJson();
    var result = await server.send("edit.sortMembers", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditSortMembersResult.fromJson(decoder, 'result', result);
  }

  /**
   * Organizes all of the directives - removes unused imports and sorts
   * directives of the given Dart file according to the Dart Style Guide.
   *
   * If a request is made for a file that does not exist, does not belong to an
   * analysis root or is not a Dart file, FILE_NOT_ANALYZED will be generated.
   *
   * If directives of the Dart file cannot be organized, for example because it
   * has scan or parse errors, or by other reasons, ORGANIZE_DIRECTIVES_ERROR
   * will be generated. The message will provide details about the reason.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The Dart file to organize directives in.
   *
   * Returns
   *
   * edit: SourceFileEdit
   *
   *   The file edit that is to be applied to the given file to effect the
   *   organizing.
   */
  Future<EditOrganizeDirectivesResult> sendEditOrganizeDirectives(
      String file) async {
    var params = new EditOrganizeDirectivesParams(file).toJson();
    var result = await server.send("edit.organizeDirectives", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new EditOrganizeDirectivesResult.fromJson(decoder, 'result', result);
  }

  /**
   * Create an execution context for the executable file with the given path.
   * The context that is created will persist until execution.deleteContext is
   * used to delete it. Clients, therefore, are responsible for managing the
   * lifetime of execution contexts.
   *
   * Parameters
   *
   * contextRoot: FilePath
   *
   *   The path of the Dart or HTML file that will be launched, or the path of
   *   the directory containing the file.
   *
   * Returns
   *
   * id: ExecutionContextId
   *
   *   The identifier used to refer to the execution context that was created.
   */
  Future<ExecutionCreateContextResult> sendExecutionCreateContext(
      String contextRoot) async {
    var params = new ExecutionCreateContextParams(contextRoot).toJson();
    var result = await server.send("execution.createContext", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new ExecutionCreateContextResult.fromJson(decoder, 'result', result);
  }

  /**
   * Delete the execution context with the given identifier. The context id is
   * no longer valid after this command. The server is allowed to re-use ids
   * when they are no longer valid.
   *
   * Parameters
   *
   * id: ExecutionContextId
   *
   *   The identifier of the execution context that is to be deleted.
   */
  Future sendExecutionDeleteContext(String id) async {
    var params = new ExecutionDeleteContextParams(id).toJson();
    var result = await server.send("execution.deleteContext", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Request completion suggestions for the given runtime context.
   *
   * It might take one or two requests of this type to get completion
   * suggestions. The first request should have only "code", "offset", and
   * "variables", but not "expressions". If there are sub-expressions that can
   * have different runtime types, and are considered to be safe to evaluate at
   * runtime (e.g. getters), so using their actual runtime types can improve
   * completion results, the server will not include the "suggestions" field in
   * the response, and instead will return the "expressions" field. The client
   * will use debug API to get current runtime types for these sub-expressions
   * and send another request, this time with "expressions". If there are no
   * interesting sub-expressions to get runtime types for, or when the
   * "expressions" field is provided by the client, the server will return
   * "suggestions" in the response.
   *
   * Parameters
   *
   * code: String
   *
   *   The code to get suggestions in.
   *
   * offset: int
   *
   *   The offset within the code to get suggestions at.
   *
   * contextFile: FilePath
   *
   *   The path of the context file, e.g. the file of the current debugger
   *   frame. The combination of the context file and context offset can be
   *   used to ensure that all variables of the context are available for
   *   completion (with their static types).
   *
   * contextOffset: int
   *
   *   The offset in the context file, e.g. the line offset in the current
   *   debugger frame.
   *
   * variables: List<RuntimeCompletionVariable>
   *
   *   The runtime context variables that are potentially referenced in the
   *   code.
   *
   * expressions: List<RuntimeCompletionExpression> (optional)
   *
   *   The list of sub-expressions in the code for which the client wants to
   *   provide runtime types. It does not have to be the full list of
   *   expressions requested by the server, for missing expressions their
   *   static types will be used.
   *
   *   When this field is omitted, the server will return completion
   *   suggestions only when there are no interesting sub-expressions in the
   *   given code. The client may provide an empty list, in this case the
   *   server will return completion suggestions.
   *
   * Returns
   *
   * suggestions: List<CompletionSuggestion> (optional)
   *
   *   The completion suggestions. In contrast to usual completion request,
   *   suggestions for private elements also will be provided.
   *
   *   If there are sub-expressions that can have different runtime types, and
   *   are considered to be safe to evaluate at runtime (e.g. getters), so
   *   using their actual runtime types can improve completion results, the
   *   server omits this field in the response, and instead will return the
   *   "expressions" field.
   *
   * expressions: List<RuntimeCompletionExpression> (optional)
   *
   *   The list of sub-expressions in the code for which the server would like
   *   to know runtime types to provide better completion suggestions.
   *
   *   This field is omitted the field "suggestions" is returned.
   */
  Future<ExecutionGetSuggestionsResult> sendExecutionGetSuggestions(
      String code,
      int offset,
      String contextFile,
      int contextOffset,
      List<RuntimeCompletionVariable> variables,
      {List<RuntimeCompletionExpression> expressions}) async {
    var params = new ExecutionGetSuggestionsParams(
            code, offset, contextFile, contextOffset, variables,
            expressions: expressions)
        .toJson();
    var result = await server.send("execution.getSuggestions", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new ExecutionGetSuggestionsResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Map a URI from the execution context to the file that it corresponds to,
   * or map a file to the URI that it corresponds to in the execution context.
   *
   * Exactly one of the file and uri fields must be provided. If both fields
   * are provided, then an error of type INVALID_PARAMETER will be generated.
   * Similarly, if neither field is provided, then an error of type
   * INVALID_PARAMETER will be generated.
   *
   * If the file field is provided and the value is not the path of a file
   * (either the file does not exist or the path references something other
   * than a file), then an error of type INVALID_PARAMETER will be generated.
   *
   * If the uri field is provided and the value is not a valid URI or if the
   * URI references something that is not a file (either a file that does not
   * exist or something other than a file), then an error of type
   * INVALID_PARAMETER will be generated.
   *
   * If the contextRoot used to create the execution context does not exist,
   * then an error of type INVALID_EXECUTION_CONTEXT will be generated.
   *
   * Parameters
   *
   * id: ExecutionContextId
   *
   *   The identifier of the execution context in which the URI is to be
   *   mapped.
   *
   * file: FilePath (optional)
   *
   *   The path of the file to be mapped into a URI.
   *
   * uri: String (optional)
   *
   *   The URI to be mapped into a file path.
   *
   * Returns
   *
   * file: FilePath (optional)
   *
   *   The file to which the URI was mapped. This field is omitted if the uri
   *   field was not given in the request.
   *
   * uri: String (optional)
   *
   *   The URI to which the file path was mapped. This field is omitted if the
   *   file field was not given in the request.
   */
  Future<ExecutionMapUriResult> sendExecutionMapUri(String id,
      {String file, String uri}) async {
    var params = new ExecutionMapUriParams(id, file: file, uri: uri).toJson();
    var result = await server.send("execution.mapUri", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new ExecutionMapUriResult.fromJson(decoder, 'result', result);
  }

  /**
   * Deprecated: the analysis server no longer fires LAUNCH_DATA events.
   *
   * Subscribe for services. All previous subscriptions are replaced by the
   * given set of services.
   *
   * It is an error if any of the elements in the list are not valid services.
   * If there is an error, then the current subscriptions will remain
   * unchanged.
   *
   * Parameters
   *
   * subscriptions: List<ExecutionService>
   *
   *   A list of the services being subscribed to.
   */
  @deprecated
  Future sendExecutionSetSubscriptions(
      List<ExecutionService> subscriptions) async {
    var params = new ExecutionSetSubscriptionsParams(subscriptions).toJson();
    var result = await server.send("execution.setSubscriptions", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Reports information needed to allow a single file to be launched.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "LAUNCH_DATA" in the list of services passed in an
   * execution.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file for which launch data is being provided. This will either be a
   *   Dart library or an HTML file.
   *
   * kind: ExecutableKind (optional)
   *
   *   The kind of the executable file. This field is omitted if the file is
   *   not a Dart file.
   *
   * referencedFiles: List<FilePath> (optional)
   *
   *   A list of the Dart files that are referenced by the file. This field is
   *   omitted if the file is not an HTML file.
   */
  Stream<ExecutionLaunchDataParams> onExecutionLaunchData;

  /**
   * Stream controller for [onExecutionLaunchData].
   */
  StreamController<ExecutionLaunchDataParams> _onExecutionLaunchData;

  /**
   * Return server diagnostics.
   *
   * Returns
   *
   * contexts: List<ContextData>
   *
   *   The list of analysis contexts.
   */
  Future<DiagnosticGetDiagnosticsResult> sendDiagnosticGetDiagnostics() async {
    var result = await server.send("diagnostic.getDiagnostics", null);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new DiagnosticGetDiagnosticsResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Return the port of the diagnostic web server. If the server is not running
   * this call will start the server. If unable to start the diagnostic web
   * server, this call will return an error of DEBUG_PORT_COULD_NOT_BE_OPENED.
   *
   * Returns
   *
   * port: int
   *
   *   The diagnostic server port.
   */
  Future<DiagnosticGetServerPortResult> sendDiagnosticGetServerPort() async {
    var result = await server.send("diagnostic.getServerPort", null);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new DiagnosticGetServerPortResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Query whether analytics is enabled.
   *
   * This flag controls whether the analysis server sends any analytics data to
   * the cloud. If disabled, the analysis server does not send any analytics
   * data, and any data sent to it by clients (from sendEvent and sendTiming)
   * will be ignored.
   *
   * The value of this flag can be changed by other tools outside of the
   * analysis server's process. When you query the flag, you get the value of
   * the flag at a given moment. Clients should not use the value returned to
   * decide whether or not to send the sendEvent and sendTiming requests. Those
   * requests should be used unconditionally and server will determine whether
   * or not it is appropriate to forward the information to the cloud at the
   * time each request is received.
   *
   * Returns
   *
   * enabled: bool
   *
   *   Whether sending analytics is enabled or not.
   */
  Future<AnalyticsIsEnabledResult> sendAnalyticsIsEnabled() async {
    var result = await server.send("analytics.isEnabled", null);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new AnalyticsIsEnabledResult.fromJson(decoder, 'result', result);
  }

  /**
   * Enable or disable the sending of analytics data. Note that there are other
   * ways for users to change this setting, so clients cannot assume that they
   * have complete control over this setting. In particular, there is no
   * guarantee that the result returned by the isEnabled request will match the
   * last value set via this request.
   *
   * Parameters
   *
   * value: bool
   *
   *   Enable or disable analytics.
   */
  Future sendAnalyticsEnable(bool value) async {
    var params = new AnalyticsEnableParams(value).toJson();
    var result = await server.send("analytics.enable", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Send information about client events.
   *
   * Ask the analysis server to include the fact that an action was performed
   * in the client as part of the analytics data being sent. The data will only
   * be included if the sending of analytics data is enabled at the time the
   * request is processed. The action that was performed is indicated by the
   * value of the action field.
   *
   * The value of the action field should not include the identity of the
   * client. The analytics data sent by server will include the client id
   * passed in using the --client-id command-line argument. The request will be
   * ignored if the client id was not provided when server was started.
   *
   * Parameters
   *
   * action: String
   *
   *   The value used to indicate which action was performed.
   */
  Future sendAnalyticsSendEvent(String action) async {
    var params = new AnalyticsSendEventParams(action).toJson();
    var result = await server.send("analytics.sendEvent", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Send timing information for client events (e.g. code completions).
   *
   * Ask the analysis server to include the fact that a timed event occurred as
   * part of the analytics data being sent. The data will only be included if
   * the sending of analytics data is enabled at the time the request is
   * processed.
   *
   * The value of the event field should not include the identity of the
   * client. The analytics data sent by server will include the client id
   * passed in using the --client-id command-line argument. The request will be
   * ignored if the client id was not provided when server was started.
   *
   * Parameters
   *
   * event: String
   *
   *   The name of the event.
   *
   * millis: int
   *
   *   The duration of the event in milliseconds.
   */
  Future sendAnalyticsSendTiming(String event, int millis) async {
    var params = new AnalyticsSendTimingParams(event, millis).toJson();
    var result = await server.send("analytics.sendTiming", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Return the list of KytheEntry objects for some file, given the current
   * state of the file system populated by "analysis.updateContent".
   *
   * If a request is made for a file that does not exist, or that is not
   * currently subject to analysis (e.g. because it is not associated with any
   * analysis root specified to analysis.setAnalysisRoots), an error of type
   * GET_KYTHE_ENTRIES_INVALID_FILE will be generated.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the code for which the Kythe Entry objects are being
   *   requested.
   *
   * Returns
   *
   * entries: List<KytheEntry>
   *
   *   The list of KytheEntry objects for the queried file.
   *
   * files: List<FilePath>
   *
   *   The set of files paths that were required, but not in the file system,
   *   to give a complete and accurate Kythe graph for the file. This could be
   *   due to a referenced file that does not exist or generated files not
   *   being generated or passed before the call to "getKytheEntries".
   */
  Future<KytheGetKytheEntriesResult> sendKytheGetKytheEntries(
      String file) async {
    var params = new KytheGetKytheEntriesParams(file).toJson();
    var result = await server.send("kythe.getKytheEntries", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new KytheGetKytheEntriesResult.fromJson(decoder, 'result', result);
  }

  /**
   * Return the change that adds the forDesignTime() constructor for the widget
   * class at the given offset.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file containing the code of the class.
   *
   * offset: int
   *
   *   The offset of the class in the code.
   *
   * Returns
   *
   * change: SourceChange
   *
   *   The change that adds the forDesignTime() constructor. If the change
   *   cannot be produced, an error is returned.
   */
  Future<FlutterGetChangeAddForDesignTimeConstructorResult>
      sendFlutterGetChangeAddForDesignTimeConstructor(
          String file, int offset) async {
    var params =
        new FlutterGetChangeAddForDesignTimeConstructorParams(file, offset)
            .toJson();
    var result = await server.send(
        "flutter.getChangeAddForDesignTimeConstructor", params);
    ResponseDecoder decoder = new ResponseDecoder(null);
    return new FlutterGetChangeAddForDesignTimeConstructorResult.fromJson(
        decoder, 'result', result);
  }

  /**
   * Subscribe for services that are specific to individual files. All previous
   * subscriptions are replaced by the current set of subscriptions. If a given
   * service is not included as a key in the map then no files will be
   * subscribed to the service, exactly as if the service had been included in
   * the map with an explicit empty list of files.
   *
   * Note that this request determines the set of requested subscriptions. The
   * actual set of subscriptions at any given time is the intersection of this
   * set with the set of files currently subject to analysis. The files
   * currently subject to analysis are the set of files contained within an
   * actual analysis root but not excluded, plus all of the files transitively
   * reachable from those files via import, export and part directives. (See
   * analysis.setAnalysisRoots for an explanation of how the actual analysis
   * roots are determined.) When the actual analysis roots change, the actual
   * set of subscriptions is automatically updated, but the set of requested
   * subscriptions is unchanged.
   *
   * If a requested subscription is a directory it is ignored, but remains in
   * the set of requested subscriptions so that if it later becomes a file it
   * can be included in the set of actual subscriptions.
   *
   * It is an error if any of the keys in the map are not valid services. If
   * there is an error, then the existing subscriptions will remain unchanged.
   *
   * Parameters
   *
   * subscriptions: Map<FlutterService, List<FilePath>>
   *
   *   A table mapping services to a list of the files being subscribed to the
   *   service.
   */
  Future sendFlutterSetSubscriptions(
      Map<FlutterService, List<String>> subscriptions) async {
    var params = new FlutterSetSubscriptionsParams(subscriptions).toJson();
    var result = await server.send("flutter.setSubscriptions", params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /**
   * Reports the Flutter outline associated with a single file.
   *
   * This notification is not subscribed to by default. Clients can subscribe
   * by including the value "OUTLINE" in the list of services passed in an
   * flutter.setSubscriptions request.
   *
   * Parameters
   *
   * file: FilePath
   *
   *   The file with which the outline is associated.
   *
   * outline: FlutterOutline
   *
   *   The outline associated with the file.
   *
   * instrumentedCode: String (optional)
   *
   *   If the file has Flutter widgets that can be rendered, this field has the
   *   instrumented content of the file, that allows associating widgets with
   *   corresponding outline nodes. If there are no widgets to render, this
   *   field is absent.
   */
  Stream<FlutterOutlineParams> onFlutterOutline;

  /**
   * Stream controller for [onFlutterOutline].
   */
  StreamController<FlutterOutlineParams> _onFlutterOutline;

  /**
   * Initialize the fields in InttestMixin, and ensure that notifications will
   * be handled.
   */
  void initializeInttestMixin() {
    _onServerConnected =
        new StreamController<ServerConnectedParams>(sync: true);
    onServerConnected = _onServerConnected.stream.asBroadcastStream();
    _onServerError = new StreamController<ServerErrorParams>(sync: true);
    onServerError = _onServerError.stream.asBroadcastStream();
    _onServerStatus = new StreamController<ServerStatusParams>(sync: true);
    onServerStatus = _onServerStatus.stream.asBroadcastStream();
    _onAnalysisAnalyzedFiles =
        new StreamController<AnalysisAnalyzedFilesParams>(sync: true);
    onAnalysisAnalyzedFiles =
        _onAnalysisAnalyzedFiles.stream.asBroadcastStream();
    _onAnalysisClosingLabels =
        new StreamController<AnalysisClosingLabelsParams>(sync: true);
    onAnalysisClosingLabels =
        _onAnalysisClosingLabels.stream.asBroadcastStream();
    _onAnalysisErrors = new StreamController<AnalysisErrorsParams>(sync: true);
    onAnalysisErrors = _onAnalysisErrors.stream.asBroadcastStream();
    _onAnalysisFlushResults =
        new StreamController<AnalysisFlushResultsParams>(sync: true);
    onAnalysisFlushResults = _onAnalysisFlushResults.stream.asBroadcastStream();
    _onAnalysisFolding =
        new StreamController<AnalysisFoldingParams>(sync: true);
    onAnalysisFolding = _onAnalysisFolding.stream.asBroadcastStream();
    _onAnalysisHighlights =
        new StreamController<AnalysisHighlightsParams>(sync: true);
    onAnalysisHighlights = _onAnalysisHighlights.stream.asBroadcastStream();
    _onAnalysisImplemented =
        new StreamController<AnalysisImplementedParams>(sync: true);
    onAnalysisImplemented = _onAnalysisImplemented.stream.asBroadcastStream();
    _onAnalysisInvalidate =
        new StreamController<AnalysisInvalidateParams>(sync: true);
    onAnalysisInvalidate = _onAnalysisInvalidate.stream.asBroadcastStream();
    _onAnalysisNavigation =
        new StreamController<AnalysisNavigationParams>(sync: true);
    onAnalysisNavigation = _onAnalysisNavigation.stream.asBroadcastStream();
    _onAnalysisOccurrences =
        new StreamController<AnalysisOccurrencesParams>(sync: true);
    onAnalysisOccurrences = _onAnalysisOccurrences.stream.asBroadcastStream();
    _onAnalysisOutline =
        new StreamController<AnalysisOutlineParams>(sync: true);
    onAnalysisOutline = _onAnalysisOutline.stream.asBroadcastStream();
    _onAnalysisOverrides =
        new StreamController<AnalysisOverridesParams>(sync: true);
    onAnalysisOverrides = _onAnalysisOverrides.stream.asBroadcastStream();
    _onCompletionResults =
        new StreamController<CompletionResultsParams>(sync: true);
    onCompletionResults = _onCompletionResults.stream.asBroadcastStream();
    _onSearchResults = new StreamController<SearchResultsParams>(sync: true);
    onSearchResults = _onSearchResults.stream.asBroadcastStream();
    _onExecutionLaunchData =
        new StreamController<ExecutionLaunchDataParams>(sync: true);
    onExecutionLaunchData = _onExecutionLaunchData.stream.asBroadcastStream();
    _onFlutterOutline = new StreamController<FlutterOutlineParams>(sync: true);
    onFlutterOutline = _onFlutterOutline.stream.asBroadcastStream();
  }

  /**
   * Dispatch the notification named [event], and containing parameters
   * [params], to the appropriate stream.
   */
  void dispatchNotification(String event, params) {
    ResponseDecoder decoder = new ResponseDecoder(null);
    switch (event) {
      case "server.connected":
        outOfTestExpect(params, isServerConnectedParams);
        _onServerConnected
            .add(new ServerConnectedParams.fromJson(decoder, 'params', params));
        break;
      case "server.error":
        outOfTestExpect(params, isServerErrorParams);
        _onServerError
            .add(new ServerErrorParams.fromJson(decoder, 'params', params));
        break;
      case "server.status":
        outOfTestExpect(params, isServerStatusParams);
        _onServerStatus
            .add(new ServerStatusParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.analyzedFiles":
        outOfTestExpect(params, isAnalysisAnalyzedFilesParams);
        _onAnalysisAnalyzedFiles.add(new AnalysisAnalyzedFilesParams.fromJson(
            decoder, 'params', params));
        break;
      case "analysis.closingLabels":
        outOfTestExpect(params, isAnalysisClosingLabelsParams);
        _onAnalysisClosingLabels.add(new AnalysisClosingLabelsParams.fromJson(
            decoder, 'params', params));
        break;
      case "analysis.errors":
        outOfTestExpect(params, isAnalysisErrorsParams);
        _onAnalysisErrors
            .add(new AnalysisErrorsParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.flushResults":
        outOfTestExpect(params, isAnalysisFlushResultsParams);
        _onAnalysisFlushResults.add(
            new AnalysisFlushResultsParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.folding":
        outOfTestExpect(params, isAnalysisFoldingParams);
        _onAnalysisFolding
            .add(new AnalysisFoldingParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.highlights":
        outOfTestExpect(params, isAnalysisHighlightsParams);
        _onAnalysisHighlights.add(
            new AnalysisHighlightsParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.implemented":
        outOfTestExpect(params, isAnalysisImplementedParams);
        _onAnalysisImplemented.add(
            new AnalysisImplementedParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.invalidate":
        outOfTestExpect(params, isAnalysisInvalidateParams);
        _onAnalysisInvalidate.add(
            new AnalysisInvalidateParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.navigation":
        outOfTestExpect(params, isAnalysisNavigationParams);
        _onAnalysisNavigation.add(
            new AnalysisNavigationParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.occurrences":
        outOfTestExpect(params, isAnalysisOccurrencesParams);
        _onAnalysisOccurrences.add(
            new AnalysisOccurrencesParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.outline":
        outOfTestExpect(params, isAnalysisOutlineParams);
        _onAnalysisOutline
            .add(new AnalysisOutlineParams.fromJson(decoder, 'params', params));
        break;
      case "analysis.overrides":
        outOfTestExpect(params, isAnalysisOverridesParams);
        _onAnalysisOverrides.add(
            new AnalysisOverridesParams.fromJson(decoder, 'params', params));
        break;
      case "completion.results":
        outOfTestExpect(params, isCompletionResultsParams);
        _onCompletionResults.add(
            new CompletionResultsParams.fromJson(decoder, 'params', params));
        break;
      case "search.results":
        outOfTestExpect(params, isSearchResultsParams);
        _onSearchResults
            .add(new SearchResultsParams.fromJson(decoder, 'params', params));
        break;
      case "execution.launchData":
        outOfTestExpect(params, isExecutionLaunchDataParams);
        _onExecutionLaunchData.add(
            new ExecutionLaunchDataParams.fromJson(decoder, 'params', params));
        break;
      case "flutter.outline":
        outOfTestExpect(params, isFlutterOutlineParams);
        _onFlutterOutline
            .add(new FlutterOutlineParams.fromJson(decoder, 'params', params));
        break;
      default:
        fail('Unexpected notification: $event');
        break;
    }
  }
}
