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

/// Support for interacting with an analysis server that is running in a
/// separate process.
import 'dart:async';
import 'dart:collection';
import 'dart:convert' hide JsonDecoder;
import 'dart:io';
import 'dart:math' as math;

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:path/path.dart' as path;

import 'logger.dart';

/// Return the current time expressed as milliseconds since the epoch.
int get currentTime => DateTime.now().millisecondsSinceEpoch;

/// ???
class ErrorMap {
  /// A table mapping file paths to the errors associated with that file.
  final Map<String, List<AnalysisError>> pathMap =
      HashMap<String, List<AnalysisError>>();

  /// Initialize a newly created error map.
  ErrorMap();

  /// Initialize a newly created error map to contain the same mapping as the
  /// given [errorMap].
  ErrorMap.from(ErrorMap errorMap) {
    pathMap.addAll(errorMap.pathMap);
  }

  void operator []=(String filePath, List<AnalysisError> errors) {
    pathMap[filePath] = errors;
  }
}

/// Data that has been collected about a request sent to the server.
class RequestData {
  /// The unique id of the request.
  final String id;

  /// The method that was requested.
  final String method;

  /// The request parameters, or `null` if there are no parameters.
  final Map<String, dynamic>? params;

  /// The time at which the request was sent.
  final int requestTime;

  /// The time at which the response was received, or `null` if no response has
  /// been received.
  int? responseTime;

  /// The response that was received.
  Response? _response;

  /// The completer that will be completed when a response is received.
  Completer<Response>? _responseCompleter;

  /// Initialize a newly created set of request data.
  RequestData(this.id, this.method, this.params, this.requestTime);

  /// Return the number of milliseconds that elapsed between the request and the
  /// response. This getter assumes that the response was received.
  int get elapsedTime => responseTime! - requestTime;

  /// Return a future that will complete when a response is received.
  Future<Response> get respondedTo {
    if (_response != null) {
      return Future.value(_response);
    }
    var completer = _responseCompleter ??= Completer<Response>();
    return completer.future;
  }

  /// Record that the given [response] was received.
  void recordResponse(Response response) {
    if (_response != null) {
      stdout.writeln(
          'Received a second response to a $method request (id = $id)');
      return;
    }
    responseTime = currentTime;
    _response = response;
    var completer = _responseCompleter;
    if (completer != null) {
      completer.complete(response);
      _responseCompleter = null;
    }
  }
}

/// A utility for starting and communicating with an analysis server that is
/// running in a separate process.
class Server {
  /// The label used for communications from the client.
  static const String fromClient = 'client';

  /// The label used for normal communications from the server.
  static const String fromServer = 'server';

  /// The label used for output written by the server on [fromStderr].
  static const String fromStderr = 'stderr';

  /// The logger to which the communications log should be written, or `null` if
  /// the log should not be written.
  final Logger? logger;

  /// The process in which the server is running, or `null` if the server hasn't
  /// been started yet.
  Process? _process;

  /// Number that should be used to compute the 'id' to send in the next command
  /// sent to the server.
  int _nextId = 0;

  /// The analysis roots that are included.
  List<String> _analysisRootIncludes = <String>[];

  /// A list containing the paths of files for which an overlay has been
  /// created.
  List<String> filesWithOverlays = <String>[];

  /// The files that the server reported as being analyzed.
  List<String> _analyzedFiles = <String>[];

  /// A mapping from the absolute paths of files to the most recent set of
  /// errors received for that file.
  final ErrorMap _errorMap = ErrorMap();

  /// The completer that will be completed the next time a 'server.status'
  /// notification is received from the server with 'analyzing' set to false.
  Completer<void>? _analysisFinishedCompleter;

  /// The completer that will be completed the next time a 'server.connected'
  /// notification is received from the server.
  Completer<void>? _serverConnectedCompleter;

  /// A table mapping the ids of requests that have been sent to the server to
  /// data about those requests.
  final Map<String, RequestData> _requestDataMap = <String, RequestData>{};

  /// A table mapping the number of times a request whose 'event' is equal to
  /// the key was sent to the server.
  final Map<String, int> _notificationCountMap = <String, int>{};

  /// Initialize a new analysis server. The analysis server is not running and
  /// must be started using [start].
  ///
  /// If a [logger] is provided, the communications between the client (this
  /// test) and the server will be written to it.
  Server({this.logger});

  /// Return a future that will complete when a 'server.status' notification is
  /// received from the server with 'analyzing' set to false.
  ///
  /// The future will only be completed by 'server.status' notifications that
  /// are received after this function call, so it is safe to use this getter
  /// multiple times in one test; each time it is used it will wait afresh for
  /// analysis to finish.
  Future get analysisFinished {
    var completer = _analysisFinishedCompleter ??= Completer<void>();
    return completer.future;
  }

  /// Return a list of the paths of files that are currently being analyzed.
  List<String> get analyzedDartFiles {
    bool isAnalyzed(String filePath) {
      // TODO(brianwilkerson) This should use the path package to determine
      // inclusion, and needs to take exclusions into account.
      for (var includedRoot in _analysisRootIncludes) {
        if (filePath.startsWith(includedRoot)) {
          return true;
        }
      }
      return false;
    }

    var analyzedFiles = <String>[];
    for (var filePath in _analyzedFiles) {
      if (filePath.endsWith('.dart') && isAnalyzed(filePath)) {
        analyzedFiles.add(filePath);
      }
    }
    return analyzedFiles;
  }

  /// Return a table mapping the absolute paths of files to the most recent set
  /// of errors received for that file. The content of the map will not change
  /// when new sets of errors are received.
  ErrorMap get errorMap => ErrorMap.from(_errorMap);

  /// Compute a mapping from each of the file paths in the given list of
  /// [filePaths] to the list of errors in the file at that path.
  Future<ErrorMap> computeErrorMap(List<String> filePaths) async {
    var errorMap = ErrorMap();
    var futures = <Future>[];
    for (var filePath in filePaths) {
      var requestData = sendAnalysisGetErrors(filePath);
      futures.add(requestData.respondedTo.then((Response response) {
        if (response.result != null) {
          var result = AnalysisGetErrorsResult.fromResponse(response);
          errorMap[filePath] = result.errors;
        }
      }));
    }
    await Future.wait(futures);
    return errorMap;
  }

  /// Print information about the communications with the server.
  void printStatistics() {
    void writeSpaces(int count) {
      for (var i = 0; i < count; i++) {
        stdout.write(' ');
      }
    }

    //
    // Print information about the requests that were sent.
    //
    stdout.writeln('Request Counts');
    if (_requestDataMap.isEmpty) {
      stdout.writeln('  none');
    } else {
      var requestsByMethod = <String, List<RequestData>>{};
      for (var requestData in _requestDataMap.values) {
        requestsByMethod
            .putIfAbsent(requestData.method, () => <RequestData>[])
            .add(requestData);
      }
      var keys = requestsByMethod.keys.toList();
      keys.sort();
      var maxCount = requestsByMethod.values
          .fold(0, (int count, List<RequestData> list) => count + list.length);
      var countWidth = maxCount.toString().length;
      for (var key in keys) {
        var requests = requestsByMethod[key]!;
        var noResponseCount = 0;
        var responseCount = 0;
        var minTime = -1;
        var maxTime = -1;
        var totalTime = 0;
        for (var data in requests) {
          if (data.responseTime == null) {
            noResponseCount++;
          } else {
            responseCount++;
            var time = data.elapsedTime;
            minTime = minTime < 0 ? time : math.min(minTime, time);
            maxTime = math.max(maxTime, time);
            totalTime += time;
          }
        }
        var count = requests.length.toString();
        writeSpaces(countWidth - count.length);
        stdout.write('  ');
        stdout.write(count);
        stdout.write(' - ');
        stdout.write(key);
        if (noResponseCount > 0) {
          stdout.write(', ');
          stdout.write(noResponseCount);
          stdout.write(' with no response');
        }
        if (maxTime >= 0) {
          stdout.write(' (');
          stdout.write(minTime);
          stdout.write(', ');
          stdout.write(totalTime / responseCount);
          stdout.write(', ');
          stdout.write(maxTime);
          stdout.write(')');
        }
        stdout.writeln();
      }
    }
    //
    // Print information about the notifications that were received.
    //
    stdout.writeln();
    stdout.writeln('Notification Counts');
    if (_notificationCountMap.isEmpty) {
      stdout.writeln('  none');
    } else {
      var keys = _notificationCountMap.keys.toList();
      keys.sort();
      var maxCount = _notificationCountMap.values.fold(0, math.max);
      var countWidth = maxCount.toString().length;
      for (var key in keys) {
        var count = _notificationCountMap[key].toString();
        writeSpaces(countWidth - count.length);
        stdout.write('  ');
        stdout.write(count);
        stdout.write(' - ');
        stdout.writeln(key);
      }
    }
  }

  /// Remove any existing overlays.
  void removeAllOverlays() {
    var files = <String, Object>{};
    for (var path in filesWithOverlays) {
      files[path] = RemoveContentOverlay();
    }
    sendAnalysisUpdateContent(files);
  }

  RequestData sendAnalysisGetErrors(String file) {
    var params = AnalysisGetErrorsParams(file).toJson();
    return _send('analysis.getErrors', params);
  }

  RequestData sendAnalysisGetHover(String file, int offset) {
    var params = AnalysisGetHoverParams(file, offset).toJson();
    return _send('analysis.getHover', params);
  }

  RequestData sendAnalysisGetLibraryDependencies() {
    return _send('analysis.getLibraryDependencies', null);
  }

  RequestData sendAnalysisGetNavigation(String file, int offset, int length) {
    var params = AnalysisGetNavigationParams(file, offset, length).toJson();
    return _send('analysis.getNavigation', params);
  }

  RequestData sendAnalysisGetReachableSources(String file) {
    var params = AnalysisGetReachableSourcesParams(file).toJson();
    return _send('analysis.getReachableSources', params);
  }

  void sendAnalysisReanalyze() {
    var params = AnalysisReanalyzeParams().toJson();
    _send('analysis.reanalyze', params);
  }

  void sendAnalysisSetAnalysisRoots(
      List<String> included, List<String> excluded,
      {Map<String, String>? packageRoots}) {
    _analysisRootIncludes = included;
    var params = AnalysisSetAnalysisRootsParams(included, excluded,
            packageRoots: packageRoots)
        .toJson();
    _send('analysis.setAnalysisRoots', params);
  }

  void sendAnalysisSetGeneralSubscriptions(
      List<GeneralAnalysisService> subscriptions) {
    var params = AnalysisSetGeneralSubscriptionsParams(subscriptions).toJson();
    _send('analysis.setGeneralSubscriptions', params);
  }

  void sendAnalysisSetPriorityFiles(List<String> files) {
    var params = AnalysisSetPriorityFilesParams(files).toJson();
    _send('analysis.setPriorityFiles', params);
  }

  void sendAnalysisSetSubscriptions(
      Map<AnalysisService, List<String>> subscriptions) {
    var params = AnalysisSetSubscriptionsParams(subscriptions).toJson();
    _send('analysis.setSubscriptions', params);
  }

  void sendAnalysisUpdateContent(Map<String, Object> files) {
    files.forEach((path, overlay) {
      if (overlay is AddContentOverlay) {
        filesWithOverlays.add(path);
      } else if (overlay is RemoveContentOverlay) {
        filesWithOverlays.remove(path);
      }
    });
    var params = AnalysisUpdateContentParams(files).toJson();
    _send('analysis.updateContent', params);
  }

  void sendAnalysisUpdateOptions(AnalysisOptions options) {
    var params = AnalysisUpdateOptionsParams(options).toJson();
    _send('analysis.updateOptions', params);
  }

  void sendCompletionGetSuggestions(String file, int offset) {
    var params = CompletionGetSuggestionsParams(file, offset).toJson();
    _send('completion.getSuggestions', params);
  }

  RequestData sendDiagnosticGetDiagnostics() {
    return _send('diagnostic.getDiagnostics', null);
  }

  RequestData sendEditFormat(
      String file, int selectionOffset, int selectionLength,
      {int? lineLength}) {
    var params = EditFormatParams(file, selectionOffset, selectionLength,
            lineLength: lineLength)
        .toJson();
    return _send('edit.format', params);
  }

  RequestData sendEditGetAssists(String file, int offset, int length) {
    var params = EditGetAssistsParams(file, offset, length).toJson();
    return _send('edit.getAssists', params);
  }

  RequestData sendEditGetAvailableRefactorings(
      String file, int offset, int length) {
    var params =
        EditGetAvailableRefactoringsParams(file, offset, length).toJson();
    return _send('edit.getAvailableRefactorings', params);
  }

  RequestData sendEditGetFixes(String file, int offset) {
    var params = EditGetFixesParams(file, offset).toJson();
    return _send('edit.getFixes', params);
  }

  RequestData sendEditGetRefactoring(RefactoringKind kind, String file,
      int offset, int length, bool validateOnly,
      {RefactoringOptions? options}) {
    var params = EditGetRefactoringParams(
            kind, file, offset, length, validateOnly,
            options: options)
        .toJson();
    return _send('edit.getRefactoring', params);
  }

  RequestData sendEditOrganizeDirectives(String file) {
    var params = EditOrganizeDirectivesParams(file).toJson();
    return _send('edit.organizeDirectives', params);
  }

  RequestData sendEditSortMembers(String file) {
    var params = EditSortMembersParams(file).toJson();
    return _send('edit.sortMembers', params);
  }

  RequestData sendExecutionCreateContext(String contextRoot) {
    var params = ExecutionCreateContextParams(contextRoot).toJson();
    return _send('execution.createContext', params);
  }

  RequestData sendExecutionDeleteContext(String id) {
    var params = ExecutionDeleteContextParams(id).toJson();
    return _send('execution.deleteContext', params);
  }

  RequestData sendExecutionMapUri(String id, {String? file, String? uri}) {
    var params = ExecutionMapUriParams(id, file: file, uri: uri).toJson();
    return _send('execution.mapUri', params);
  }

  RequestData sendExecutionSetSubscriptions(
      List<ExecutionService> subscriptions) {
    var params = ExecutionSetSubscriptionsParams(subscriptions).toJson();
    return _send('execution.setSubscriptions', params);
  }

  void sendSearchFindElementReferences(
      String file, int offset, bool includePotential) {
    var params =
        SearchFindElementReferencesParams(file, offset, includePotential)
            .toJson();
    _send('search.findElementReferences', params);
  }

  void sendSearchFindMemberDeclarations(String name) {
    var params = SearchFindMemberDeclarationsParams(name).toJson();
    _send('search.findMemberDeclarations', params);
  }

  void sendSearchFindMemberReferences(String name) {
    var params = SearchFindMemberReferencesParams(name).toJson();
    _send('search.findMemberReferences', params);
  }

  void sendSearchFindTopLevelDeclarations(String pattern) {
    var params = SearchFindTopLevelDeclarationsParams(pattern).toJson();
    _send('search.findTopLevelDeclarations', params);
  }

  void sendSearchGetTypeHierarchy(String file, int offset, {bool? superOnly}) {
    var params =
        SearchGetTypeHierarchyParams(file, offset, superOnly: superOnly)
            .toJson();
    _send('search.getTypeHierarchy', params);
  }

  RequestData sendServerGetVersion() {
    return _send('server.getVersion', null);
  }

  void sendServerSetSubscriptions(List<ServerService> subscriptions) {
    var params = ServerSetSubscriptionsParams(subscriptions).toJson();
    _send('server.setSubscriptions', params);
  }

  void sendServerShutdown() {
    _send('server.shutdown', null);
  }

  /// Start the server and listen for communications from it.
  ///
  /// If [checked] is `true`, the server's VM will be running in checked mode.
  ///
  /// If [diagnosticPort] is not `null`, the server will serve status pages to
  /// the specified port.
  ///
  /// If [profileServer] is `true`, the server will be started with "--observe"
  /// and "--pause-isolates-on-exit", allowing the observatory to be used.
  ///
  /// If [useAnalysisHighlight2] is `true`, the server will use the new
  /// highlight APIs.
  Future<void> start(
      {bool checked = true,
      int? diagnosticPort,
      bool profileServer = false,
      String? sdkPath,
      int? servicesPort,
      bool useAnalysisHighlight2 = false}) async {
    if (_process != null) {
      throw Exception('Process already started');
    }
    var dartBinary = Platform.executable;
    var rootDir =
        _findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
    var serverPath = path.normalize(path.join(rootDir, 'bin', 'server.dart'));
    var arguments = <String>[];
    //
    // Add VM arguments.
    //
    if (profileServer) {
      if (servicesPort == null) {
        arguments.add('--observe');
      } else {
        arguments.add('--observe=$servicesPort');
      }
      arguments.add('--pause-isolates-on-exit');
    } else if (servicesPort != null) {
      arguments.add('--enable-vm-service=$servicesPort');
    }
    if (Platform.packageConfig != null) {
      arguments.add('--packages=${Platform.packageConfig}');
    }
    if (checked) {
      arguments.add('--checked');
    }
    //
    // Add the server executable.
    //
    arguments.add(serverPath);
    //
    // Add server arguments.
    //
    if (diagnosticPort != null) {
      arguments.add('--port');
      arguments.add(diagnosticPort.toString());
    }
    if (sdkPath != null) {
      arguments.add('--sdk=$sdkPath');
    }
    if (useAnalysisHighlight2) {
      arguments.add('--useAnalysisHighlight2');
    }
//    stdout.writeln('Launching $serverPath');
//    stdout.writeln('$dartBinary ${arguments.join(' ')}');
    _process = await Process.start(dartBinary, arguments);
    _process!.exitCode.then((int code) {
      if (code != 0) {
        throw StateError('Server terminated with exit code $code');
      }
    });
    _listenToOutput();
    var completer = Completer<void>();
    _serverConnectedCompleter = completer;
    return completer.future;
  }

  /// Find the root directory of the analysis_server package by proceeding
  /// upward to the 'test' dir, and then going up one more directory.
  String _findRoot(String pathname) {
    while (!['benchmark', 'test'].contains(path.basename(pathname))) {
      var parent = path.dirname(pathname);
      if (parent.length >= pathname.length) {
        throw Exception("Can't find root directory");
      }
      pathname = parent;
    }
    return path.dirname(pathname);
  }

  /// Handle a [notification] received from the server.
  void _handleNotification(Notification notification) {
    switch (notification.event) {
      case 'server.connected':
//        new ServerConnectedParams.fromNotification(notification);
        _serverConnectedCompleter!.complete(null);
        break;
      case 'server.error':
//        new ServerErrorParams.fromNotification(notification);
        throw StateError('Server error: ${notification.toJson()}');
      case 'server.status':
        if (_analysisFinishedCompleter != null) {
          var params = ServerStatusParams.fromNotification(notification);
          var analysis = params.analysis;
          if (analysis != null && !analysis.isAnalyzing) {
            _analysisFinishedCompleter!.complete(null);
          }
        }
        break;
      case 'analysis.analyzedFiles':
        var params = AnalysisAnalyzedFilesParams.fromNotification(notification);
        _analyzedFiles = params.directories;
        break;
      case 'analysis.errors':
        var params = AnalysisErrorsParams.fromNotification(notification);
        _errorMap.pathMap[params.file] = params.errors;
        break;
      case 'analysis.flushResults':
//        new AnalysisFlushResultsParams.fromNotification(notification);
        _errorMap.pathMap.clear();
        break;
      case 'analysis.folding':
//        new AnalysisFoldingParams.fromNotification(notification);
        break;
      case 'analysis.highlights':
//        new AnalysisHighlightsParams.fromNotification(notification);
        break;
      case 'analysis.implemented':
//        new AnalysisImplementedParams.fromNotification(notification);
        break;
      case 'analysis.invalidate':
//        new AnalysisInvalidateParams.fromNotification(notification);
        break;
      case 'analysis.navigation':
//        new AnalysisNavigationParams.fromNotification(notification);
        break;
      case 'analysis.occurrences':
//        new AnalysisOccurrencesParams.fromNotification(notification);
        break;
      case 'analysis.outline':
//        new AnalysisOutlineParams.fromNotification(notification);
        break;
      case 'analysis.overrides':
//        new AnalysisOverridesParams.fromNotification(notification);
        break;
      case 'completion.results':
//        new CompletionResultsParams.fromNotification(notification);
        break;
      case 'search.results':
//        new SearchResultsParams.fromNotification(notification);
        break;
      case 'execution.launchData':
//        new ExecutionLaunchDataParams.fromNotification(notification);
        break;
      default:
        throw StateError('Unhandled notification: ${notification.toJson()}');
    }
  }

  /// Handle a [response] received from the server.
  void _handleResponse(Response response) {
    var id = response.id.toString();
    var requestData = _requestDataMap[id]!;
    requestData.recordResponse(response);
//    switch (requestData.method) {
//      case "analysis.getErrors":
//        break;
//      case "analysis.getHover":
//        break;
//      case "analysis.getLibraryDependencies":
//        break;
//      case "analysis.getNavigation":
//        break;
//      case "analysis.getReachableSources":
//        break;
//      case "analysis.reanalyze":
//        break;
//      case "analysis.setAnalysisRoots":
//        break;
//      case "analysis.setGeneralSubscriptions":
//        break;
//      case "analysis.setPriorityFiles":
//        break;
//      case "analysis.setSubscriptions":
//        break;
//      case 'analysis.updateContent':
//        break;
//      case "analysis.updateOptions":
//        break;
//      case "completion.getSuggestions":
//        break;
//      case "diagnostic.getDiagnostics":
//        break;
//      case "edit.format":
//        break;
//      case "edit.getAssists":
//        break;
//      case "edit.getAvailableRefactorings":
//        break;
//      case "edit.getFixes":
//        break;
//      case "edit.getRefactoring":
//        break;
//      case "edit.organizeDirectives":
//        break;
//      case "edit.sortMembers":
//        break;
//      case "execution.createContext":
//        break;
//      case "execution.deleteContext":
//        break;
//      case "execution.mapUri":
//        break;
//      case "execution.setSubscriptions":
//        break;
//      case "search.findElementReferences":
//        break;
//      case "search.findMemberDeclarations":
//        break;
//      case "search.findMemberReferences":
//        break;
//      case "search.findTopLevelDeclarations":
//        break;
//      case "search.getTypeHierarchy":
//        break;
//      case "server.getVersion":
//        break;
//      case "server.setSubscriptions":
//        break;
//      case "server.shutdown":
//        break;
//      default:
//        throw new StateError('Unhandled response: ${response.toJson()}');
//    }
  }

  /// Handle a [line] of input read from stderr.
  void _handleStdErr(String line) {
    var trimmedLine = line.trim();
    logger?.log(fromStderr, trimmedLine);
    throw StateError('Message received on stderr: "$trimmedLine"');
  }

  /// Handle a [line] of input read from stdout.
  void _handleStdOut(String line) {
    /// Cast the given [value] to a Map, or throw an [ArgumentError] if the
    /// value cannot be cast.
    Map<String, Object?> asMap(Object value) {
      if (value is Map<String, Object?>) {
        return value;
      }
      throw ArgumentError('Expected a Map, found a ${value.runtimeType}');
    }

    var trimmedLine = line.trim();
    if (trimmedLine.isEmpty ||
        trimmedLine.startsWith('The Dart VM service is listening on ')) {
      return;
    }
    logger?.log(fromServer, trimmedLine);
    var message = asMap(json.decoder.convert(trimmedLine) as Object);
    if (message.containsKey('id')) {
      // The message is a response.
      var response = Response.fromJson(message)!;
      _handleResponse(response);
    } else {
      // The message is a notification.
      var notification = Notification.fromJson(message);
      var event = notification.event;
      _notificationCountMap[event] = (_notificationCountMap[event] ?? 0) + 1;
      _handleNotification(notification);
    }
  }

  /// Start listening to output from the server.
  void _listenToOutput() {
    /// Install the given [handler] to listen to transformed output from the
    /// given [stream].
    void installHandler(
        Stream<List<int>> stream, void Function(String) handler) {
      stream
          .transform(Utf8Codec().decoder)
          .transform(LineSplitter())
          .listen(handler);
    }

    installHandler(_process!.stdout, _handleStdOut);
    installHandler(_process!.stderr, _handleStdErr);
  }

  /// Send a command to the server. An 'id' will be automatically assigned.
  RequestData _send(String method, Map<String, dynamic>? params) {
    var id = '${_nextId++}';
    var requestData = RequestData(id, method, params, currentTime);
    _requestDataMap[id] = requestData;
    var command = <String, dynamic>{'id': id, 'method': method};
    if (params != null) {
      command['params'] = params;
    }
    var line = json.encode(command);
    _process!.stdin.add(utf8.encoder.convert('$line\n'));
    logger?.log(fromClient, line);
    return requestData;
  }
}
