// 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);
    var decoder = ResponseDecoder(null);
    return 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 = ServerSetSubscriptionsParams(subscriptions).toJson();
    var result = await server.send('server.setSubscriptions', params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /// Requests cancellation of a request sent by the client by id. This is
  /// provided on a best-effort basis and there is no guarantee the server will
  /// be able to cancel any specific request. The server will still always
  /// produce a response to the request even in the case of cancellation, but
  /// clients should discard any results of any cancelled request because they
  /// may be incomplete or inaccurate. This request always completes without
  /// error regardless of whether the request is successfully cancelled.
  ///
  /// Parameters
  ///
  /// id: String
  ///
  ///   The id of the request that should be cancelled.
  Future sendServerCancelRequest(String id) async {
    var params = ServerCancelRequestParams(id).toJson();
    var result = await server.send('server.cancelRequest', 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.
  late Stream<ServerConnectedParams> onServerConnected;

  /// Stream controller for [onServerConnected].
  late 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.
  late Stream<ServerErrorParams> onServerError;

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

  /// The stream of entries describing events happened in the server.
  ///
  /// Parameters
  ///
  /// entry: ServerLogEntry
  late Stream<ServerLogParams> onServerLog;

  /// Stream controller for [onServerLog].
  late StreamController<ServerLogParams> _onServerLog;

  /// 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.
  late Stream<ServerStatusParams> onServerStatus;

  /// Stream controller for [onServerStatus].
  late 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 = AnalysisGetErrorsParams(file).toJson();
    var result = await server.send('analysis.getErrors', params);
    var decoder = ResponseDecoder(null);
    return 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 = AnalysisGetHoverParams(file, offset).toJson();
    var result = await server.send('analysis.getHover', params);
    var decoder = ResponseDecoder(null);
    return 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 =
        AnalysisGetImportedElementsParams(file, offset, length).toJson();
    var result = await server.send('analysis.getImportedElements', params);
    var decoder = ResponseDecoder(null);
    return 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);
    var decoder = ResponseDecoder(null);
    return 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 = AnalysisGetNavigationParams(file, offset, length).toJson();
    var result = await server.send('analysis.getNavigation', params);
    var decoder = ResponseDecoder(null);
    return 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 = AnalysisGetReachableSourcesParams(file).toJson();
    var result = await server.send('analysis.getReachableSources', params);
    var decoder = ResponseDecoder(null);
    return 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 = AnalysisGetSignatureParams(file, offset).toJson();
    var result = await server.send('analysis.getSignature', params);
    var decoder = ResponseDecoder(null);
    return AnalysisGetSignatureResult.fromJson(decoder, 'result', result);
  }

  /// Force re-reading of all potentially changed files, re-resolving of all
  /// referenced URIs, and corresponding re-analysis of everything affected in
  /// the current analysis roots.
  Future sendAnalysisReanalyze() async {
    var result = await server.send('analysis.reanalyze', null);
    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 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 = 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 = 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 = 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 = 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, Object> files) async {
    var params = AnalysisUpdateContentParams(files).toJson();
    var result = await server.send('analysis.updateContent', params);
    var decoder = ResponseDecoder(null);
    return 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 = 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.
  late Stream<AnalysisAnalyzedFilesParams> onAnalysisAnalyzedFiles;

  /// Stream controller for [onAnalysisAnalyzedFiles].
  late 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.
  late Stream<AnalysisClosingLabelsParams> onAnalysisClosingLabels;

  /// Stream controller for [onAnalysisClosingLabels].
  late 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.
  late Stream<AnalysisErrorsParams> onAnalysisErrors;

  /// Stream controller for [onAnalysisErrors].
  late 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.
  late Stream<AnalysisFlushResultsParams> onAnalysisFlushResults;

  /// Stream controller for [onAnalysisFlushResults].
  late 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.
  late Stream<AnalysisFoldingParams> onAnalysisFolding;

  /// Stream controller for [onAnalysisFolding].
  late 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.
  late Stream<AnalysisHighlightsParams> onAnalysisHighlights;

  /// Stream controller for [onAnalysisHighlights].
  late 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.
  late Stream<AnalysisImplementedParams> onAnalysisImplemented;

  /// Stream controller for [onAnalysisImplemented].
  late 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.
  late Stream<AnalysisInvalidateParams> onAnalysisInvalidate;

  /// Stream controller for [onAnalysisInvalidate].
  late 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.
  late Stream<AnalysisNavigationParams> onAnalysisNavigation;

  /// Stream controller for [onAnalysisNavigation].
  late 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.
  late Stream<AnalysisOccurrencesParams> onAnalysisOccurrences;

  /// Stream controller for [onAnalysisOccurrences].
  late 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.
  late Stream<AnalysisOutlineParams> onAnalysisOutline;

  /// Stream controller for [onAnalysisOutline].
  late 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.
  late Stream<AnalysisOverridesParams> onAnalysisOverrides;

  /// Stream controller for [onAnalysisOverrides].
  late 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 = CompletionGetSuggestionsParams(file, offset).toJson();
    var result = await server.send('completion.getSuggestions', params);
    var decoder = ResponseDecoder(null);
    return CompletionGetSuggestionsResult.fromJson(decoder, 'result', result);
  }

  /// Request that completion suggestions for the given offset in the given
  /// file be returned. The suggestions will be filtered using fuzzy matching
  /// with the already existing prefix.
  ///
  /// 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.
  ///
  /// maxResults: int
  ///
  ///   The maximum number of suggestions to return. If the number of
  ///   suggestions after filtering is greater than the maxResults, then
  ///   isIncomplete is set to true.
  ///
  /// Returns
  ///
  /// replacementOffset: int
  ///
  ///   The offset of the start of the text to be replaced. This will be
  ///   different from 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).
  ///
  /// suggestions: List<CompletionSuggestion>
  ///
  ///   The completion suggestions being reported. This list is filtered by the
  ///   already existing prefix, and sorted first by relevance, and (if the
  ///   same) by the suggestion text. The list will have at most maxResults
  ///   items. If the user types a new keystroke, the client is expected to
  ///   either do local filtering (when the returned list was complete), or ask
  ///   the server again (if isIncomplete was true).
  ///
  ///   This list contains suggestions from both imported, and not yet imported
  ///   libraries. Items from not yet imported libraries will have
  ///   libraryUriToImportIndex set, which is an index into the
  ///   libraryUrisToImport in this response.
  ///
  /// libraryUrisToImport: List<String>
  ///
  ///   The list of libraries with declarations that are not yet available in
  ///   the file where completion was requested, most often because the library
  ///   is not yet imported. The declarations still might be included into the
  ///   suggestions, and the client should use getSuggestionDetails2 on
  ///   selection to make the library available in the file.
  ///
  ///   Each item is the URI of a library, such as package:foo/bar.dart or
  ///   file:///home/me/workspace/foo/test/bar_test.dart.
  ///
  /// isIncomplete: bool
  ///
  ///   True if the number of suggestions after filtering was greater than the
  ///   requested maxResults.
  Future<CompletionGetSuggestions2Result> sendCompletionGetSuggestions2(
      String file, int offset, int maxResults,
      {int? timeout}) async {
    var params = CompletionGetSuggestions2Params(file, offset, maxResults,
            timeout: timeout)
        .toJson();
    var result = await server.send('completion.getSuggestions2', params);
    var decoder = ResponseDecoder(null);
    return CompletionGetSuggestions2Result.fromJson(decoder, 'result', result);
  }

  /// Subscribe for completion 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<CompletionService>
  ///
  ///   A list of the services being subscribed to.
  Future sendCompletionSetSubscriptions(
      List<CompletionService> subscriptions) async {
    var params = CompletionSetSubscriptionsParams(subscriptions).toJson();
    var result = await server.send('completion.setSubscriptions', params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /// The client can make this request to express interest in certain libraries
  /// to receive completion suggestions from based on the client path. If this
  /// request is received before the client has used
  /// 'completion.setSubscriptions' to subscribe to the
  /// AVAILABLE_SUGGESTION_SETS service, then an error of type
  /// NOT_SUBSCRIBED_TO_AVAILABLE_SUGGESTION_SETS will be generated. All
  /// previous paths are replaced by the given set of paths.
  ///
  /// Parameters
  ///
  /// paths: List<LibraryPathSet>
  ///
  ///   A list of objects each containing a path and the additional libraries
  ///   from which the client is interested in receiving completion
  ///   suggestions. If one configured path is beneath another, the descendent
  ///   will override the ancestors' configured libraries of interest.
  @deprecated
  Future sendCompletionRegisterLibraryPaths(List<LibraryPathSet> paths) async {
    var params = CompletionRegisterLibraryPathsParams(paths).toJson();
    var result = await server.send('completion.registerLibraryPaths', params);
    outOfTestExpect(result, isNull);
    return null;
  }

  /// Clients must make this request when the user has selected a completion
  /// suggestion from an AvailableSuggestionSet. Analysis server will respond
  /// with the text to insert as well as any SourceChange that needs to be
  /// applied in case the completion requires an additional import to be added.
  /// It is an error if the id is no longer valid, for instance if the library
  /// has been removed after the completion suggestion is accepted.
  ///
  /// Parameters
  ///
  /// file: FilePath
  ///
  ///   The path of the file into which this completion is being inserted.
  ///
  /// id: int
  ///
  ///   The identifier of the AvailableSuggestionSet containing the selected
  ///   label.
  ///
  /// label: String
  ///
  ///   The label from the AvailableSuggestionSet with the `id` for which
  ///   insertion information is requested.
  ///
  /// offset: int
  ///
  ///   The offset in the file where the completion will be inserted.
  ///
  /// Returns
  ///
  /// completion: String
  ///
  ///   The full text to insert, including any optional import prefix.
  ///
  /// change: SourceChange (optional)
  ///
  ///   A change for the client to apply in case the library containing the
  ///   accepted completion suggestion needs to be imported. The field will be
  ///   omitted if there are no additional changes that need to be made.
  Future<CompletionGetSuggestionDetailsResult>
      sendCompletionGetSuggestionDetails(
          String file, int id, String label, int offset) async {
    var params =
        CompletionGetSuggestionDetailsParams(file, id, label, offset).toJson();
    var result = await server.send('completion.getSuggestionDetails', params);
    var decoder = ResponseDecoder(null);
    return CompletionGetSuggestionDetailsResult.fromJson(
        decoder, 'result', result);
  }

  /// Clients must make this request when the user has selected a completion
  /// suggestion with the libraryUriToImportIndex field set. The server will
  /// respond with the text to insert, as well as any SourceChange that needs
  /// to be applied in case the completion requires an additional import to be
  /// added. The text to insert might be different from the original suggestion
  /// to include an import prefix if the library will be imported with a prefix
  /// to avoid shadowing conflicts in the file.
  ///
  /// Parameters
  ///
  /// file: FilePath
  ///
  ///   The path of the file into which this completion is being inserted.
  ///
  /// offset: int
  ///
  ///   The offset in the file where the completion will be inserted.
  ///
  /// completion: String
  ///
  ///   The completion from the selected CompletionSuggestion. It could be a
  ///   name of a class, or a name of a constructor in form
  ///   "typeName.constructorName()", or an enumeration constant in form
  ///   "enumName.constantName", etc.
  ///
  /// libraryUri: String
  ///
  ///   The URI of the library to import, so that the element referenced in the
  ///   completion becomes accessible.
  ///
  /// Returns
  ///
  /// completion: String
  ///
  ///   The full text to insert, which possibly includes now an import prefix.
  ///   The client should insert this text, not the completion from the
  ///   selected CompletionSuggestion.
  ///
  /// change: SourceChange
  ///
  ///   A change for the client to apply to make the accepted completion
  ///   suggestion available. In most cases the change is to add a new import
  ///   directive to the file.
  Future<CompletionGetSuggestionDetails2Result>
      sendCompletionGetSuggestionDetails2(
          String file, int offset, String completion, String libraryUri) async {
    var params = CompletionGetSuggestionDetails2Params(
            file, offset, completion, libraryUri)
        .toJson();
    var result = await server.send('completion.getSuggestionDetails2', params);
    var decoder = ResponseDecoder(null);
    return CompletionGetSuggestionDetails2Result.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.
  ///
  /// libraryFile: FilePath (optional)
  ///
  ///   The library file that contains the file where completion was requested.
  ///   The client might use it for example together with the existingImports
  ///   notification to filter out available suggestions. If there were changes
  ///   to existing imports in the library, the corresponding existingImports
  ///   notification will be sent before the completion notification.
  ///
  /// includedSuggestionSets: List<IncludedSuggestionSet> (optional)
  ///
  ///   References to AvailableSuggestionSet objects previously sent to the
  ///   client. The client can include applicable names from the referenced
  ///   library in code completion suggestions.
  ///
  /// includedElementKinds: List<ElementKind> (optional)
  ///
  ///   The client is expected to check this list against the ElementKind sent
  ///   in IncludedSuggestionSet to decide whether or not these symbols should
  ///   should be presented to the user.
  ///
  /// includedSuggestionRelevanceTags: List<IncludedSuggestionRelevanceTag>
  /// (optional)
  ///
  ///   The client is expected to check this list against the values of the
  ///   field relevanceTags of AvailableSuggestion to decide if the suggestion
  ///   should be given a different relevance than the IncludedSuggestionSet
  ///   that contains it. This might be used for example to give higher
  ///   relevance to suggestions of matching types.
  ///
  ///   If an AvailableSuggestion has relevance tags that match more than one
  ///   IncludedSuggestionRelevanceTag, the maximum relevance boost is used.
  late Stream<CompletionResultsParams> onCompletionResults;

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

  /// Reports the pre-computed, candidate completions from symbols defined in a
  /// corresponding library. This notification may be sent multiple times. When
  /// a notification is processed, clients should replace any previous
  /// information about the libraries in the list of changedLibraries, discard
  /// any information about the libraries in the list of removedLibraries, and
  /// preserve any previously received information about any libraries that are
  /// not included in either list.
  ///
  /// Parameters
  ///
  /// changedLibraries: List<AvailableSuggestionSet> (optional)
  ///
  ///   A list of pre-computed, potential completions coming from this set of
  ///   completion suggestions.
  ///
  /// removedLibraries: List<int> (optional)
  ///
  ///   A list of library ids that no longer apply.
  late Stream<CompletionAvailableSuggestionsParams>
      onCompletionAvailableSuggestions;

  /// Stream controller for [onCompletionAvailableSuggestions].
  late StreamController<CompletionAvailableSuggestionsParams>
      _onCompletionAvailableSuggestions;

  /// Reports existing imports in a library. This notification may be sent
  /// multiple times for a library. When a notification is processed, clients
  /// should replace any previous information for the library.
  ///
  /// Parameters
  ///
  /// file: FilePath
  ///
  ///   The defining file of the library.
  ///
  /// imports: ExistingImports
  ///
  ///   The existing imports in the library.
  late Stream<CompletionExistingImportsParams> onCompletionExistingImports;

  /// Stream controller for [onCompletionExistingImports].
  late StreamController<CompletionExistingImportsParams>
      _onCompletionExistingImports;

  /// 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 =
        SearchFindElementReferencesParams(file, offset, includePotential)
            .toJson();
    var result = await server.send('search.findElementReferences', params);
    var decoder = ResponseDecoder(null);
    return 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 = SearchFindMemberDeclarationsParams(name).toJson();
    var result = await server.send('search.findMemberDeclarations', params);
    var decoder = ResponseDecoder(null);
    return 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 = SearchFindMemberReferencesParams(name).toJson();
    var result = await server.send('search.findMemberReferences', params);
    var decoder = ResponseDecoder(null);
    return 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 = SearchFindTopLevelDeclarationsParams(pattern).toJson();
    var result = await server.send('search.findTopLevelDeclarations', params);
    var decoder = ResponseDecoder(null);
    return 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 = SearchGetElementDeclarationsParams(
            file: file, pattern: pattern, maxResults: maxResults)
        .toJson();
    var result = await server.send('search.getElementDeclarations', params);
    var decoder = ResponseDecoder(null);
    return 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 =
        SearchGetTypeHierarchyParams(file, offset, superOnly: superOnly)
            .toJson();
    var result = await server.send('search.getTypeHierarchy', params);
    var decoder = ResponseDecoder(null);
    return 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.
  late Stream<SearchResultsParams> onSearchResults;

  /// Stream controller for [onSearchResults].
  late 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 = EditFormatParams(file, selectionOffset, selectionLength,
            lineLength: lineLength)
        .toJson();
    var result = await server.send('edit.format', params);
    var decoder = ResponseDecoder(null);
    return 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 = EditGetAssistsParams(file, offset, length).toJson();
    var result = await server.send('edit.getAssists', params);
    var decoder = ResponseDecoder(null);
    return 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 =
        EditGetAvailableRefactoringsParams(file, offset, length).toJson();
    var result = await server.send('edit.getAvailableRefactorings', params);
    var decoder = ResponseDecoder(null);
    return EditGetAvailableRefactoringsResult.fromJson(
        decoder, 'result', result);
  }

  /// Analyze the specified sources for fixes that can be applied in bulk 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.
  ///
  /// inTestMode: bool (optional)
  ///
  ///   A flag indicating whether the bulk fixes are being run in test mode.
  ///   The only difference is that in test mode the fix processor will look
  ///   for a configuration file that can modify the content of the data file
  ///   used to compute the fixes when data-driven fixes are being considered.
  ///
  ///   If this field is omitted the flag defaults to false.
  ///
  /// Returns
  ///
  /// edits: List<SourceFileEdit>
  ///
  ///   A list of source edits to apply the recommended changes.
  ///
  /// details: List<BulkFix>
  ///
  ///   Details that summarize the fixes associated with the recommended
  ///   changes.
  Future<EditBulkFixesResult> sendEditBulkFixes(List<String> included,
      {bool? inTestMode}) async {
    var params = EditBulkFixesParams(included, inTestMode: inTestMode).toJson();
    var result = await server.send('edit.bulkFixes', params);
    var decoder = ResponseDecoder(null);
    return EditBulkFixesResult.fromJson(decoder, 'result', result);
  }

  /// Return the set of fixes that are available for the errors at a given
  /// offset in 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_FIXES_INVALID_FILE will be generated.
  ///
  /// 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 = EditGetFixesParams(file, offset).toJson();
    var result = await server.send('edit.getFixes', params);
    var decoder = ResponseDecoder(null);
    return 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 = EditGetPostfixCompletionParams(file, key, offset).toJson();
    var result = await server.send('edit.getPostfixCompletion', params);
    var decoder = ResponseDecoder(null);
    return 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 = EditGetRefactoringParams(
            kind, file, offset, length, validateOnly,
            options: options)
        .toJson();
    var result = await server.send('edit.getRefactoring', params);
    var decoder = ResponseDecoder(kind);
    return 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 = EditGetStatementCompletionParams(file, offset).toJson();
    var result = await server.send('edit.getStatementCompletion', params);
    var decoder = ResponseDecoder(null);
    return 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 =
        EditIsPostfixCompletionApplicableParams(file, key, offset).toJson();
    var result =
        await server.send('edit.isPostfixCompletionApplicable', params);
    var decoder = ResponseDecoder(null);
    return 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);
    var decoder = ResponseDecoder(null);
    return 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.
  ///
  /// offset: int (optional)
  ///
  ///   The offset at which the specified elements need to be made accessible.
  ///   If provided, this is used to guard against adding imports for text that
  ///   would be inserted into a comment, string literal, or other location
  ///   where the imports would not be necessary.
  ///
  /// 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,
      {int? offset}) async {
    var params =
        EditImportElementsParams(file, elements, offset: offset).toJson();
    var result = await server.send('edit.importElements', params);
    var decoder = ResponseDecoder(null);
    return 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 = EditSortMembersParams(file).toJson();
    var result = await server.send('edit.sortMembers', params);
    var decoder = ResponseDecoder(null);
    return 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 = EditOrganizeDirectivesParams(file).toJson();
    var result = await server.send('edit.organizeDirectives', params);
    var decoder = ResponseDecoder(null);
    return 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 = ExecutionCreateContextParams(contextRoot).toJson();
    var result = await server.send('execution.createContext', params);
    var decoder = ResponseDecoder(null);
    return 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 = 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 = ExecutionGetSuggestionsParams(
            code, offset, contextFile, contextOffset, variables,
            expressions: expressions)
        .toJson();
    var result = await server.send('execution.getSuggestions', params);
    var decoder = ResponseDecoder(null);
    return 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 = ExecutionMapUriParams(id, file: file, uri: uri).toJson();
    var result = await server.send('execution.mapUri', params);
    var decoder = ResponseDecoder(null);
    return 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 = 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.
  late Stream<ExecutionLaunchDataParams> onExecutionLaunchData;

  /// Stream controller for [onExecutionLaunchData].
  late 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);
    var decoder = ResponseDecoder(null);
    return 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);
    var decoder = ResponseDecoder(null);
    return 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);
    var decoder = ResponseDecoder(null);
    return 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 = 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 = 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 = 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 = KytheGetKytheEntriesParams(file).toJson();
    var result = await server.send('kythe.getKytheEntries', params);
    var decoder = ResponseDecoder(null);
    return KytheGetKytheEntriesResult.fromJson(decoder, 'result', result);
  }

  /// Return the description of the widget instance at the given location.
  ///
  /// If the location does not have a support widget, an error of type
  /// FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET will be generated.
  ///
  /// If a change to a file happens while widget descriptions are computed, an
  /// error of type FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED will be
  /// generated.
  ///
  /// Parameters
  ///
  /// file: FilePath
  ///
  ///   The file where the widget instance is created.
  ///
  /// offset: int
  ///
  ///   The offset in the file where the widget instance is created.
  ///
  /// Returns
  ///
  /// properties: List<FlutterWidgetProperty>
  ///
  ///   The list of properties of the widget. Some of the properties might be
  ///   read only, when their editor is not set. This might be because they
  ///   have type that we don't know how to edit, or for compound properties
  ///   that work as containers for sub-properties.
  Future<FlutterGetWidgetDescriptionResult> sendFlutterGetWidgetDescription(
      String file, int offset) async {
    var params = FlutterGetWidgetDescriptionParams(file, offset).toJson();
    var result = await server.send('flutter.getWidgetDescription', params);
    var decoder = ResponseDecoder(null);
    return FlutterGetWidgetDescriptionResult.fromJson(
        decoder, 'result', result);
  }

  /// Set the value of a property, or remove it.
  ///
  /// The server will generate a change that the client should apply to the
  /// project to get the value of the property set to the new value. The
  /// complexity of the change might be from updating a single literal value in
  /// the code, to updating multiple files to get libraries imported, and new
  /// intermediate widgets instantiated.
  ///
  /// Parameters
  ///
  /// id: int
  ///
  ///   The identifier of the property, previously returned as a part of a
  ///   FlutterWidgetProperty.
  ///
  ///   An error of type FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID is
  ///   generated if the identifier is not valid.
  ///
  /// value: FlutterWidgetPropertyValue (optional)
  ///
  ///   The new value to set for the property.
  ///
  ///   If absent, indicates that the property should be removed. If the
  ///   property corresponds to an optional parameter, the corresponding named
  ///   argument is removed. If the property isRequired is true,
  ///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED error is generated.
  ///
  ///   If the expression is not a syntactically valid Dart code, then
  ///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION is reported.
  ///
  /// Returns
  ///
  /// change: SourceChange
  ///
  ///   The change that should be applied.
  Future<FlutterSetWidgetPropertyValueResult> sendFlutterSetWidgetPropertyValue(
      int id,
      {FlutterWidgetPropertyValue? value}) async {
    var params = FlutterSetWidgetPropertyValueParams(id, value: value).toJson();
    var result = await server.send('flutter.setWidgetPropertyValue', params);
    var decoder = ResponseDecoder(null);
    return FlutterSetWidgetPropertyValueResult.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 = 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.
  late Stream<FlutterOutlineParams> onFlutterOutline;

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

  /// Initialize the fields in InttestMixin, and ensure that notifications will
  /// be handled.
  void initializeInttestMixin() {
    _onServerConnected = StreamController<ServerConnectedParams>(sync: true);
    onServerConnected = _onServerConnected.stream.asBroadcastStream();
    _onServerError = StreamController<ServerErrorParams>(sync: true);
    onServerError = _onServerError.stream.asBroadcastStream();
    _onServerLog = StreamController<ServerLogParams>(sync: true);
    onServerLog = _onServerLog.stream.asBroadcastStream();
    _onServerStatus = StreamController<ServerStatusParams>(sync: true);
    onServerStatus = _onServerStatus.stream.asBroadcastStream();
    _onAnalysisAnalyzedFiles =
        StreamController<AnalysisAnalyzedFilesParams>(sync: true);
    onAnalysisAnalyzedFiles =
        _onAnalysisAnalyzedFiles.stream.asBroadcastStream();
    _onAnalysisClosingLabels =
        StreamController<AnalysisClosingLabelsParams>(sync: true);
    onAnalysisClosingLabels =
        _onAnalysisClosingLabels.stream.asBroadcastStream();
    _onAnalysisErrors = StreamController<AnalysisErrorsParams>(sync: true);
    onAnalysisErrors = _onAnalysisErrors.stream.asBroadcastStream();
    _onAnalysisFlushResults =
        StreamController<AnalysisFlushResultsParams>(sync: true);
    onAnalysisFlushResults = _onAnalysisFlushResults.stream.asBroadcastStream();
    _onAnalysisFolding = StreamController<AnalysisFoldingParams>(sync: true);
    onAnalysisFolding = _onAnalysisFolding.stream.asBroadcastStream();
    _onAnalysisHighlights =
        StreamController<AnalysisHighlightsParams>(sync: true);
    onAnalysisHighlights = _onAnalysisHighlights.stream.asBroadcastStream();
    _onAnalysisImplemented =
        StreamController<AnalysisImplementedParams>(sync: true);
    onAnalysisImplemented = _onAnalysisImplemented.stream.asBroadcastStream();
    _onAnalysisInvalidate =
        StreamController<AnalysisInvalidateParams>(sync: true);
    onAnalysisInvalidate = _onAnalysisInvalidate.stream.asBroadcastStream();
    _onAnalysisNavigation =
        StreamController<AnalysisNavigationParams>(sync: true);
    onAnalysisNavigation = _onAnalysisNavigation.stream.asBroadcastStream();
    _onAnalysisOccurrences =
        StreamController<AnalysisOccurrencesParams>(sync: true);
    onAnalysisOccurrences = _onAnalysisOccurrences.stream.asBroadcastStream();
    _onAnalysisOutline = StreamController<AnalysisOutlineParams>(sync: true);
    onAnalysisOutline = _onAnalysisOutline.stream.asBroadcastStream();
    _onAnalysisOverrides =
        StreamController<AnalysisOverridesParams>(sync: true);
    onAnalysisOverrides = _onAnalysisOverrides.stream.asBroadcastStream();
    _onCompletionResults =
        StreamController<CompletionResultsParams>(sync: true);
    onCompletionResults = _onCompletionResults.stream.asBroadcastStream();
    _onCompletionAvailableSuggestions =
        StreamController<CompletionAvailableSuggestionsParams>(sync: true);
    onCompletionAvailableSuggestions =
        _onCompletionAvailableSuggestions.stream.asBroadcastStream();
    _onCompletionExistingImports =
        StreamController<CompletionExistingImportsParams>(sync: true);
    onCompletionExistingImports =
        _onCompletionExistingImports.stream.asBroadcastStream();
    _onSearchResults = StreamController<SearchResultsParams>(sync: true);
    onSearchResults = _onSearchResults.stream.asBroadcastStream();
    _onExecutionLaunchData =
        StreamController<ExecutionLaunchDataParams>(sync: true);
    onExecutionLaunchData = _onExecutionLaunchData.stream.asBroadcastStream();
    _onFlutterOutline = 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) {
    var decoder = ResponseDecoder(null);
    switch (event) {
      case 'server.connected':
        outOfTestExpect(params, isServerConnectedParams);
        _onServerConnected
            .add(ServerConnectedParams.fromJson(decoder, 'params', params));
        break;
      case 'server.error':
        outOfTestExpect(params, isServerErrorParams);
        _onServerError
            .add(ServerErrorParams.fromJson(decoder, 'params', params));
        break;
      case 'server.log':
        outOfTestExpect(params, isServerLogParams);
        _onServerLog.add(ServerLogParams.fromJson(decoder, 'params', params));
        break;
      case 'server.status':
        outOfTestExpect(params, isServerStatusParams);
        _onServerStatus
            .add(ServerStatusParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.analyzedFiles':
        outOfTestExpect(params, isAnalysisAnalyzedFilesParams);
        _onAnalysisAnalyzedFiles.add(
            AnalysisAnalyzedFilesParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.closingLabels':
        outOfTestExpect(params, isAnalysisClosingLabelsParams);
        _onAnalysisClosingLabels.add(
            AnalysisClosingLabelsParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.errors':
        outOfTestExpect(params, isAnalysisErrorsParams);
        _onAnalysisErrors
            .add(AnalysisErrorsParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.flushResults':
        outOfTestExpect(params, isAnalysisFlushResultsParams);
        _onAnalysisFlushResults.add(
            AnalysisFlushResultsParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.folding':
        outOfTestExpect(params, isAnalysisFoldingParams);
        _onAnalysisFolding
            .add(AnalysisFoldingParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.highlights':
        outOfTestExpect(params, isAnalysisHighlightsParams);
        _onAnalysisHighlights
            .add(AnalysisHighlightsParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.implemented':
        outOfTestExpect(params, isAnalysisImplementedParams);
        _onAnalysisImplemented
            .add(AnalysisImplementedParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.invalidate':
        outOfTestExpect(params, isAnalysisInvalidateParams);
        _onAnalysisInvalidate
            .add(AnalysisInvalidateParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.navigation':
        outOfTestExpect(params, isAnalysisNavigationParams);
        _onAnalysisNavigation
            .add(AnalysisNavigationParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.occurrences':
        outOfTestExpect(params, isAnalysisOccurrencesParams);
        _onAnalysisOccurrences
            .add(AnalysisOccurrencesParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.outline':
        outOfTestExpect(params, isAnalysisOutlineParams);
        _onAnalysisOutline
            .add(AnalysisOutlineParams.fromJson(decoder, 'params', params));
        break;
      case 'analysis.overrides':
        outOfTestExpect(params, isAnalysisOverridesParams);
        _onAnalysisOverrides
            .add(AnalysisOverridesParams.fromJson(decoder, 'params', params));
        break;
      case 'completion.results':
        outOfTestExpect(params, isCompletionResultsParams);
        _onCompletionResults
            .add(CompletionResultsParams.fromJson(decoder, 'params', params));
        break;
      case 'completion.availableSuggestions':
        outOfTestExpect(params, isCompletionAvailableSuggestionsParams);
        _onCompletionAvailableSuggestions.add(
            CompletionAvailableSuggestionsParams.fromJson(
                decoder, 'params', params));
        break;
      case 'completion.existingImports':
        outOfTestExpect(params, isCompletionExistingImportsParams);
        _onCompletionExistingImports.add(
            CompletionExistingImportsParams.fromJson(
                decoder, 'params', params));
        break;
      case 'search.results':
        outOfTestExpect(params, isSearchResultsParams);
        _onSearchResults
            .add(SearchResultsParams.fromJson(decoder, 'params', params));
        break;
      case 'execution.launchData':
        outOfTestExpect(params, isExecutionLaunchDataParams);
        _onExecutionLaunchData
            .add(ExecutionLaunchDataParams.fromJson(decoder, 'params', params));
        break;
      case 'flutter.outline':
        outOfTestExpect(params, isFlutterOutlineParams);
        _onFlutterOutline
            .add(FlutterOutlineParams.fromJson(decoder, 'params', params));
        break;
      default:
        fail('Unexpected notification: $event');
    }
  }
}
