// 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".

import 'dart:convert' hide JsonDecoder;

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart';
import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';

/// analysis.analyzedFiles params
///
/// {
///   "directories": List<FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisAnalyzedFilesParams implements HasToJson {
  /// A list of the paths of the files that are being analyzed.
  List<String> directories;

  AnalysisAnalyzedFilesParams(this.directories);

  factory AnalysisAnalyzedFilesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> directories;
      if (json.containsKey('directories')) {
        directories = jsonDecoder.decodeList(
          '$jsonPath.directories',
          json['directories'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'directories');
      }
      return AnalysisAnalyzedFilesParams(directories);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.analyzedFiles params',
        json,
      );
    }
  }

  factory AnalysisAnalyzedFilesParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisAnalyzedFilesParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['directories'] =
        directories
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.analyzedFiles',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisAnalyzedFilesParams) {
      return listEqual(
        directories,
        other.directories,
        (String a, String b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(directories);
}

/// analysis.closingLabels params
///
/// {
///   "file": FilePath
///   "labels": List<ClosingLabel>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisClosingLabelsParams implements HasToJson {
  /// The file the closing labels relate to.
  String file;

  /// Closing labels relevant to the file. Each item represents a useful label
  /// associated with some range which 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.
  List<ClosingLabel> labels;

  AnalysisClosingLabelsParams(this.file, this.labels);

  factory AnalysisClosingLabelsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      List<ClosingLabel> labels;
      if (json.containsKey('labels')) {
        labels = jsonDecoder.decodeList(
          '$jsonPath.labels',
          json['labels'],
          (String jsonPath, Object? json) => ClosingLabel.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'labels');
      }
      return AnalysisClosingLabelsParams(file, labels);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.closingLabels params',
        json,
      );
    }
  }

  factory AnalysisClosingLabelsParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisClosingLabelsParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['labels'] =
        labels
            .map(
              (ClosingLabel value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.closingLabels',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisClosingLabelsParams) {
      return file == other.file &&
          listEqual(
            labels,
            other.labels,
            (ClosingLabel a, ClosingLabel b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, Object.hashAll(labels));
}

/// AnalysisErrorFixes
///
/// {
///   "error": AnalysisError
///   "fixes": List<SourceChange>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisErrorFixes implements HasToJson {
  /// The error with which the fixes are associated.
  AnalysisError error;

  /// The fixes associated with the error.
  List<SourceChange> fixes;

  AnalysisErrorFixes(this.error, {List<SourceChange>? fixes})
    : fixes = fixes ?? <SourceChange>[];

  factory AnalysisErrorFixes.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      AnalysisError error;
      if (json.containsKey('error')) {
        error = AnalysisError.fromJson(
          jsonDecoder,
          '$jsonPath.error',
          json['error'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'error');
      }
      List<SourceChange> fixes;
      if (json.containsKey('fixes')) {
        fixes = jsonDecoder.decodeList(
          '$jsonPath.fixes',
          json['fixes'],
          (String jsonPath, Object? json) => SourceChange.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'fixes');
      }
      return AnalysisErrorFixes(error, fixes: fixes);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'AnalysisErrorFixes', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['error'] = error.toJson(clientUriConverter: clientUriConverter);
    result['fixes'] =
        fixes
            .map(
              (SourceChange value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisErrorFixes) {
      return error == other.error &&
          listEqual(
            fixes,
            other.fixes,
            (SourceChange a, SourceChange b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(error, Object.hashAll(fixes));
}

/// analysis.errors params
///
/// {
///   "file": FilePath
///   "errors": List<AnalysisError>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisErrorsParams implements HasToJson {
  /// The file containing the errors.
  String file;

  /// The errors contained in the file.
  List<AnalysisError> errors;

  AnalysisErrorsParams(this.file, this.errors);

  factory AnalysisErrorsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      List<AnalysisError> errors;
      if (json.containsKey('errors')) {
        errors = jsonDecoder.decodeList(
          '$jsonPath.errors',
          json['errors'],
          (String jsonPath, Object? json) => AnalysisError.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'errors');
      }
      return AnalysisErrorsParams(file, errors);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.errors params', json);
    }
  }

  factory AnalysisErrorsParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisErrorsParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['errors'] =
        errors
            .map(
              (AnalysisError value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.errors',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisErrorsParams) {
      return file == other.file &&
          listEqual(
            errors,
            other.errors,
            (AnalysisError a, AnalysisError b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, Object.hashAll(errors));
}

/// analysis.flushResults params
///
/// {
///   "files": List<FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisFlushResultsParams implements HasToJson {
  /// The files that are no longer being analyzed.
  List<String> files;

  AnalysisFlushResultsParams(this.files);

  factory AnalysisFlushResultsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> files;
      if (json.containsKey('files')) {
        files = jsonDecoder.decodeList(
          '$jsonPath.files',
          json['files'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'files');
      }
      return AnalysisFlushResultsParams(files);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.flushResults params',
        json,
      );
    }
  }

  factory AnalysisFlushResultsParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisFlushResultsParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['files'] =
        files
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.flushResults',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisFlushResultsParams) {
      return listEqual(files, other.files, (String a, String b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(files);
}

/// analysis.folding params
///
/// {
///   "file": FilePath
///   "regions": List<FoldingRegion>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisFoldingParams implements HasToJson {
  /// The file containing the folding regions.
  String file;

  /// The folding regions contained in the file.
  List<FoldingRegion> regions;

  AnalysisFoldingParams(this.file, this.regions);

  factory AnalysisFoldingParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      List<FoldingRegion> regions;
      if (json.containsKey('regions')) {
        regions = jsonDecoder.decodeList(
          '$jsonPath.regions',
          json['regions'],
          (String jsonPath, Object? json) => FoldingRegion.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'regions');
      }
      return AnalysisFoldingParams(file, regions);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.folding params', json);
    }
  }

  factory AnalysisFoldingParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisFoldingParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['regions'] =
        regions
            .map(
              (FoldingRegion value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.folding',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisFoldingParams) {
      return file == other.file &&
          listEqual(
            regions,
            other.regions,
            (FoldingRegion a, FoldingRegion b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, Object.hashAll(regions));
}

/// analysis.getErrors params
///
/// {
///   "file": FilePath
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetErrorsParams implements RequestParams {
  /// The file for which errors are being requested.
  String file;

  AnalysisGetErrorsParams(this.file);

  factory AnalysisGetErrorsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      return AnalysisGetErrorsParams(file);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.getErrors params', json);
    }
  }

  factory AnalysisGetErrorsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetErrorsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.getErrors',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetErrorsParams) {
      return file == other.file;
    }
    return false;
  }

  @override
  int get hashCode => file.hashCode;
}

/// analysis.getErrors result
///
/// {
///   "errors": List<AnalysisError>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetErrorsResult implements ResponseResult {
  /// The errors associated with the file.
  List<AnalysisError> errors;

  AnalysisGetErrorsResult(this.errors);

  factory AnalysisGetErrorsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<AnalysisError> errors;
      if (json.containsKey('errors')) {
        errors = jsonDecoder.decodeList(
          '$jsonPath.errors',
          json['errors'],
          (String jsonPath, Object? json) => AnalysisError.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'errors');
      }
      return AnalysisGetErrorsResult(errors);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.getErrors result', json);
    }
  }

  factory AnalysisGetErrorsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetErrorsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['errors'] =
        errors
            .map(
              (AnalysisError value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetErrorsResult) {
      return listEqual(
        errors,
        other.errors,
        (AnalysisError a, AnalysisError b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(errors);
}

/// analysis.getHover params
///
/// {
///   "file": FilePath
///   "offset": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetHoverParams implements RequestParams {
  /// The file in which hover information is being requested.
  String file;

  /// The offset for which hover information is being requested.
  int offset;

  AnalysisGetHoverParams(this.file, this.offset);

  factory AnalysisGetHoverParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      return AnalysisGetHoverParams(file, offset);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.getHover params', json);
    }
  }

  factory AnalysisGetHoverParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetHoverParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.getHover',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetHoverParams) {
      return file == other.file && offset == other.offset;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset);
}

/// analysis.getHover result
///
/// {
///   "hovers": List<HoverInformation>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetHoverResult implements ResponseResult {
  /// 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).
  List<HoverInformation> hovers;

  AnalysisGetHoverResult(this.hovers);

  factory AnalysisGetHoverResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<HoverInformation> hovers;
      if (json.containsKey('hovers')) {
        hovers = jsonDecoder.decodeList(
          '$jsonPath.hovers',
          json['hovers'],
          (String jsonPath, Object? json) => HoverInformation.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'hovers');
      }
      return AnalysisGetHoverResult(hovers);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.getHover result', json);
    }
  }

  factory AnalysisGetHoverResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetHoverResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['hovers'] =
        hovers
            .map(
              (HoverInformation value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetHoverResult) {
      return listEqual(
        hovers,
        other.hovers,
        (HoverInformation a, HoverInformation b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(hovers);
}

/// analysis.getImportedElements params
///
/// {
///   "file": FilePath
///   "offset": int
///   "length": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetImportedElementsParams implements RequestParams {
  /// The file in which import information is being requested.
  String file;

  /// The offset of the region for which import information is being requested.
  int offset;

  /// The length of the region for which import information is being requested.
  int length;

  AnalysisGetImportedElementsParams(this.file, this.offset, this.length);

  factory AnalysisGetImportedElementsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      return AnalysisGetImportedElementsParams(file, offset, length);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.getImportedElements params',
        json,
      );
    }
  }

  factory AnalysisGetImportedElementsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetImportedElementsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    result['length'] = length;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.getImportedElements',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetImportedElementsParams) {
      return file == other.file &&
          offset == other.offset &&
          length == other.length;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset, length);
}

/// analysis.getImportedElements result
///
/// {
///   "elements": List<ImportedElements>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetImportedElementsResult implements ResponseResult {
  /// The information about the elements that are referenced in the specified
  /// region of the specified file that come from imported libraries.
  List<ImportedElements> elements;

  AnalysisGetImportedElementsResult(this.elements);

  factory AnalysisGetImportedElementsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<ImportedElements> elements;
      if (json.containsKey('elements')) {
        elements = jsonDecoder.decodeList(
          '$jsonPath.elements',
          json['elements'],
          (String jsonPath, Object? json) => ImportedElements.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'elements');
      }
      return AnalysisGetImportedElementsResult(elements);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.getImportedElements result',
        json,
      );
    }
  }

  factory AnalysisGetImportedElementsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetImportedElementsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['elements'] =
        elements
            .map(
              (ImportedElements value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetImportedElementsResult) {
      return listEqual(
        elements,
        other.elements,
        (ImportedElements a, ImportedElements b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(elements);
}

/// analysis.getLibraryDependencies params
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetLibraryDependenciesParams implements RequestParams {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(id, 'analysis.getLibraryDependencies');
  }

  @override
  bool operator ==(Object other) =>
      other is AnalysisGetLibraryDependenciesParams;

  @override
  int get hashCode => 246577680;
}

/// analysis.getLibraryDependencies result
///
/// {
///   "libraries": List<FilePath>
///   "packageMap": Map<String, Map<String, List<FilePath>>>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetLibraryDependenciesResult implements ResponseResult {
  /// A list of the paths of library elements referenced by files in existing
  /// analysis roots.
  List<String> libraries;

  /// A mapping from context source roots to package maps which map package
  /// names to source directories for use in client-side package URI
  /// resolution.
  Map<String, Map<String, List<String>>> packageMap;

  AnalysisGetLibraryDependenciesResult(this.libraries, this.packageMap);

  factory AnalysisGetLibraryDependenciesResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> libraries;
      if (json.containsKey('libraries')) {
        libraries = jsonDecoder.decodeList(
          '$jsonPath.libraries',
          json['libraries'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'libraries');
      }
      Map<String, Map<String, List<String>>> packageMap;
      if (json.containsKey('packageMap')) {
        packageMap = jsonDecoder.decodeMap(
          '$jsonPath.packageMap',
          json['packageMap'],
          valueDecoder:
              (String jsonPath, Object? json) => jsonDecoder.decodeMap(
                jsonPath,
                json,
                valueDecoder:
                    (String jsonPath, Object? json) => jsonDecoder.decodeList(
                      jsonPath,
                      json,
                      (String jsonPath, Object? json) =>
                          clientUriConverter?.fromClientFilePath(
                            jsonDecoder.decodeString(jsonPath, json),
                          ) ??
                          jsonDecoder.decodeString(jsonPath, json),
                    ),
              ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'packageMap');
      }
      return AnalysisGetLibraryDependenciesResult(libraries, packageMap);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.getLibraryDependencies result',
        json,
      );
    }
  }

  factory AnalysisGetLibraryDependenciesResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetLibraryDependenciesResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['libraries'] =
        libraries
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    result['packageMap'] = mapMap(
      packageMap,
      valueCallback:
          (Map<String, List<String>> value) => mapMap(
            value,
            valueCallback:
                (List<String> value) =>
                    value
                        .map(
                          (String value) =>
                              clientUriConverter?.toClientFilePath(value) ??
                              value,
                        )
                        .toList(),
          ),
    );
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetLibraryDependenciesResult) {
      return listEqual(
            libraries,
            other.libraries,
            (String a, String b) => a == b,
          ) &&
          mapEqual(
            packageMap,
            other.packageMap,
            (Map<String, List<String>> a, Map<String, List<String>> b) =>
                mapEqual(
                  a,
                  b,
                  (List<String> a, List<String> b) =>
                      listEqual(a, b, (String a, String b) => a == b),
                ),
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    Object.hashAll(libraries),
    Object.hashAll([...packageMap.keys, ...packageMap.values]),
  );
}

/// analysis.getNavigation params
///
/// {
///   "file": FilePath
///   "offset": int
///   "length": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetNavigationParams implements RequestParams {
  /// The file in which navigation information is being requested.
  String file;

  /// The offset of the region for which navigation information is being
  /// requested.
  int offset;

  /// The length of the region for which navigation information is being
  /// requested.
  int length;

  AnalysisGetNavigationParams(this.file, this.offset, this.length);

  factory AnalysisGetNavigationParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      return AnalysisGetNavigationParams(file, offset, length);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.getNavigation params',
        json,
      );
    }
  }

  factory AnalysisGetNavigationParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetNavigationParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    result['length'] = length;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.getNavigation',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetNavigationParams) {
      return file == other.file &&
          offset == other.offset &&
          length == other.length;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset, length);
}

/// analysis.getNavigation result
///
/// {
///   "files": List<FilePath>
///   "targets": List<NavigationTarget>
///   "regions": List<NavigationRegion>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetNavigationResult implements ResponseResult {
  /// A list of the paths of files that are referenced by the navigation
  /// targets.
  List<String> files;

  /// A list of the navigation targets that are referenced by the navigation
  /// regions.
  List<NavigationTarget> targets;

  /// A list of the navigation regions within the requested region of the file.
  List<NavigationRegion> regions;

  AnalysisGetNavigationResult(this.files, this.targets, this.regions);

  factory AnalysisGetNavigationResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> files;
      if (json.containsKey('files')) {
        files = jsonDecoder.decodeList(
          '$jsonPath.files',
          json['files'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'files');
      }
      List<NavigationTarget> targets;
      if (json.containsKey('targets')) {
        targets = jsonDecoder.decodeList(
          '$jsonPath.targets',
          json['targets'],
          (String jsonPath, Object? json) => NavigationTarget.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'targets');
      }
      List<NavigationRegion> regions;
      if (json.containsKey('regions')) {
        regions = jsonDecoder.decodeList(
          '$jsonPath.regions',
          json['regions'],
          (String jsonPath, Object? json) => NavigationRegion.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'regions');
      }
      return AnalysisGetNavigationResult(files, targets, regions);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.getNavigation result',
        json,
      );
    }
  }

  factory AnalysisGetNavigationResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetNavigationResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['files'] =
        files
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    result['targets'] =
        targets
            .map(
              (NavigationTarget value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['regions'] =
        regions
            .map(
              (NavigationRegion value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetNavigationResult) {
      return listEqual(files, other.files, (String a, String b) => a == b) &&
          listEqual(
            targets,
            other.targets,
            (NavigationTarget a, NavigationTarget b) => a == b,
          ) &&
          listEqual(
            regions,
            other.regions,
            (NavigationRegion a, NavigationRegion b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    Object.hashAll(files),
    Object.hashAll(targets),
    Object.hashAll(regions),
  );
}

/// analysis.getReachableSources params
///
/// {
///   "file": FilePath
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetReachableSourcesParams implements RequestParams {
  /// The file for which reachable source information is being requested.
  String file;

  AnalysisGetReachableSourcesParams(this.file);

  factory AnalysisGetReachableSourcesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      return AnalysisGetReachableSourcesParams(file);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.getReachableSources params',
        json,
      );
    }
  }

  factory AnalysisGetReachableSourcesParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetReachableSourcesParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.getReachableSources',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetReachableSourcesParams) {
      return file == other.file;
    }
    return false;
  }

  @override
  int get hashCode => file.hashCode;
}

/// analysis.getReachableSources result
///
/// {
///   "sources": Map<String, List<String>>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetReachableSourcesResult implements ResponseResult {
  /// 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.
  Map<String, List<String>> sources;

  AnalysisGetReachableSourcesResult(this.sources);

  factory AnalysisGetReachableSourcesResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Map<String, List<String>> sources;
      if (json.containsKey('sources')) {
        sources = jsonDecoder.decodeMap(
          '$jsonPath.sources',
          json['sources'],
          valueDecoder:
              (String jsonPath, Object? json) => jsonDecoder.decodeList(
                jsonPath,
                json,
                jsonDecoder.decodeString,
              ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'sources');
      }
      return AnalysisGetReachableSourcesResult(sources);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.getReachableSources result',
        json,
      );
    }
  }

  factory AnalysisGetReachableSourcesResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetReachableSourcesResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['sources'] = sources;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetReachableSourcesResult) {
      return mapEqual(
        sources,
        other.sources,
        (List<String> a, List<String> b) =>
            listEqual(a, b, (String a, String b) => a == b),
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll([...sources.keys, ...sources.values]);
}

/// analysis.getSignature params
///
/// {
///   "file": FilePath
///   "offset": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetSignatureParams implements RequestParams {
  /// The file in which signature information is being requested.
  String file;

  /// The location for which signature information is being requested.
  int offset;

  AnalysisGetSignatureParams(this.file, this.offset);

  factory AnalysisGetSignatureParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      return AnalysisGetSignatureParams(file, offset);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.getSignature params',
        json,
      );
    }
  }

  factory AnalysisGetSignatureParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetSignatureParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.getSignature',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetSignatureParams) {
      return file == other.file && offset == other.offset;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset);
}

/// analysis.getSignature result
///
/// {
///   "name": String
///   "parameters": List<ParameterInfo>
///   "dartdoc": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisGetSignatureResult implements ResponseResult {
  /// The name of the function being invoked at the given offset.
  String name;

  /// A list of information about each of the parameters of the function being
  /// invoked.
  List<ParameterInfo> parameters;

  /// 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.
  String? dartdoc;

  AnalysisGetSignatureResult(this.name, this.parameters, {this.dartdoc});

  factory AnalysisGetSignatureResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      List<ParameterInfo> parameters;
      if (json.containsKey('parameters')) {
        parameters = jsonDecoder.decodeList(
          '$jsonPath.parameters',
          json['parameters'],
          (String jsonPath, Object? json) => ParameterInfo.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'parameters');
      }
      String? dartdoc;
      if (json.containsKey('dartdoc')) {
        dartdoc = jsonDecoder.decodeString(
          '$jsonPath.dartdoc',
          json['dartdoc'],
        );
      }
      return AnalysisGetSignatureResult(name, parameters, dartdoc: dartdoc);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.getSignature result',
        json,
      );
    }
  }

  factory AnalysisGetSignatureResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisGetSignatureResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    result['parameters'] =
        parameters
            .map(
              (ParameterInfo value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    var dartdoc = this.dartdoc;
    if (dartdoc != null) {
      result['dartdoc'] = dartdoc;
    }
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisGetSignatureResult) {
      return name == other.name &&
          listEqual(
            parameters,
            other.parameters,
            (ParameterInfo a, ParameterInfo b) => a == b,
          ) &&
          dartdoc == other.dartdoc;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(name, Object.hashAll(parameters), dartdoc);
}

/// analysis.highlights params
///
/// {
///   "file": FilePath
///   "regions": List<HighlightRegion>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisHighlightsParams implements HasToJson {
  /// The file containing the highlight regions.
  String file;

  /// 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.
  List<HighlightRegion> regions;

  AnalysisHighlightsParams(this.file, this.regions);

  factory AnalysisHighlightsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      List<HighlightRegion> regions;
      if (json.containsKey('regions')) {
        regions = jsonDecoder.decodeList(
          '$jsonPath.regions',
          json['regions'],
          (String jsonPath, Object? json) => HighlightRegion.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'regions');
      }
      return AnalysisHighlightsParams(file, regions);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.highlights params', json);
    }
  }

  factory AnalysisHighlightsParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisHighlightsParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['regions'] =
        regions
            .map(
              (HighlightRegion value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.highlights',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisHighlightsParams) {
      return file == other.file &&
          listEqual(
            regions,
            other.regions,
            (HighlightRegion a, HighlightRegion b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, Object.hashAll(regions));
}

/// analysis.implemented params
///
/// {
///   "file": FilePath
///   "classes": List<ImplementedClass>
///   "members": List<ImplementedMember>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisImplementedParams implements HasToJson {
  /// The file with which the implementations are associated.
  String file;

  /// The classes defined in the file that are implemented or extended.
  List<ImplementedClass> classes;

  /// The members defined in the file that are implemented or overridden.
  List<ImplementedMember> members;

  AnalysisImplementedParams(this.file, this.classes, this.members);

  factory AnalysisImplementedParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      List<ImplementedClass> classes;
      if (json.containsKey('classes')) {
        classes = jsonDecoder.decodeList(
          '$jsonPath.classes',
          json['classes'],
          (String jsonPath, Object? json) => ImplementedClass.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'classes');
      }
      List<ImplementedMember> members;
      if (json.containsKey('members')) {
        members = jsonDecoder.decodeList(
          '$jsonPath.members',
          json['members'],
          (String jsonPath, Object? json) => ImplementedMember.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'members');
      }
      return AnalysisImplementedParams(file, classes, members);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.implemented params', json);
    }
  }

  factory AnalysisImplementedParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisImplementedParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['classes'] =
        classes
            .map(
              (ImplementedClass value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['members'] =
        members
            .map(
              (ImplementedMember value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.implemented',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisImplementedParams) {
      return file == other.file &&
          listEqual(
            classes,
            other.classes,
            (ImplementedClass a, ImplementedClass b) => a == b,
          ) &&
          listEqual(
            members,
            other.members,
            (ImplementedMember a, ImplementedMember b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(file, Object.hashAll(classes), Object.hashAll(members));
}

/// analysis.invalidate params
///
/// {
///   "file": FilePath
///   "offset": int
///   "length": int
///   "delta": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisInvalidateParams implements HasToJson {
  /// The file whose information has been invalidated.
  String file;

  /// The offset of the invalidated region.
  int offset;

  /// The length of the invalidated region.
  int length;

  /// 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.
  int delta;

  AnalysisInvalidateParams(this.file, this.offset, this.length, this.delta);

  factory AnalysisInvalidateParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      int delta;
      if (json.containsKey('delta')) {
        delta = jsonDecoder.decodeInt('$jsonPath.delta', json['delta']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'delta');
      }
      return AnalysisInvalidateParams(file, offset, length, delta);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.invalidate params', json);
    }
  }

  factory AnalysisInvalidateParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisInvalidateParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    result['length'] = length;
    result['delta'] = delta;
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.invalidate',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisInvalidateParams) {
      return file == other.file &&
          offset == other.offset &&
          length == other.length &&
          delta == other.delta;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset, length, delta);
}

/// analysis.navigation params
///
/// {
///   "file": FilePath
///   "regions": List<NavigationRegion>
///   "targets": List<NavigationTarget>
///   "files": List<FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisNavigationParams implements HasToJson {
  /// The file containing the navigation regions.
  String file;

  /// 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.
  List<NavigationRegion> regions;

  /// The navigation targets referenced in the file. They are referenced by
  /// `NavigationRegion`s by their index in this array.
  List<NavigationTarget> targets;

  /// The files containing navigation targets referenced in the file. They are
  /// referenced by `NavigationTarget`s by their index in this array.
  List<String> files;

  AnalysisNavigationParams(this.file, this.regions, this.targets, this.files);

  factory AnalysisNavigationParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      List<NavigationRegion> regions;
      if (json.containsKey('regions')) {
        regions = jsonDecoder.decodeList(
          '$jsonPath.regions',
          json['regions'],
          (String jsonPath, Object? json) => NavigationRegion.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'regions');
      }
      List<NavigationTarget> targets;
      if (json.containsKey('targets')) {
        targets = jsonDecoder.decodeList(
          '$jsonPath.targets',
          json['targets'],
          (String jsonPath, Object? json) => NavigationTarget.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'targets');
      }
      List<String> files;
      if (json.containsKey('files')) {
        files = jsonDecoder.decodeList(
          '$jsonPath.files',
          json['files'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'files');
      }
      return AnalysisNavigationParams(file, regions, targets, files);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.navigation params', json);
    }
  }

  factory AnalysisNavigationParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisNavigationParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['regions'] =
        regions
            .map(
              (NavigationRegion value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['targets'] =
        targets
            .map(
              (NavigationTarget value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['files'] =
        files
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.navigation',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisNavigationParams) {
      return file == other.file &&
          listEqual(
            regions,
            other.regions,
            (NavigationRegion a, NavigationRegion b) => a == b,
          ) &&
          listEqual(
            targets,
            other.targets,
            (NavigationTarget a, NavigationTarget b) => a == b,
          ) &&
          listEqual(files, other.files, (String a, String b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    file,
    Object.hashAll(regions),
    Object.hashAll(targets),
    Object.hashAll(files),
  );
}

/// analysis.occurrences params
///
/// {
///   "file": FilePath
///   "occurrences": List<Occurrences>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisOccurrencesParams implements HasToJson {
  /// The file in which the references occur.
  String file;

  /// The occurrences of references to elements within the file.
  List<Occurrences> occurrences;

  AnalysisOccurrencesParams(this.file, this.occurrences);

  factory AnalysisOccurrencesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      List<Occurrences> occurrences;
      if (json.containsKey('occurrences')) {
        occurrences = jsonDecoder.decodeList(
          '$jsonPath.occurrences',
          json['occurrences'],
          (String jsonPath, Object? json) => Occurrences.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'occurrences');
      }
      return AnalysisOccurrencesParams(file, occurrences);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.occurrences params', json);
    }
  }

  factory AnalysisOccurrencesParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisOccurrencesParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['occurrences'] =
        occurrences
            .map(
              (Occurrences value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.occurrences',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisOccurrencesParams) {
      return file == other.file &&
          listEqual(
            occurrences,
            other.occurrences,
            (Occurrences a, Occurrences b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, Object.hashAll(occurrences));
}

/// AnalysisOptions
///
/// {
///   "enableAsync": optional bool
///   "enableDeferredLoading": optional bool
///   "enableEnums": optional bool
///   "enableNullAwareOperators": optional bool
///   "generateDart2jsHints": optional bool
///   "generateHints": optional bool
///   "generateLints": optional bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisOptions implements HasToJson {
  /// Deprecated: this feature is always enabled.
  ///
  /// True if the client wants to enable support for the proposed async
  /// feature.
  bool? enableAsync;

  /// Deprecated: this feature is always enabled.
  ///
  /// True if the client wants to enable support for the proposed deferred
  /// loading feature.
  bool? enableDeferredLoading;

  /// Deprecated: this feature is always enabled.
  ///
  /// True if the client wants to enable support for the proposed enum feature.
  bool? enableEnums;

  /// Deprecated: this feature is always enabled.
  ///
  /// True if the client wants to enable support for the proposed "null aware
  /// operators" feature.
  bool? enableNullAwareOperators;

  /// True if hints that are specific to dart2js should be generated. This
  /// option is ignored if generateHints is false.
  bool? generateDart2jsHints;

  /// True if hints should be generated as part of generating errors and
  /// warnings.
  bool? generateHints;

  /// True if lints should be generated as part of generating errors and
  /// warnings.
  bool? generateLints;

  AnalysisOptions({
    this.enableAsync,
    this.enableDeferredLoading,
    this.enableEnums,
    this.enableNullAwareOperators,
    this.generateDart2jsHints,
    this.generateHints,
    this.generateLints,
  });

  factory AnalysisOptions.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      bool? enableAsync;
      if (json.containsKey('enableAsync')) {
        enableAsync = jsonDecoder.decodeBool(
          '$jsonPath.enableAsync',
          json['enableAsync'],
        );
      }
      bool? enableDeferredLoading;
      if (json.containsKey('enableDeferredLoading')) {
        enableDeferredLoading = jsonDecoder.decodeBool(
          '$jsonPath.enableDeferredLoading',
          json['enableDeferredLoading'],
        );
      }
      bool? enableEnums;
      if (json.containsKey('enableEnums')) {
        enableEnums = jsonDecoder.decodeBool(
          '$jsonPath.enableEnums',
          json['enableEnums'],
        );
      }
      bool? enableNullAwareOperators;
      if (json.containsKey('enableNullAwareOperators')) {
        enableNullAwareOperators = jsonDecoder.decodeBool(
          '$jsonPath.enableNullAwareOperators',
          json['enableNullAwareOperators'],
        );
      }
      bool? generateDart2jsHints;
      if (json.containsKey('generateDart2jsHints')) {
        generateDart2jsHints = jsonDecoder.decodeBool(
          '$jsonPath.generateDart2jsHints',
          json['generateDart2jsHints'],
        );
      }
      bool? generateHints;
      if (json.containsKey('generateHints')) {
        generateHints = jsonDecoder.decodeBool(
          '$jsonPath.generateHints',
          json['generateHints'],
        );
      }
      bool? generateLints;
      if (json.containsKey('generateLints')) {
        generateLints = jsonDecoder.decodeBool(
          '$jsonPath.generateLints',
          json['generateLints'],
        );
      }
      return AnalysisOptions(
        enableAsync: enableAsync,
        enableDeferredLoading: enableDeferredLoading,
        enableEnums: enableEnums,
        enableNullAwareOperators: enableNullAwareOperators,
        generateDart2jsHints: generateDart2jsHints,
        generateHints: generateHints,
        generateLints: generateLints,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'AnalysisOptions', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var enableAsync = this.enableAsync;
    if (enableAsync != null) {
      result['enableAsync'] = enableAsync;
    }
    var enableDeferredLoading = this.enableDeferredLoading;
    if (enableDeferredLoading != null) {
      result['enableDeferredLoading'] = enableDeferredLoading;
    }
    var enableEnums = this.enableEnums;
    if (enableEnums != null) {
      result['enableEnums'] = enableEnums;
    }
    var enableNullAwareOperators = this.enableNullAwareOperators;
    if (enableNullAwareOperators != null) {
      result['enableNullAwareOperators'] = enableNullAwareOperators;
    }
    var generateDart2jsHints = this.generateDart2jsHints;
    if (generateDart2jsHints != null) {
      result['generateDart2jsHints'] = generateDart2jsHints;
    }
    var generateHints = this.generateHints;
    if (generateHints != null) {
      result['generateHints'] = generateHints;
    }
    var generateLints = this.generateLints;
    if (generateLints != null) {
      result['generateLints'] = generateLints;
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisOptions) {
      return enableAsync == other.enableAsync &&
          enableDeferredLoading == other.enableDeferredLoading &&
          enableEnums == other.enableEnums &&
          enableNullAwareOperators == other.enableNullAwareOperators &&
          generateDart2jsHints == other.generateDart2jsHints &&
          generateHints == other.generateHints &&
          generateLints == other.generateLints;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    enableAsync,
    enableDeferredLoading,
    enableEnums,
    enableNullAwareOperators,
    generateDart2jsHints,
    generateHints,
    generateLints,
  );
}

/// analysis.outline params
///
/// {
///   "file": FilePath
///   "kind": FileKind
///   "libraryName": optional String
///   "outline": Outline
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisOutlineParams implements HasToJson {
  /// The file with which the outline is associated.
  String file;

  /// The kind of the file.
  FileKind kind;

  /// 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.
  String? libraryName;

  /// The outline associated with the file.
  Outline outline;

  AnalysisOutlineParams(this.file, this.kind, this.outline, {this.libraryName});

  factory AnalysisOutlineParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      FileKind kind;
      if (json.containsKey('kind')) {
        kind = FileKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kind');
      }
      String? libraryName;
      if (json.containsKey('libraryName')) {
        libraryName = jsonDecoder.decodeString(
          '$jsonPath.libraryName',
          json['libraryName'],
        );
      }
      Outline outline;
      if (json.containsKey('outline')) {
        outline = Outline.fromJson(
          jsonDecoder,
          '$jsonPath.outline',
          json['outline'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'outline');
      }
      return AnalysisOutlineParams(
        file,
        kind,
        outline,
        libraryName: libraryName,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.outline params', json);
    }
  }

  factory AnalysisOutlineParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisOutlineParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    var libraryName = this.libraryName;
    if (libraryName != null) {
      result['libraryName'] = libraryName;
    }
    result['outline'] = outline.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.outline',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisOutlineParams) {
      return file == other.file &&
          kind == other.kind &&
          libraryName == other.libraryName &&
          outline == other.outline;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, kind, libraryName, outline);
}

/// analysis.overrides params
///
/// {
///   "file": FilePath
///   "overrides": List<Override>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisOverridesParams implements HasToJson {
  /// The file with which the overrides are associated.
  String file;

  /// The overrides associated with the file.
  List<Override> overrides;

  AnalysisOverridesParams(this.file, this.overrides);

  factory AnalysisOverridesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      List<Override> overrides;
      if (json.containsKey('overrides')) {
        overrides = jsonDecoder.decodeList(
          '$jsonPath.overrides',
          json['overrides'],
          (String jsonPath, Object? json) => Override.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'overrides');
      }
      return AnalysisOverridesParams(file, overrides);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analysis.overrides params', json);
    }
  }

  factory AnalysisOverridesParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisOverridesParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['overrides'] =
        overrides
            .map(
              (Override value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'analysis.overrides',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisOverridesParams) {
      return file == other.file &&
          listEqual(
            overrides,
            other.overrides,
            (Override a, Override b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, Object.hashAll(overrides));
}

/// analysis.reanalyze params
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisReanalyzeParams implements RequestParams {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(id, 'analysis.reanalyze');
  }

  @override
  bool operator ==(Object other) => other is AnalysisReanalyzeParams;

  @override
  int get hashCode => 613039876;
}

/// analysis.reanalyze result
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisReanalyzeResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is AnalysisReanalyzeResult;

  @override
  int get hashCode => 846803925;
}

/// AnalysisService
///
/// enum {
///   CLOSING_LABELS
///   FOLDING
///   HIGHLIGHTS
///   IMPLEMENTED
///   INVALIDATE
///   NAVIGATION
///   OCCURRENCES
///   OUTLINE
///   OVERRIDES
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum AnalysisService {
  CLOSING_LABELS,

  FOLDING,

  HIGHLIGHTS,

  IMPLEMENTED,

  /// This service is not currently implemented and will become a
  /// GeneralAnalysisService in a future release.
  INVALIDATE,

  NAVIGATION,

  OCCURRENCES,

  OUTLINE,

  OVERRIDES;

  factory AnalysisService.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'AnalysisService', json);
  }

  @override
  String toString() => 'AnalysisService.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// analysis.setAnalysisRoots params
///
/// {
///   "included": List<FilePath>
///   "excluded": List<FilePath>
///   "packageRoots": optional Map<FilePath, FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisSetAnalysisRootsParams implements RequestParams {
  /// A list of the files and directories that should be analyzed.
  List<String> included;

  /// A list of the files and directories within the included directories that
  /// should not be analyzed.
  List<String> excluded;

  /// 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 ".dart_tool/package_config.json" 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.
  Map<String, String>? packageRoots;

  AnalysisSetAnalysisRootsParams(
    this.included,
    this.excluded, {
    this.packageRoots,
  });

  factory AnalysisSetAnalysisRootsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> included;
      if (json.containsKey('included')) {
        included = jsonDecoder.decodeList(
          '$jsonPath.included',
          json['included'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'included');
      }
      List<String> excluded;
      if (json.containsKey('excluded')) {
        excluded = jsonDecoder.decodeList(
          '$jsonPath.excluded',
          json['excluded'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'excluded');
      }
      Map<String, String>? packageRoots;
      if (json.containsKey('packageRoots')) {
        packageRoots = jsonDecoder.decodeMap(
          '$jsonPath.packageRoots',
          json['packageRoots'],
          keyDecoder:
              (String jsonPath, Object? json) =>
                  clientUriConverter?.fromClientFilePath(
                    jsonDecoder.decodeString(jsonPath, json),
                  ) ??
                  jsonDecoder.decodeString(jsonPath, json),
          valueDecoder:
              (String jsonPath, Object? json) =>
                  clientUriConverter?.fromClientFilePath(
                    jsonDecoder.decodeString(jsonPath, json),
                  ) ??
                  jsonDecoder.decodeString(jsonPath, json),
        );
      }
      return AnalysisSetAnalysisRootsParams(
        included,
        excluded,
        packageRoots: packageRoots,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.setAnalysisRoots params',
        json,
      );
    }
  }

  factory AnalysisSetAnalysisRootsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisSetAnalysisRootsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['included'] =
        included
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    result['excluded'] =
        excluded
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    var packageRoots = this.packageRoots;
    if (packageRoots != null) {
      result['packageRoots'] = mapMap(
        packageRoots,
        keyCallback:
            (String value) =>
                clientUriConverter?.toClientFilePath(value) ?? value,
        valueCallback:
            (String value) =>
                clientUriConverter?.toClientFilePath(value) ?? value,
      );
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.setAnalysisRoots',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisSetAnalysisRootsParams) {
      return listEqual(
            included,
            other.included,
            (String a, String b) => a == b,
          ) &&
          listEqual(excluded, other.excluded, (String a, String b) => a == b) &&
          mapEqual(
            packageRoots,
            other.packageRoots,
            (String a, String b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    Object.hashAll(included),
    Object.hashAll(excluded),
    Object.hashAll([...?packageRoots?.keys, ...?packageRoots?.values]),
  );
}

/// analysis.setAnalysisRoots result
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisSetAnalysisRootsResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is AnalysisSetAnalysisRootsResult;

  @override
  int get hashCode => 866004753;
}

/// analysis.setGeneralSubscriptions params
///
/// {
///   "subscriptions": List<GeneralAnalysisService>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisSetGeneralSubscriptionsParams implements RequestParams {
  /// A list of the services being subscribed to.
  List<GeneralAnalysisService> subscriptions;

  AnalysisSetGeneralSubscriptionsParams(this.subscriptions);

  factory AnalysisSetGeneralSubscriptionsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<GeneralAnalysisService> subscriptions;
      if (json.containsKey('subscriptions')) {
        subscriptions = jsonDecoder.decodeList(
          '$jsonPath.subscriptions',
          json['subscriptions'],
          (String jsonPath, Object? json) => GeneralAnalysisService.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'subscriptions');
      }
      return AnalysisSetGeneralSubscriptionsParams(subscriptions);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.setGeneralSubscriptions params',
        json,
      );
    }
  }

  factory AnalysisSetGeneralSubscriptionsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisSetGeneralSubscriptionsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['subscriptions'] =
        subscriptions
            .map(
              (GeneralAnalysisService value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.setGeneralSubscriptions',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisSetGeneralSubscriptionsParams) {
      return listEqual(
        subscriptions,
        other.subscriptions,
        (GeneralAnalysisService a, GeneralAnalysisService b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(subscriptions);
}

/// analysis.setGeneralSubscriptions result
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisSetGeneralSubscriptionsResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) =>
      other is AnalysisSetGeneralSubscriptionsResult;

  @override
  int get hashCode => 386759562;
}

/// analysis.setPriorityFiles params
///
/// {
///   "files": List<FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisSetPriorityFilesParams implements RequestParams {
  /// The files that are to be a priority for analysis.
  List<String> files;

  AnalysisSetPriorityFilesParams(this.files);

  factory AnalysisSetPriorityFilesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> files;
      if (json.containsKey('files')) {
        files = jsonDecoder.decodeList(
          '$jsonPath.files',
          json['files'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'files');
      }
      return AnalysisSetPriorityFilesParams(files);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.setPriorityFiles params',
        json,
      );
    }
  }

  factory AnalysisSetPriorityFilesParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisSetPriorityFilesParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['files'] =
        files
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.setPriorityFiles',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisSetPriorityFilesParams) {
      return listEqual(files, other.files, (String a, String b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(files);
}

/// analysis.setPriorityFiles result
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisSetPriorityFilesResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is AnalysisSetPriorityFilesResult;

  @override
  int get hashCode => 330050055;
}

/// analysis.setSubscriptions params
///
/// {
///   "subscriptions": Map<AnalysisService, List<FilePath>>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisSetSubscriptionsParams implements RequestParams {
  /// A table mapping services to a list of the files being subscribed to the
  /// service.
  Map<AnalysisService, List<String>> subscriptions;

  AnalysisSetSubscriptionsParams(this.subscriptions);

  factory AnalysisSetSubscriptionsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Map<AnalysisService, List<String>> subscriptions;
      if (json.containsKey('subscriptions')) {
        subscriptions = jsonDecoder.decodeMap(
          '$jsonPath.subscriptions',
          json['subscriptions'],
          keyDecoder:
              (String jsonPath, Object? json) => AnalysisService.fromJson(
                jsonDecoder,
                jsonPath,
                json,
                clientUriConverter: clientUriConverter,
              ),
          valueDecoder:
              (String jsonPath, Object? json) => jsonDecoder.decodeList(
                jsonPath,
                json,
                (String jsonPath, Object? json) =>
                    clientUriConverter?.fromClientFilePath(
                      jsonDecoder.decodeString(jsonPath, json),
                    ) ??
                    jsonDecoder.decodeString(jsonPath, json),
              ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'subscriptions');
      }
      return AnalysisSetSubscriptionsParams(subscriptions);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.setSubscriptions params',
        json,
      );
    }
  }

  factory AnalysisSetSubscriptionsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisSetSubscriptionsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['subscriptions'] = mapMap(
      subscriptions,
      keyCallback:
          (AnalysisService value) =>
              value.toJson(clientUriConverter: clientUriConverter),
      valueCallback:
          (List<String> value) =>
              value
                  .map(
                    (String value) =>
                        clientUriConverter?.toClientFilePath(value) ?? value,
                  )
                  .toList(),
    );
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.setSubscriptions',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisSetSubscriptionsParams) {
      return mapEqual(
        subscriptions,
        other.subscriptions,
        (List<String> a, List<String> b) =>
            listEqual(a, b, (String a, String b) => a == b),
      );
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hashAll([...subscriptions.keys, ...subscriptions.values]);
}

/// analysis.setSubscriptions result
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisSetSubscriptionsResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is AnalysisSetSubscriptionsResult;

  @override
  int get hashCode => 218088493;
}

/// AnalysisStatus
///
/// {
///   "isAnalyzing": bool
///   "analysisTarget": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisStatus implements HasToJson {
  /// True if analysis is currently being performed.
  bool isAnalyzing;

  /// The name of the current target of analysis. This field is omitted if
  /// analyzing is false.
  String? analysisTarget;

  AnalysisStatus(this.isAnalyzing, {this.analysisTarget});

  factory AnalysisStatus.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      bool isAnalyzing;
      if (json.containsKey('isAnalyzing')) {
        isAnalyzing = jsonDecoder.decodeBool(
          '$jsonPath.isAnalyzing',
          json['isAnalyzing'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'isAnalyzing');
      }
      String? analysisTarget;
      if (json.containsKey('analysisTarget')) {
        analysisTarget = jsonDecoder.decodeString(
          '$jsonPath.analysisTarget',
          json['analysisTarget'],
        );
      }
      return AnalysisStatus(isAnalyzing, analysisTarget: analysisTarget);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'AnalysisStatus', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['isAnalyzing'] = isAnalyzing;
    var analysisTarget = this.analysisTarget;
    if (analysisTarget != null) {
      result['analysisTarget'] = analysisTarget;
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisStatus) {
      return isAnalyzing == other.isAnalyzing &&
          analysisTarget == other.analysisTarget;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(isAnalyzing, analysisTarget);
}

/// analysis.updateContent params
///
/// {
///   "files": Map<FilePath, AddContentOverlay | ChangeContentOverlay | RemoveContentOverlay>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisUpdateContentParams implements RequestParams {
  /// A table mapping the files whose content has changed to a description of
  /// the content change.
  Map<String, Object> files;

  AnalysisUpdateContentParams(this.files);

  factory AnalysisUpdateContentParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Map<String, Object> files;
      if (json.containsKey('files')) {
        files = jsonDecoder.decodeMap(
          '$jsonPath.files',
          json['files'],
          keyDecoder:
              (String jsonPath, Object? json) =>
                  clientUriConverter?.fromClientFilePath(
                    jsonDecoder.decodeString(jsonPath, json),
                  ) ??
                  jsonDecoder.decodeString(jsonPath, json),
          valueDecoder:
              (String jsonPath, Object? json) =>
                  jsonDecoder.decodeUnion(jsonPath, json, 'type', {
                    'add':
                        (String jsonPath, Object? json) =>
                            AddContentOverlay.fromJson(
                              jsonDecoder,
                              jsonPath,
                              json,
                              clientUriConverter: clientUriConverter,
                            ),
                    'change':
                        (String jsonPath, Object? json) =>
                            ChangeContentOverlay.fromJson(
                              jsonDecoder,
                              jsonPath,
                              json,
                              clientUriConverter: clientUriConverter,
                            ),
                    'remove':
                        (String jsonPath, Object? json) =>
                            RemoveContentOverlay.fromJson(
                              jsonDecoder,
                              jsonPath,
                              json,
                              clientUriConverter: clientUriConverter,
                            ),
                  }),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'files');
      }
      return AnalysisUpdateContentParams(files);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.updateContent params',
        json,
      );
    }
  }

  factory AnalysisUpdateContentParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisUpdateContentParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['files'] = mapMap(
      files,
      keyCallback:
          (String value) =>
              clientUriConverter?.toClientFilePath(value) ?? value,
      valueCallback: (Object value) => (value as dynamic).toJson(),
    );
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.updateContent',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisUpdateContentParams) {
      return mapEqual(files, other.files, (Object a, Object b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll([...files.keys, ...files.values]);
}

/// analysis.updateContent result
///
/// {
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisUpdateContentResult implements ResponseResult {
  AnalysisUpdateContentResult();

  factory AnalysisUpdateContentResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      return AnalysisUpdateContentResult();
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.updateContent result',
        json,
      );
    }
  }

  factory AnalysisUpdateContentResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisUpdateContentResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisUpdateContentResult) {
      return true;
    }
    return false;
  }

  @override
  int get hashCode => 0;
}

/// analysis.updateOptions params
///
/// {
///   "options": AnalysisOptions
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisUpdateOptionsParams implements RequestParams {
  /// The options that are to be used to control analysis.
  AnalysisOptions options;

  AnalysisUpdateOptionsParams(this.options);

  factory AnalysisUpdateOptionsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      AnalysisOptions options;
      if (json.containsKey('options')) {
        options = AnalysisOptions.fromJson(
          jsonDecoder,
          '$jsonPath.options',
          json['options'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'options');
      }
      return AnalysisUpdateOptionsParams(options);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'analysis.updateOptions params',
        json,
      );
    }
  }

  factory AnalysisUpdateOptionsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalysisUpdateOptionsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['options'] = options.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analysis.updateOptions',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalysisUpdateOptionsParams) {
      return options == other.options;
    }
    return false;
  }

  @override
  int get hashCode => options.hashCode;
}

/// analysis.updateOptions result
///
/// Clients may not extend, implement or mix-in this class.
class AnalysisUpdateOptionsResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is AnalysisUpdateOptionsResult;

  @override
  int get hashCode => 179689467;
}

/// analytics.enable params
///
/// {
///   "value": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalyticsEnableParams implements RequestParams {
  /// Enable or disable analytics.
  bool value;

  AnalyticsEnableParams(this.value);

  factory AnalyticsEnableParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      bool value;
      if (json.containsKey('value')) {
        value = jsonDecoder.decodeBool('$jsonPath.value', json['value']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'value');
      }
      return AnalyticsEnableParams(value);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analytics.enable params', json);
    }
  }

  factory AnalyticsEnableParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalyticsEnableParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['value'] = value;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analytics.enable',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalyticsEnableParams) {
      return value == other.value;
    }
    return false;
  }

  @override
  int get hashCode => value.hashCode;
}

/// analytics.enable result
///
/// Clients may not extend, implement or mix-in this class.
class AnalyticsEnableResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is AnalyticsEnableResult;

  @override
  int get hashCode => 237990792;
}

/// analytics.isEnabled params
///
/// Clients may not extend, implement or mix-in this class.
class AnalyticsIsEnabledParams implements RequestParams {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(id, 'analytics.isEnabled');
  }

  @override
  bool operator ==(Object other) => other is AnalyticsIsEnabledParams;

  @override
  int get hashCode => 57215544;
}

/// analytics.isEnabled result
///
/// {
///   "enabled": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalyticsIsEnabledResult implements ResponseResult {
  /// Whether sending analytics is enabled or not.
  bool enabled;

  AnalyticsIsEnabledResult(this.enabled);

  factory AnalyticsIsEnabledResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      bool enabled;
      if (json.containsKey('enabled')) {
        enabled = jsonDecoder.decodeBool('$jsonPath.enabled', json['enabled']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'enabled');
      }
      return AnalyticsIsEnabledResult(enabled);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analytics.isEnabled result', json);
    }
  }

  factory AnalyticsIsEnabledResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalyticsIsEnabledResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['enabled'] = enabled;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalyticsIsEnabledResult) {
      return enabled == other.enabled;
    }
    return false;
  }

  @override
  int get hashCode => enabled.hashCode;
}

/// analytics.sendEvent params
///
/// {
///   "action": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalyticsSendEventParams implements RequestParams {
  /// The value used to indicate which action was performed.
  String action;

  AnalyticsSendEventParams(this.action);

  factory AnalyticsSendEventParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String action;
      if (json.containsKey('action')) {
        action = jsonDecoder.decodeString('$jsonPath.action', json['action']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'action');
      }
      return AnalyticsSendEventParams(action);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analytics.sendEvent params', json);
    }
  }

  factory AnalyticsSendEventParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalyticsSendEventParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['action'] = action;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analytics.sendEvent',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalyticsSendEventParams) {
      return action == other.action;
    }
    return false;
  }

  @override
  int get hashCode => action.hashCode;
}

/// analytics.sendEvent result
///
/// Clients may not extend, implement or mix-in this class.
class AnalyticsSendEventResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is AnalyticsSendEventResult;

  @override
  int get hashCode => 227063188;
}

/// analytics.sendTiming params
///
/// {
///   "event": String
///   "millis": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class AnalyticsSendTimingParams implements RequestParams {
  /// The name of the event.
  String event;

  /// The duration of the event in milliseconds.
  int millis;

  AnalyticsSendTimingParams(this.event, this.millis);

  factory AnalyticsSendTimingParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String event;
      if (json.containsKey('event')) {
        event = jsonDecoder.decodeString('$jsonPath.event', json['event']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'event');
      }
      int millis;
      if (json.containsKey('millis')) {
        millis = jsonDecoder.decodeInt('$jsonPath.millis', json['millis']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'millis');
      }
      return AnalyticsSendTimingParams(event, millis);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'analytics.sendTiming params', json);
    }
  }

  factory AnalyticsSendTimingParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return AnalyticsSendTimingParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['event'] = event;
    result['millis'] = millis;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'analytics.sendTiming',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is AnalyticsSendTimingParams) {
      return event == other.event && millis == other.millis;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(event, millis);
}

/// analytics.sendTiming result
///
/// Clients may not extend, implement or mix-in this class.
class AnalyticsSendTimingResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is AnalyticsSendTimingResult;

  @override
  int get hashCode => 875010924;
}

/// BulkFix
///
/// {
///   "path": FilePath
///   "fixes": List<BulkFixDetail>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class BulkFix implements HasToJson {
  /// The path of the library.
  String path;

  /// A list of bulk fix details.
  List<BulkFixDetail> fixes;

  BulkFix(this.path, this.fixes);

  factory BulkFix.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String path;
      if (json.containsKey('path')) {
        path =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.path', json['path']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.path', json['path']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'path');
      }
      List<BulkFixDetail> fixes;
      if (json.containsKey('fixes')) {
        fixes = jsonDecoder.decodeList(
          '$jsonPath.fixes',
          json['fixes'],
          (String jsonPath, Object? json) => BulkFixDetail.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'fixes');
      }
      return BulkFix(path, fixes);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'BulkFix', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['path'] = clientUriConverter?.toClientFilePath(path) ?? path;
    result['fixes'] =
        fixes
            .map(
              (BulkFixDetail value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is BulkFix) {
      return path == other.path &&
          listEqual(
            fixes,
            other.fixes,
            (BulkFixDetail a, BulkFixDetail b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(path, Object.hashAll(fixes));
}

/// BulkFixDetail
///
/// {
///   "code": String
///   "occurrences": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class BulkFixDetail implements HasToJson {
  /// The code of the diagnostic associated with the fix.
  String code;

  /// The number times the associated diagnostic was fixed in the associated
  /// source edit.
  int occurrences;

  BulkFixDetail(this.code, this.occurrences);

  factory BulkFixDetail.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String code;
      if (json.containsKey('code')) {
        code = jsonDecoder.decodeString('$jsonPath.code', json['code']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'code');
      }
      int occurrences;
      if (json.containsKey('occurrences')) {
        occurrences = jsonDecoder.decodeInt(
          '$jsonPath.occurrences',
          json['occurrences'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'occurrences');
      }
      return BulkFixDetail(code, occurrences);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'BulkFixDetail', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['code'] = code;
    result['occurrences'] = occurrences;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is BulkFixDetail) {
      return code == other.code && occurrences == other.occurrences;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(code, occurrences);
}

/// ClosingLabel
///
/// {
///   "offset": int
///   "length": int
///   "label": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ClosingLabel implements HasToJson {
  /// The offset of the construct being labelled.
  int offset;

  /// The length of the whole construct to be labelled.
  int length;

  /// The label associated with this range that should be displayed to the
  /// user.
  String label;

  ClosingLabel(this.offset, this.length, this.label);

  factory ClosingLabel.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      String label;
      if (json.containsKey('label')) {
        label = jsonDecoder.decodeString('$jsonPath.label', json['label']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'label');
      }
      return ClosingLabel(offset, length, label);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ClosingLabel', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['offset'] = offset;
    result['length'] = length;
    result['label'] = label;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ClosingLabel) {
      return offset == other.offset &&
          length == other.length &&
          label == other.label;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(offset, length, label);
}

/// CompletionCaseMatchingMode
///
/// enum {
///   FIRST_CHAR
///   ALL_CHARS
///   NONE
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum CompletionCaseMatchingMode {
  /// Match the first character case only when filtering completions, the
  /// default for this enumeration.
  FIRST_CHAR,

  /// Match all character cases when filtering completion lists.
  ALL_CHARS,

  /// Do not match character cases when filtering completion lists.
  NONE;

  factory CompletionCaseMatchingMode.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'CompletionCaseMatchingMode', json);
  }

  @override
  String toString() => 'CompletionCaseMatchingMode.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// completion.existingImports params
///
/// {
///   "file": FilePath
///   "imports": ExistingImports
/// }
///
/// Clients may not extend, implement or mix-in this class.
class CompletionExistingImportsParams implements HasToJson {
  /// The defining file of the library.
  String file;

  /// The existing imports in the library.
  ExistingImports imports;

  CompletionExistingImportsParams(this.file, this.imports);

  factory CompletionExistingImportsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      ExistingImports imports;
      if (json.containsKey('imports')) {
        imports = ExistingImports.fromJson(
          jsonDecoder,
          '$jsonPath.imports',
          json['imports'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'imports');
      }
      return CompletionExistingImportsParams(file, imports);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'completion.existingImports params',
        json,
      );
    }
  }

  factory CompletionExistingImportsParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return CompletionExistingImportsParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['imports'] = imports.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'completion.existingImports',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is CompletionExistingImportsParams) {
      return file == other.file && imports == other.imports;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, imports);
}

/// completion.getSuggestionDetails2 params
///
/// {
///   "file": FilePath
///   "offset": int
///   "completion": String
///   "libraryUri": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class CompletionGetSuggestionDetails2Params implements RequestParams {
  /// The path of the file into which this completion is being inserted.
  String file;

  /// The offset in the file where the completion will be inserted.
  int offset;

  /// The `completion` from the selected `CompletionSuggestion`. It could be a
  /// name of a class, or a name of a constructor in the form
  /// "typeName.constructorName()", or an enumeration constant in the form
  /// "enumName.constantName", etc.
  String completion;

  /// The URI of the library to import, so that the element referenced in the
  /// `completion` becomes accessible.
  String libraryUri;

  CompletionGetSuggestionDetails2Params(
    this.file,
    this.offset,
    this.completion,
    this.libraryUri,
  );

  factory CompletionGetSuggestionDetails2Params.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      String completion;
      if (json.containsKey('completion')) {
        completion = jsonDecoder.decodeString(
          '$jsonPath.completion',
          json['completion'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'completion');
      }
      String libraryUri;
      if (json.containsKey('libraryUri')) {
        libraryUri = jsonDecoder.decodeString(
          '$jsonPath.libraryUri',
          json['libraryUri'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'libraryUri');
      }
      return CompletionGetSuggestionDetails2Params(
        file,
        offset,
        completion,
        libraryUri,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'completion.getSuggestionDetails2 params',
        json,
      );
    }
  }

  factory CompletionGetSuggestionDetails2Params.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return CompletionGetSuggestionDetails2Params.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    result['completion'] = completion;
    result['libraryUri'] = libraryUri;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'completion.getSuggestionDetails2',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is CompletionGetSuggestionDetails2Params) {
      return file == other.file &&
          offset == other.offset &&
          completion == other.completion &&
          libraryUri == other.libraryUri;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset, completion, libraryUri);
}

/// completion.getSuggestionDetails2 result
///
/// {
///   "completion": String
///   "change": SourceChange
/// }
///
/// Clients may not extend, implement or mix-in this class.
class CompletionGetSuggestionDetails2Result implements ResponseResult {
  /// 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`.
  String completion;

  /// 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.
  SourceChange change;

  CompletionGetSuggestionDetails2Result(this.completion, this.change);

  factory CompletionGetSuggestionDetails2Result.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String completion;
      if (json.containsKey('completion')) {
        completion = jsonDecoder.decodeString(
          '$jsonPath.completion',
          json['completion'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'completion');
      }
      SourceChange change;
      if (json.containsKey('change')) {
        change = SourceChange.fromJson(
          jsonDecoder,
          '$jsonPath.change',
          json['change'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'change');
      }
      return CompletionGetSuggestionDetails2Result(completion, change);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'completion.getSuggestionDetails2 result',
        json,
      );
    }
  }

  factory CompletionGetSuggestionDetails2Result.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return CompletionGetSuggestionDetails2Result.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['completion'] = completion;
    result['change'] = change.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is CompletionGetSuggestionDetails2Result) {
      return completion == other.completion && change == other.change;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(completion, change);
}

/// completion.getSuggestions2 params
///
/// {
///   "file": FilePath
///   "offset": int
///   "maxResults": int
///   "completionCaseMatchingMode": optional CompletionCaseMatchingMode
/// }
///
/// Clients may not extend, implement or mix-in this class.
class CompletionGetSuggestions2Params implements RequestParams {
  /// The file containing the point at which suggestions are to be made.
  String file;

  /// The offset within the file at which suggestions are to be made.
  int offset;

  /// 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`.
  int maxResults;

  /// The mode of code completion being invoked. If no value is provided,
  /// `MATCH_FIRST_CHAR` will be assumed.
  CompletionCaseMatchingMode? completionCaseMatchingMode;

  /// The mode of code completion being invoked. If no value is provided,
  /// `BASIC` will be assumed. `BASIC` is also the only currently supported.
  CompletionMode? completionMode;

  /// The number of times that the user has invoked code completion at the same
  /// code location, counting from 1. If no value is provided, 1 will be
  /// assumed.
  int? invocationCount;

  /// The approximate time in milliseconds that the server should spend. The
  /// server will perform some steps anyway, even if it takes longer than the
  /// specified timeout. This field is intended to be used for benchmarking,
  /// and usually should not be provided, so that the default timeout is used.
  int? timeout;

  CompletionGetSuggestions2Params(
    this.file,
    this.offset,
    this.maxResults, {
    this.completionCaseMatchingMode,
    this.completionMode,
    this.invocationCount,
    this.timeout,
  });

  factory CompletionGetSuggestions2Params.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int maxResults;
      if (json.containsKey('maxResults')) {
        maxResults = jsonDecoder.decodeInt(
          '$jsonPath.maxResults',
          json['maxResults'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'maxResults');
      }
      CompletionCaseMatchingMode? completionCaseMatchingMode;
      if (json.containsKey('completionCaseMatchingMode')) {
        completionCaseMatchingMode = CompletionCaseMatchingMode.fromJson(
          jsonDecoder,
          '$jsonPath.completionCaseMatchingMode',
          json['completionCaseMatchingMode'],
          clientUriConverter: clientUriConverter,
        );
      }
      CompletionMode? completionMode;
      if (json.containsKey('completionMode')) {
        completionMode = CompletionMode.fromJson(
          jsonDecoder,
          '$jsonPath.completionMode',
          json['completionMode'],
          clientUriConverter: clientUriConverter,
        );
      }
      int? invocationCount;
      if (json.containsKey('invocationCount')) {
        invocationCount = jsonDecoder.decodeInt(
          '$jsonPath.invocationCount',
          json['invocationCount'],
        );
      }
      int? timeout;
      if (json.containsKey('timeout')) {
        timeout = jsonDecoder.decodeInt('$jsonPath.timeout', json['timeout']);
      }
      return CompletionGetSuggestions2Params(
        file,
        offset,
        maxResults,
        completionCaseMatchingMode: completionCaseMatchingMode,
        completionMode: completionMode,
        invocationCount: invocationCount,
        timeout: timeout,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'completion.getSuggestions2 params',
        json,
      );
    }
  }

  factory CompletionGetSuggestions2Params.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return CompletionGetSuggestions2Params.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    result['maxResults'] = maxResults;
    var completionCaseMatchingMode = this.completionCaseMatchingMode;
    if (completionCaseMatchingMode != null) {
      result['completionCaseMatchingMode'] = completionCaseMatchingMode.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var completionMode = this.completionMode;
    if (completionMode != null) {
      result['completionMode'] = completionMode.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var invocationCount = this.invocationCount;
    if (invocationCount != null) {
      result['invocationCount'] = invocationCount;
    }
    var timeout = this.timeout;
    if (timeout != null) {
      result['timeout'] = timeout;
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'completion.getSuggestions2',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is CompletionGetSuggestions2Params) {
      return file == other.file &&
          offset == other.offset &&
          maxResults == other.maxResults &&
          completionCaseMatchingMode == other.completionCaseMatchingMode &&
          completionMode == other.completionMode &&
          invocationCount == other.invocationCount &&
          timeout == other.timeout;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    file,
    offset,
    maxResults,
    completionCaseMatchingMode,
    completionMode,
    invocationCount,
    timeout,
  );
}

/// completion.getSuggestions2 result
///
/// {
///   "replacementOffset": int
///   "replacementLength": int
///   "suggestions": List<CompletionSuggestion>
///   "isIncomplete": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class CompletionGetSuggestions2Result implements ResponseResult {
  /// 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.
  int replacementOffset;

  /// 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).
  int replacementLength;

  /// 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
  /// `isNotImported` set to `true`.
  List<CompletionSuggestion> suggestions;

  /// True if the number of suggestions after filtering was greater than the
  /// requested `maxResults`.
  bool isIncomplete;

  CompletionGetSuggestions2Result(
    this.replacementOffset,
    this.replacementLength,
    this.suggestions,
    this.isIncomplete,
  );

  factory CompletionGetSuggestions2Result.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int replacementOffset;
      if (json.containsKey('replacementOffset')) {
        replacementOffset = jsonDecoder.decodeInt(
          '$jsonPath.replacementOffset',
          json['replacementOffset'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'replacementOffset');
      }
      int replacementLength;
      if (json.containsKey('replacementLength')) {
        replacementLength = jsonDecoder.decodeInt(
          '$jsonPath.replacementLength',
          json['replacementLength'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'replacementLength');
      }
      List<CompletionSuggestion> suggestions;
      if (json.containsKey('suggestions')) {
        suggestions = jsonDecoder.decodeList(
          '$jsonPath.suggestions',
          json['suggestions'],
          (String jsonPath, Object? json) => CompletionSuggestion.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'suggestions');
      }
      bool isIncomplete;
      if (json.containsKey('isIncomplete')) {
        isIncomplete = jsonDecoder.decodeBool(
          '$jsonPath.isIncomplete',
          json['isIncomplete'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'isIncomplete');
      }
      return CompletionGetSuggestions2Result(
        replacementOffset,
        replacementLength,
        suggestions,
        isIncomplete,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'completion.getSuggestions2 result',
        json,
      );
    }
  }

  factory CompletionGetSuggestions2Result.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return CompletionGetSuggestions2Result.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['replacementOffset'] = replacementOffset;
    result['replacementLength'] = replacementLength;
    result['suggestions'] =
        suggestions
            .map(
              (CompletionSuggestion value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['isIncomplete'] = isIncomplete;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is CompletionGetSuggestions2Result) {
      return replacementOffset == other.replacementOffset &&
          replacementLength == other.replacementLength &&
          listEqual(
            suggestions,
            other.suggestions,
            (CompletionSuggestion a, CompletionSuggestion b) => a == b,
          ) &&
          isIncomplete == other.isIncomplete;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    replacementOffset,
    replacementLength,
    Object.hashAll(suggestions),
    isIncomplete,
  );
}

/// CompletionMode
///
/// enum {
///   BASIC
///   SMART
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum CompletionMode {
  /// Basic code completion invocation type, and the default for this
  /// enumeration.
  BASIC,

  /// Smart code completion, currently not implemented.
  SMART;

  factory CompletionMode.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'CompletionMode', json);
  }

  @override
  String toString() => 'CompletionMode.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// completion.registerLibraryPaths params
///
/// {
///   "paths": List<LibraryPathSet>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class CompletionRegisterLibraryPathsParams implements RequestParams {
  /// 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 descendant will override
  /// the ancestors' configured libraries of interest.
  List<LibraryPathSet> paths;

  CompletionRegisterLibraryPathsParams(this.paths);

  factory CompletionRegisterLibraryPathsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<LibraryPathSet> paths;
      if (json.containsKey('paths')) {
        paths = jsonDecoder.decodeList(
          '$jsonPath.paths',
          json['paths'],
          (String jsonPath, Object? json) => LibraryPathSet.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'paths');
      }
      return CompletionRegisterLibraryPathsParams(paths);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'completion.registerLibraryPaths params',
        json,
      );
    }
  }

  factory CompletionRegisterLibraryPathsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return CompletionRegisterLibraryPathsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['paths'] =
        paths
            .map(
              (LibraryPathSet value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'completion.registerLibraryPaths',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is CompletionRegisterLibraryPathsParams) {
      return listEqual(
        paths,
        other.paths,
        (LibraryPathSet a, LibraryPathSet b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(paths);
}

/// completion.registerLibraryPaths result
///
/// Clients may not extend, implement or mix-in this class.
class CompletionRegisterLibraryPathsResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) =>
      other is CompletionRegisterLibraryPathsResult;

  @override
  int get hashCode => 104675661;
}

/// ContextData
///
/// {
///   "name": String
///   "explicitFileCount": int
///   "implicitFileCount": int
///   "workItemQueueLength": int
///   "cacheEntryExceptions": List<String>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ContextData implements HasToJson {
  /// The name of the context.
  String name;

  /// Explicitly analyzed files.
  int explicitFileCount;

  /// Implicitly analyzed files.
  int implicitFileCount;

  /// The number of work items in the queue.
  int workItemQueueLength;

  /// Exceptions associated with cache entries.
  List<String> cacheEntryExceptions;

  ContextData(
    this.name,
    this.explicitFileCount,
    this.implicitFileCount,
    this.workItemQueueLength,
    this.cacheEntryExceptions,
  );

  factory ContextData.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      int explicitFileCount;
      if (json.containsKey('explicitFileCount')) {
        explicitFileCount = jsonDecoder.decodeInt(
          '$jsonPath.explicitFileCount',
          json['explicitFileCount'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'explicitFileCount');
      }
      int implicitFileCount;
      if (json.containsKey('implicitFileCount')) {
        implicitFileCount = jsonDecoder.decodeInt(
          '$jsonPath.implicitFileCount',
          json['implicitFileCount'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'implicitFileCount');
      }
      int workItemQueueLength;
      if (json.containsKey('workItemQueueLength')) {
        workItemQueueLength = jsonDecoder.decodeInt(
          '$jsonPath.workItemQueueLength',
          json['workItemQueueLength'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'workItemQueueLength');
      }
      List<String> cacheEntryExceptions;
      if (json.containsKey('cacheEntryExceptions')) {
        cacheEntryExceptions = jsonDecoder.decodeList(
          '$jsonPath.cacheEntryExceptions',
          json['cacheEntryExceptions'],
          jsonDecoder.decodeString,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'cacheEntryExceptions');
      }
      return ContextData(
        name,
        explicitFileCount,
        implicitFileCount,
        workItemQueueLength,
        cacheEntryExceptions,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ContextData', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    result['explicitFileCount'] = explicitFileCount;
    result['implicitFileCount'] = implicitFileCount;
    result['workItemQueueLength'] = workItemQueueLength;
    result['cacheEntryExceptions'] = cacheEntryExceptions;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ContextData) {
      return name == other.name &&
          explicitFileCount == other.explicitFileCount &&
          implicitFileCount == other.implicitFileCount &&
          workItemQueueLength == other.workItemQueueLength &&
          listEqual(
            cacheEntryExceptions,
            other.cacheEntryExceptions,
            (String a, String b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    name,
    explicitFileCount,
    implicitFileCount,
    workItemQueueLength,
    Object.hashAll(cacheEntryExceptions),
  );
}

/// convertGetterToMethod feedback
///
/// Clients may not extend, implement or mix-in this class.
class ConvertGetterToMethodFeedback extends RefactoringFeedback
    implements HasToJson {
  @override
  bool operator ==(Object other) => other is ConvertGetterToMethodFeedback;

  @override
  int get hashCode => 616032599;
}

/// convertGetterToMethod options
///
/// Clients may not extend, implement or mix-in this class.
class ConvertGetterToMethodOptions extends RefactoringOptions
    implements HasToJson {
  @override
  bool operator ==(Object other) => other is ConvertGetterToMethodOptions;

  @override
  int get hashCode => 488848400;
}

/// convertMethodToGetter feedback
///
/// Clients may not extend, implement or mix-in this class.
class ConvertMethodToGetterFeedback extends RefactoringFeedback
    implements HasToJson {
  @override
  bool operator ==(Object other) => other is ConvertMethodToGetterFeedback;

  @override
  int get hashCode => 165291526;
}

/// convertMethodToGetter options
///
/// Clients may not extend, implement or mix-in this class.
class ConvertMethodToGetterOptions extends RefactoringOptions
    implements HasToJson {
  @override
  bool operator ==(Object other) => other is ConvertMethodToGetterOptions;

  @override
  int get hashCode => 27952290;
}

/// diagnostic.getDiagnostics params
///
/// Clients may not extend, implement or mix-in this class.
class DiagnosticGetDiagnosticsParams implements RequestParams {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(id, 'diagnostic.getDiagnostics');
  }

  @override
  bool operator ==(Object other) => other is DiagnosticGetDiagnosticsParams;

  @override
  int get hashCode => 587526202;
}

/// diagnostic.getDiagnostics result
///
/// {
///   "contexts": List<ContextData>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class DiagnosticGetDiagnosticsResult implements ResponseResult {
  /// The list of analysis contexts.
  List<ContextData> contexts;

  DiagnosticGetDiagnosticsResult(this.contexts);

  factory DiagnosticGetDiagnosticsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<ContextData> contexts;
      if (json.containsKey('contexts')) {
        contexts = jsonDecoder.decodeList(
          '$jsonPath.contexts',
          json['contexts'],
          (String jsonPath, Object? json) => ContextData.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'contexts');
      }
      return DiagnosticGetDiagnosticsResult(contexts);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'diagnostic.getDiagnostics result',
        json,
      );
    }
  }

  factory DiagnosticGetDiagnosticsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return DiagnosticGetDiagnosticsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['contexts'] =
        contexts
            .map(
              (ContextData value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is DiagnosticGetDiagnosticsResult) {
      return listEqual(
        contexts,
        other.contexts,
        (ContextData a, ContextData b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(contexts);
}

/// diagnostic.getServerPort params
///
/// Clients may not extend, implement or mix-in this class.
class DiagnosticGetServerPortParams implements RequestParams {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(id, 'diagnostic.getServerPort');
  }

  @override
  bool operator ==(Object other) => other is DiagnosticGetServerPortParams;

  @override
  int get hashCode => 367508704;
}

/// diagnostic.getServerPort result
///
/// {
///   "port": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class DiagnosticGetServerPortResult implements ResponseResult {
  /// The diagnostic server port.
  int port;

  DiagnosticGetServerPortResult(this.port);

  factory DiagnosticGetServerPortResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int port;
      if (json.containsKey('port')) {
        port = jsonDecoder.decodeInt('$jsonPath.port', json['port']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'port');
      }
      return DiagnosticGetServerPortResult(port);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'diagnostic.getServerPort result',
        json,
      );
    }
  }

  factory DiagnosticGetServerPortResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return DiagnosticGetServerPortResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['port'] = port;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is DiagnosticGetServerPortResult) {
      return port == other.port;
    }
    return false;
  }

  @override
  int get hashCode => port.hashCode;
}

/// edit.bulkFixes params
///
/// {
///   "included": List<FilePath>
///   "inTestMode": optional bool
///   "updatePubspec": optional bool
///   "codes": optional List<String>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditBulkFixesParams implements RequestParams {
  /// 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.
  List<String> included;

  /// 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`.
  bool? inTestMode;

  /// A flag indicating whether to validate that the dependencies used by the
  /// included files are listed in the pubspec file. If specified, the fix
  /// processor will compute the set of packages imported in the source and
  /// check to see if they are listed in the corresponding pubspec file, and
  /// compute the fixes, if any.
  ///
  /// If this field is omitted the flag defaults to `false`.
  bool? updatePubspec;

  /// A list of diagnostic codes to be fixed.
  List<String>? codes;

  EditBulkFixesParams(
    this.included, {
    this.inTestMode,
    this.updatePubspec,
    this.codes,
  });

  factory EditBulkFixesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> included;
      if (json.containsKey('included')) {
        included = jsonDecoder.decodeList(
          '$jsonPath.included',
          json['included'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'included');
      }
      bool? inTestMode;
      if (json.containsKey('inTestMode')) {
        inTestMode = jsonDecoder.decodeBool(
          '$jsonPath.inTestMode',
          json['inTestMode'],
        );
      }
      bool? updatePubspec;
      if (json.containsKey('updatePubspec')) {
        updatePubspec = jsonDecoder.decodeBool(
          '$jsonPath.updatePubspec',
          json['updatePubspec'],
        );
      }
      List<String>? codes;
      if (json.containsKey('codes')) {
        codes = jsonDecoder.decodeList(
          '$jsonPath.codes',
          json['codes'],
          jsonDecoder.decodeString,
        );
      }
      return EditBulkFixesParams(
        included,
        inTestMode: inTestMode,
        updatePubspec: updatePubspec,
        codes: codes,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.bulkFixes params', json);
    }
  }

  factory EditBulkFixesParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditBulkFixesParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['included'] =
        included
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    var inTestMode = this.inTestMode;
    if (inTestMode != null) {
      result['inTestMode'] = inTestMode;
    }
    var updatePubspec = this.updatePubspec;
    if (updatePubspec != null) {
      result['updatePubspec'] = updatePubspec;
    }
    var codes = this.codes;
    if (codes != null) {
      result['codes'] = codes;
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.bulkFixes',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditBulkFixesParams) {
      return listEqual(
            included,
            other.included,
            (String a, String b) => a == b,
          ) &&
          inTestMode == other.inTestMode &&
          updatePubspec == other.updatePubspec &&
          listEqual(codes, other.codes, (String a, String b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    Object.hashAll(included),
    inTestMode,
    updatePubspec,
    Object.hashAll(codes ?? []),
  );
}

/// edit.bulkFixes result
///
/// {
///   "message": String
///   "edits": List<SourceFileEdit>
///   "details": List<BulkFix>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditBulkFixesResult implements ResponseResult {
  /// An optional message explaining unapplied fixes.
  String message;

  /// A list of source edits to apply the recommended changes.
  List<SourceFileEdit> edits;

  /// Details that summarize the fixes associated with the recommended changes.
  List<BulkFix> details;

  EditBulkFixesResult(this.message, this.edits, this.details);

  factory EditBulkFixesResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String message;
      if (json.containsKey('message')) {
        message = jsonDecoder.decodeString(
          '$jsonPath.message',
          json['message'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'message');
      }
      List<SourceFileEdit> edits;
      if (json.containsKey('edits')) {
        edits = jsonDecoder.decodeList(
          '$jsonPath.edits',
          json['edits'],
          (String jsonPath, Object? json) => SourceFileEdit.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'edits');
      }
      List<BulkFix> details;
      if (json.containsKey('details')) {
        details = jsonDecoder.decodeList(
          '$jsonPath.details',
          json['details'],
          (String jsonPath, Object? json) => BulkFix.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'details');
      }
      return EditBulkFixesResult(message, edits, details);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.bulkFixes result', json);
    }
  }

  factory EditBulkFixesResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditBulkFixesResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['message'] = message;
    result['edits'] =
        edits
            .map(
              (SourceFileEdit value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['details'] =
        details
            .map(
              (BulkFix value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditBulkFixesResult) {
      return message == other.message &&
          listEqual(
            edits,
            other.edits,
            (SourceFileEdit a, SourceFileEdit b) => a == b,
          ) &&
          listEqual(details, other.details, (BulkFix a, BulkFix b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(message, Object.hashAll(edits), Object.hashAll(details));
}

/// edit.formatIfEnabled params
///
/// {
///   "directories": List<FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditFormatIfEnabledParams implements RequestParams {
  /// The paths of the directories containing the code to be formatted.
  List<String> directories;

  EditFormatIfEnabledParams(this.directories);

  factory EditFormatIfEnabledParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> directories;
      if (json.containsKey('directories')) {
        directories = jsonDecoder.decodeList(
          '$jsonPath.directories',
          json['directories'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'directories');
      }
      return EditFormatIfEnabledParams(directories);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.formatIfEnabled params', json);
    }
  }

  factory EditFormatIfEnabledParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditFormatIfEnabledParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['directories'] =
        directories
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.formatIfEnabled',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditFormatIfEnabledParams) {
      return listEqual(
        directories,
        other.directories,
        (String a, String b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(directories);
}

/// edit.formatIfEnabled result
///
/// {
///   "edits": List<SourceFileEdit>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditFormatIfEnabledResult implements ResponseResult {
  /// The edit(s) to be applied in order to format the code. The list will be
  /// empty if none of the files were formatted, whether because they were not
  /// eligible to be formatted or because they were already formatted.
  List<SourceFileEdit> edits;

  EditFormatIfEnabledResult(this.edits);

  factory EditFormatIfEnabledResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<SourceFileEdit> edits;
      if (json.containsKey('edits')) {
        edits = jsonDecoder.decodeList(
          '$jsonPath.edits',
          json['edits'],
          (String jsonPath, Object? json) => SourceFileEdit.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'edits');
      }
      return EditFormatIfEnabledResult(edits);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.formatIfEnabled result', json);
    }
  }

  factory EditFormatIfEnabledResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditFormatIfEnabledResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['edits'] =
        edits
            .map(
              (SourceFileEdit value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditFormatIfEnabledResult) {
      return listEqual(
        edits,
        other.edits,
        (SourceFileEdit a, SourceFileEdit b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(edits);
}

/// edit.format params
///
/// {
///   "file": FilePath
///   "selectionOffset": int
///   "selectionLength": int
///   "lineLength": optional int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditFormatParams implements RequestParams {
  /// The file containing the code to be formatted.
  String file;

  /// The offset of the current selection in the file.
  int selectionOffset;

  /// The length of the current selection in the file.
  int selectionLength;

  /// The line length to be used by the formatter. This value is ignored if a
  /// `formatter.page_width` has been configured in the relevant
  /// `analysis_options.yaml` file.
  int? lineLength;

  EditFormatParams(
    this.file,
    this.selectionOffset,
    this.selectionLength, {
    this.lineLength,
  });

  factory EditFormatParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int selectionOffset;
      if (json.containsKey('selectionOffset')) {
        selectionOffset = jsonDecoder.decodeInt(
          '$jsonPath.selectionOffset',
          json['selectionOffset'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'selectionOffset');
      }
      int selectionLength;
      if (json.containsKey('selectionLength')) {
        selectionLength = jsonDecoder.decodeInt(
          '$jsonPath.selectionLength',
          json['selectionLength'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'selectionLength');
      }
      int? lineLength;
      if (json.containsKey('lineLength')) {
        lineLength = jsonDecoder.decodeInt(
          '$jsonPath.lineLength',
          json['lineLength'],
        );
      }
      return EditFormatParams(
        file,
        selectionOffset,
        selectionLength,
        lineLength: lineLength,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.format params', json);
    }
  }

  factory EditFormatParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditFormatParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['selectionOffset'] = selectionOffset;
    result['selectionLength'] = selectionLength;
    var lineLength = this.lineLength;
    if (lineLength != null) {
      result['lineLength'] = lineLength;
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.format',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditFormatParams) {
      return file == other.file &&
          selectionOffset == other.selectionOffset &&
          selectionLength == other.selectionLength &&
          lineLength == other.lineLength;
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(file, selectionOffset, selectionLength, lineLength);
}

/// edit.format result
///
/// {
///   "edits": List<SourceEdit>
///   "selectionOffset": int
///   "selectionLength": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditFormatResult implements ResponseResult {
  /// 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).
  List<SourceEdit> edits;

  /// The offset of the selection after formatting the code.
  int selectionOffset;

  /// The length of the selection after formatting the code.
  int selectionLength;

  EditFormatResult(this.edits, this.selectionOffset, this.selectionLength);

  factory EditFormatResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<SourceEdit> edits;
      if (json.containsKey('edits')) {
        edits = jsonDecoder.decodeList(
          '$jsonPath.edits',
          json['edits'],
          (String jsonPath, Object? json) => SourceEdit.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'edits');
      }
      int selectionOffset;
      if (json.containsKey('selectionOffset')) {
        selectionOffset = jsonDecoder.decodeInt(
          '$jsonPath.selectionOffset',
          json['selectionOffset'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'selectionOffset');
      }
      int selectionLength;
      if (json.containsKey('selectionLength')) {
        selectionLength = jsonDecoder.decodeInt(
          '$jsonPath.selectionLength',
          json['selectionLength'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'selectionLength');
      }
      return EditFormatResult(edits, selectionOffset, selectionLength);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.format result', json);
    }
  }

  factory EditFormatResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditFormatResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['edits'] =
        edits
            .map(
              (SourceEdit value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['selectionOffset'] = selectionOffset;
    result['selectionLength'] = selectionLength;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditFormatResult) {
      return listEqual(
            edits,
            other.edits,
            (SourceEdit a, SourceEdit b) => a == b,
          ) &&
          selectionOffset == other.selectionOffset &&
          selectionLength == other.selectionLength;
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(Object.hashAll(edits), selectionOffset, selectionLength);
}

/// edit.getAssists params
///
/// {
///   "file": FilePath
///   "offset": int
///   "length": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetAssistsParams implements RequestParams {
  /// The file containing the code for which assists are being requested.
  String file;

  /// The offset of the code for which assists are being requested.
  int offset;

  /// The length of the code for which assists are being requested.
  int length;

  EditGetAssistsParams(this.file, this.offset, this.length);

  factory EditGetAssistsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      return EditGetAssistsParams(file, offset, length);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.getAssists params', json);
    }
  }

  factory EditGetAssistsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetAssistsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    result['length'] = length;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.getAssists',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetAssistsParams) {
      return file == other.file &&
          offset == other.offset &&
          length == other.length;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset, length);
}

/// edit.getAssists result
///
/// {
///   "assists": List<SourceChange>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetAssistsResult implements ResponseResult {
  /// The assists that are available at the given location.
  List<SourceChange> assists;

  EditGetAssistsResult(this.assists);

  factory EditGetAssistsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<SourceChange> assists;
      if (json.containsKey('assists')) {
        assists = jsonDecoder.decodeList(
          '$jsonPath.assists',
          json['assists'],
          (String jsonPath, Object? json) => SourceChange.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'assists');
      }
      return EditGetAssistsResult(assists);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.getAssists result', json);
    }
  }

  factory EditGetAssistsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetAssistsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['assists'] =
        assists
            .map(
              (SourceChange value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetAssistsResult) {
      return listEqual(
        assists,
        other.assists,
        (SourceChange a, SourceChange b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(assists);
}

/// edit.getAvailableRefactorings params
///
/// {
///   "file": FilePath
///   "offset": int
///   "length": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetAvailableRefactoringsParams implements RequestParams {
  /// The file containing the code on which the refactoring would be based.
  String file;

  /// The offset of the code on which the refactoring would be based.
  int offset;

  /// The length of the code on which the refactoring would be based.
  int length;

  EditGetAvailableRefactoringsParams(this.file, this.offset, this.length);

  factory EditGetAvailableRefactoringsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      return EditGetAvailableRefactoringsParams(file, offset, length);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.getAvailableRefactorings params',
        json,
      );
    }
  }

  factory EditGetAvailableRefactoringsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetAvailableRefactoringsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    result['length'] = length;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.getAvailableRefactorings',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetAvailableRefactoringsParams) {
      return file == other.file &&
          offset == other.offset &&
          length == other.length;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset, length);
}

/// edit.getAvailableRefactorings result
///
/// {
///   "kinds": List<RefactoringKind>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetAvailableRefactoringsResult implements ResponseResult {
  /// The kinds of refactorings that are valid for the given selection.
  List<RefactoringKind> kinds;

  EditGetAvailableRefactoringsResult(this.kinds);

  factory EditGetAvailableRefactoringsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<RefactoringKind> kinds;
      if (json.containsKey('kinds')) {
        kinds = jsonDecoder.decodeList(
          '$jsonPath.kinds',
          json['kinds'],
          (String jsonPath, Object? json) => RefactoringKind.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kinds');
      }
      return EditGetAvailableRefactoringsResult(kinds);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.getAvailableRefactorings result',
        json,
      );
    }
  }

  factory EditGetAvailableRefactoringsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetAvailableRefactoringsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['kinds'] =
        kinds
            .map(
              (RefactoringKind value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetAvailableRefactoringsResult) {
      return listEqual(
        kinds,
        other.kinds,
        (RefactoringKind a, RefactoringKind b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(kinds);
}

/// edit.getFixes params
///
/// {
///   "file": FilePath
///   "offset": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetFixesParams implements RequestParams {
  /// The file containing the errors for which fixes are being requested.
  String file;

  /// The offset used to select the errors for which fixes will be returned.
  int offset;

  EditGetFixesParams(this.file, this.offset);

  factory EditGetFixesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      return EditGetFixesParams(file, offset);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.getFixes params', json);
    }
  }

  factory EditGetFixesParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetFixesParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.getFixes',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetFixesParams) {
      return file == other.file && offset == other.offset;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset);
}

/// edit.getFixes result
///
/// {
///   "fixes": List<AnalysisErrorFixes>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetFixesResult implements ResponseResult {
  /// The fixes that are available for the errors at the given offset.
  List<AnalysisErrorFixes> fixes;

  EditGetFixesResult(this.fixes);

  factory EditGetFixesResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<AnalysisErrorFixes> fixes;
      if (json.containsKey('fixes')) {
        fixes = jsonDecoder.decodeList(
          '$jsonPath.fixes',
          json['fixes'],
          (String jsonPath, Object? json) => AnalysisErrorFixes.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'fixes');
      }
      return EditGetFixesResult(fixes);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.getFixes result', json);
    }
  }

  factory EditGetFixesResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetFixesResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['fixes'] =
        fixes
            .map(
              (AnalysisErrorFixes value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetFixesResult) {
      return listEqual(
        fixes,
        other.fixes,
        (AnalysisErrorFixes a, AnalysisErrorFixes b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(fixes);
}

/// edit.getPostfixCompletion params
///
/// {
///   "file": FilePath
///   "key": String
///   "offset": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetPostfixCompletionParams implements RequestParams {
  /// The file containing the postfix template to be expanded.
  String file;

  /// The unique name that identifies the template in use.
  String key;

  /// The offset used to identify the code to which the template will be
  /// applied.
  int offset;

  EditGetPostfixCompletionParams(this.file, this.key, this.offset);

  factory EditGetPostfixCompletionParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      String key;
      if (json.containsKey('key')) {
        key = jsonDecoder.decodeString('$jsonPath.key', json['key']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'key');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      return EditGetPostfixCompletionParams(file, key, offset);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.getPostfixCompletion params',
        json,
      );
    }
  }

  factory EditGetPostfixCompletionParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetPostfixCompletionParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['key'] = key;
    result['offset'] = offset;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.getPostfixCompletion',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetPostfixCompletionParams) {
      return file == other.file && key == other.key && offset == other.offset;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, key, offset);
}

/// edit.getPostfixCompletion result
///
/// {
///   "change": SourceChange
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetPostfixCompletionResult implements ResponseResult {
  /// The change to be applied in order to complete the statement.
  SourceChange change;

  EditGetPostfixCompletionResult(this.change);

  factory EditGetPostfixCompletionResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      SourceChange change;
      if (json.containsKey('change')) {
        change = SourceChange.fromJson(
          jsonDecoder,
          '$jsonPath.change',
          json['change'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'change');
      }
      return EditGetPostfixCompletionResult(change);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.getPostfixCompletion result',
        json,
      );
    }
  }

  factory EditGetPostfixCompletionResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetPostfixCompletionResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['change'] = change.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetPostfixCompletionResult) {
      return change == other.change;
    }
    return false;
  }

  @override
  int get hashCode => change.hashCode;
}

/// edit.getRefactoring params
///
/// {
///   "kind": RefactoringKind
///   "file": FilePath
///   "offset": int
///   "length": int
///   "validateOnly": bool
///   "options": optional RefactoringOptions
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetRefactoringParams implements RequestParams {
  /// The kind of refactoring to be performed.
  RefactoringKind kind;

  /// The file containing the code involved in the refactoring.
  String file;

  /// The offset of the region involved in the refactoring.
  int offset;

  /// The length of the region involved in the refactoring.
  int length;

  /// True if the client is only requesting that the values of the options be
  /// validated and no change be generated.
  bool validateOnly;

  /// 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.
  RefactoringOptions? options;

  EditGetRefactoringParams(
    this.kind,
    this.file,
    this.offset,
    this.length,
    this.validateOnly, {
    this.options,
  });

  factory EditGetRefactoringParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      RefactoringKind kind;
      if (json.containsKey('kind')) {
        kind = RefactoringKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kind');
      }
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      bool validateOnly;
      if (json.containsKey('validateOnly')) {
        validateOnly = jsonDecoder.decodeBool(
          '$jsonPath.validateOnly',
          json['validateOnly'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'validateOnly');
      }
      RefactoringOptions? options;
      if (json.containsKey('options')) {
        options = RefactoringOptions.fromJson(
          jsonDecoder,
          '$jsonPath.options',
          json['options'],
          kind,
          clientUriConverter: clientUriConverter,
        );
      }
      return EditGetRefactoringParams(
        kind,
        file,
        offset,
        length,
        validateOnly,
        options: options,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.getRefactoring params', json);
    }
  }

  factory EditGetRefactoringParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    var params = EditGetRefactoringParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
    REQUEST_ID_REFACTORING_KINDS[request.id] = params.kind;
    return params;
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    result['length'] = length;
    result['validateOnly'] = validateOnly;
    var options = this.options;
    if (options != null) {
      result['options'] = options.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.getRefactoring',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetRefactoringParams) {
      return kind == other.kind &&
          file == other.file &&
          offset == other.offset &&
          length == other.length &&
          validateOnly == other.validateOnly &&
          options == other.options;
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(kind, file, offset, length, validateOnly, options);
}

/// edit.getRefactoring result
///
/// {
///   "initialProblems": List<RefactoringProblem>
///   "optionsProblems": List<RefactoringProblem>
///   "finalProblems": List<RefactoringProblem>
///   "feedback": optional RefactoringFeedback
///   "change": optional SourceChange
///   "potentialEdits": optional List<String>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetRefactoringResult implements ResponseResult {
  /// 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.
  List<RefactoringProblem> initialProblems;

  /// 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.
  List<RefactoringProblem> optionsProblems;

  /// 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.
  List<RefactoringProblem> finalProblems;

  /// 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".
  RefactoringFeedback? feedback;

  /// 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.
  SourceChange? change;

  /// 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.
  List<String>? potentialEdits;

  EditGetRefactoringResult(
    this.initialProblems,
    this.optionsProblems,
    this.finalProblems, {
    this.feedback,
    this.change,
    this.potentialEdits,
  });

  factory EditGetRefactoringResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<RefactoringProblem> initialProblems;
      if (json.containsKey('initialProblems')) {
        initialProblems = jsonDecoder.decodeList(
          '$jsonPath.initialProblems',
          json['initialProblems'],
          (String jsonPath, Object? json) => RefactoringProblem.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'initialProblems');
      }
      List<RefactoringProblem> optionsProblems;
      if (json.containsKey('optionsProblems')) {
        optionsProblems = jsonDecoder.decodeList(
          '$jsonPath.optionsProblems',
          json['optionsProblems'],
          (String jsonPath, Object? json) => RefactoringProblem.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'optionsProblems');
      }
      List<RefactoringProblem> finalProblems;
      if (json.containsKey('finalProblems')) {
        finalProblems = jsonDecoder.decodeList(
          '$jsonPath.finalProblems',
          json['finalProblems'],
          (String jsonPath, Object? json) => RefactoringProblem.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'finalProblems');
      }
      RefactoringFeedback? feedback;
      if (json.containsKey('feedback')) {
        feedback = RefactoringFeedback.fromJson(
          jsonDecoder,
          '$jsonPath.feedback',
          json['feedback'],
          json,
          clientUriConverter: clientUriConverter,
        );
      }
      SourceChange? change;
      if (json.containsKey('change')) {
        change = SourceChange.fromJson(
          jsonDecoder,
          '$jsonPath.change',
          json['change'],
          clientUriConverter: clientUriConverter,
        );
      }
      List<String>? potentialEdits;
      if (json.containsKey('potentialEdits')) {
        potentialEdits = jsonDecoder.decodeList(
          '$jsonPath.potentialEdits',
          json['potentialEdits'],
          jsonDecoder.decodeString,
        );
      }
      return EditGetRefactoringResult(
        initialProblems,
        optionsProblems,
        finalProblems,
        feedback: feedback,
        change: change,
        potentialEdits: potentialEdits,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.getRefactoring result', json);
    }
  }

  factory EditGetRefactoringResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetRefactoringResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['initialProblems'] =
        initialProblems
            .map(
              (RefactoringProblem value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['optionsProblems'] =
        optionsProblems
            .map(
              (RefactoringProblem value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['finalProblems'] =
        finalProblems
            .map(
              (RefactoringProblem value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    var feedback = this.feedback;
    if (feedback != null) {
      result['feedback'] = feedback.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var change = this.change;
    if (change != null) {
      result['change'] = change.toJson(clientUriConverter: clientUriConverter);
    }
    var potentialEdits = this.potentialEdits;
    if (potentialEdits != null) {
      result['potentialEdits'] = potentialEdits;
    }
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetRefactoringResult) {
      return listEqual(
            initialProblems,
            other.initialProblems,
            (RefactoringProblem a, RefactoringProblem b) => a == b,
          ) &&
          listEqual(
            optionsProblems,
            other.optionsProblems,
            (RefactoringProblem a, RefactoringProblem b) => a == b,
          ) &&
          listEqual(
            finalProblems,
            other.finalProblems,
            (RefactoringProblem a, RefactoringProblem b) => a == b,
          ) &&
          feedback == other.feedback &&
          change == other.change &&
          listEqual(
            potentialEdits,
            other.potentialEdits,
            (String a, String b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    Object.hashAll(initialProblems),
    Object.hashAll(optionsProblems),
    Object.hashAll(finalProblems),
    feedback,
    change,
    Object.hashAll(potentialEdits ?? []),
  );
}

/// edit.getStatementCompletion params
///
/// {
///   "file": FilePath
///   "offset": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetStatementCompletionParams implements RequestParams {
  /// The file containing the statement to be completed.
  String file;

  /// The offset used to identify the statement to be completed.
  int offset;

  EditGetStatementCompletionParams(this.file, this.offset);

  factory EditGetStatementCompletionParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      return EditGetStatementCompletionParams(file, offset);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.getStatementCompletion params',
        json,
      );
    }
  }

  factory EditGetStatementCompletionParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetStatementCompletionParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.getStatementCompletion',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetStatementCompletionParams) {
      return file == other.file && offset == other.offset;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset);
}

/// edit.getStatementCompletion result
///
/// {
///   "change": SourceChange
///   "whitespaceOnly": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditGetStatementCompletionResult implements ResponseResult {
  /// The change to be applied in order to complete the statement.
  SourceChange change;

  /// Will be true if the change contains nothing but whitespace characters, or
  /// is empty.
  bool whitespaceOnly;

  EditGetStatementCompletionResult(this.change, this.whitespaceOnly);

  factory EditGetStatementCompletionResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      SourceChange change;
      if (json.containsKey('change')) {
        change = SourceChange.fromJson(
          jsonDecoder,
          '$jsonPath.change',
          json['change'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'change');
      }
      bool whitespaceOnly;
      if (json.containsKey('whitespaceOnly')) {
        whitespaceOnly = jsonDecoder.decodeBool(
          '$jsonPath.whitespaceOnly',
          json['whitespaceOnly'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'whitespaceOnly');
      }
      return EditGetStatementCompletionResult(change, whitespaceOnly);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.getStatementCompletion result',
        json,
      );
    }
  }

  factory EditGetStatementCompletionResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditGetStatementCompletionResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['change'] = change.toJson(clientUriConverter: clientUriConverter);
    result['whitespaceOnly'] = whitespaceOnly;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditGetStatementCompletionResult) {
      return change == other.change && whitespaceOnly == other.whitespaceOnly;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(change, whitespaceOnly);
}

/// edit.importElements params
///
/// {
///   "file": FilePath
///   "elements": List<ImportedElements>
///   "offset": optional int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditImportElementsParams implements RequestParams {
  /// The file in which the specified elements are to be made accessible.
  String file;

  /// The elements to be made accessible in the specified file.
  List<ImportedElements> elements;

  /// 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.
  int? offset;

  EditImportElementsParams(this.file, this.elements, {this.offset});

  factory EditImportElementsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      List<ImportedElements> elements;
      if (json.containsKey('elements')) {
        elements = jsonDecoder.decodeList(
          '$jsonPath.elements',
          json['elements'],
          (String jsonPath, Object? json) => ImportedElements.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'elements');
      }
      int? offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      }
      return EditImportElementsParams(file, elements, offset: offset);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.importElements params', json);
    }
  }

  factory EditImportElementsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditImportElementsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['elements'] =
        elements
            .map(
              (ImportedElements value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    var offset = this.offset;
    if (offset != null) {
      result['offset'] = offset;
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.importElements',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditImportElementsParams) {
      return file == other.file &&
          listEqual(
            elements,
            other.elements,
            (ImportedElements a, ImportedElements b) => a == b,
          ) &&
          offset == other.offset;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, Object.hashAll(elements), offset);
}

/// edit.importElements result
///
/// {
///   "edit": optional SourceFileEdit
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditImportElementsResult implements ResponseResult {
  /// 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.
  SourceFileEdit? edit;

  EditImportElementsResult({this.edit});

  factory EditImportElementsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      SourceFileEdit? edit;
      if (json.containsKey('edit')) {
        edit = SourceFileEdit.fromJson(
          jsonDecoder,
          '$jsonPath.edit',
          json['edit'],
          clientUriConverter: clientUriConverter,
        );
      }
      return EditImportElementsResult(edit: edit);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.importElements result', json);
    }
  }

  factory EditImportElementsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditImportElementsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var edit = this.edit;
    if (edit != null) {
      result['edit'] = edit.toJson(clientUriConverter: clientUriConverter);
    }
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditImportElementsResult) {
      return edit == other.edit;
    }
    return false;
  }

  @override
  int get hashCode => edit.hashCode;
}

/// edit.isPostfixCompletionApplicable params
///
/// {
///   "file": FilePath
///   "key": String
///   "offset": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditIsPostfixCompletionApplicableParams implements RequestParams {
  /// The file containing the postfix template to be expanded.
  String file;

  /// The unique name that identifies the template in use.
  String key;

  /// The offset used to identify the code to which the template will be
  /// applied.
  int offset;

  EditIsPostfixCompletionApplicableParams(this.file, this.key, this.offset);

  factory EditIsPostfixCompletionApplicableParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      String key;
      if (json.containsKey('key')) {
        key = jsonDecoder.decodeString('$jsonPath.key', json['key']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'key');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      return EditIsPostfixCompletionApplicableParams(file, key, offset);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.isPostfixCompletionApplicable params',
        json,
      );
    }
  }

  factory EditIsPostfixCompletionApplicableParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditIsPostfixCompletionApplicableParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['key'] = key;
    result['offset'] = offset;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.isPostfixCompletionApplicable',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditIsPostfixCompletionApplicableParams) {
      return file == other.file && key == other.key && offset == other.offset;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, key, offset);
}

/// edit.isPostfixCompletionApplicable result
///
/// {
///   "value": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditIsPostfixCompletionApplicableResult implements ResponseResult {
  /// True if the template can be expanded at the given location.
  bool value;

  EditIsPostfixCompletionApplicableResult(this.value);

  factory EditIsPostfixCompletionApplicableResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      bool value;
      if (json.containsKey('value')) {
        value = jsonDecoder.decodeBool('$jsonPath.value', json['value']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'value');
      }
      return EditIsPostfixCompletionApplicableResult(value);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.isPostfixCompletionApplicable result',
        json,
      );
    }
  }

  factory EditIsPostfixCompletionApplicableResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditIsPostfixCompletionApplicableResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['value'] = value;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditIsPostfixCompletionApplicableResult) {
      return value == other.value;
    }
    return false;
  }

  @override
  int get hashCode => value.hashCode;
}

/// edit.listPostfixCompletionTemplates params
///
/// Clients may not extend, implement or mix-in this class.
class EditListPostfixCompletionTemplatesParams implements RequestParams {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(id, 'edit.listPostfixCompletionTemplates');
  }

  @override
  bool operator ==(Object other) =>
      other is EditListPostfixCompletionTemplatesParams;

  @override
  int get hashCode => 690713107;
}

/// edit.listPostfixCompletionTemplates result
///
/// {
///   "templates": List<PostfixTemplateDescriptor>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditListPostfixCompletionTemplatesResult implements ResponseResult {
  /// The list of available templates.
  List<PostfixTemplateDescriptor> templates;

  EditListPostfixCompletionTemplatesResult(this.templates);

  factory EditListPostfixCompletionTemplatesResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<PostfixTemplateDescriptor> templates;
      if (json.containsKey('templates')) {
        templates = jsonDecoder.decodeList(
          '$jsonPath.templates',
          json['templates'],
          (String jsonPath, Object? json) => PostfixTemplateDescriptor.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'templates');
      }
      return EditListPostfixCompletionTemplatesResult(templates);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.listPostfixCompletionTemplates result',
        json,
      );
    }
  }

  factory EditListPostfixCompletionTemplatesResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditListPostfixCompletionTemplatesResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['templates'] =
        templates
            .map(
              (PostfixTemplateDescriptor value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditListPostfixCompletionTemplatesResult) {
      return listEqual(
        templates,
        other.templates,
        (PostfixTemplateDescriptor a, PostfixTemplateDescriptor b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(templates);
}

/// edit.organizeDirectives params
///
/// {
///   "file": FilePath
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditOrganizeDirectivesParams implements RequestParams {
  /// The Dart file to organize directives in.
  String file;

  EditOrganizeDirectivesParams(this.file);

  factory EditOrganizeDirectivesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      return EditOrganizeDirectivesParams(file);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.organizeDirectives params',
        json,
      );
    }
  }

  factory EditOrganizeDirectivesParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditOrganizeDirectivesParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.organizeDirectives',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditOrganizeDirectivesParams) {
      return file == other.file;
    }
    return false;
  }

  @override
  int get hashCode => file.hashCode;
}

/// edit.organizeDirectives result
///
/// {
///   "edit": SourceFileEdit
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditOrganizeDirectivesResult implements ResponseResult {
  /// The file edit that is to be applied to the given file to affect the
  /// organizing.
  SourceFileEdit edit;

  EditOrganizeDirectivesResult(this.edit);

  factory EditOrganizeDirectivesResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      SourceFileEdit edit;
      if (json.containsKey('edit')) {
        edit = SourceFileEdit.fromJson(
          jsonDecoder,
          '$jsonPath.edit',
          json['edit'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'edit');
      }
      return EditOrganizeDirectivesResult(edit);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'edit.organizeDirectives result',
        json,
      );
    }
  }

  factory EditOrganizeDirectivesResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditOrganizeDirectivesResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['edit'] = edit.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditOrganizeDirectivesResult) {
      return edit == other.edit;
    }
    return false;
  }

  @override
  int get hashCode => edit.hashCode;
}

/// edit.sortMembers params
///
/// {
///   "file": FilePath
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditSortMembersParams implements RequestParams {
  /// The Dart file to sort.
  String file;

  EditSortMembersParams(this.file);

  factory EditSortMembersParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      return EditSortMembersParams(file);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.sortMembers params', json);
    }
  }

  factory EditSortMembersParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditSortMembersParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'edit.sortMembers',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditSortMembersParams) {
      return file == other.file;
    }
    return false;
  }

  @override
  int get hashCode => file.hashCode;
}

/// edit.sortMembers result
///
/// {
///   "edit": SourceFileEdit
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditSortMembersResult implements ResponseResult {
  /// The file edit that is to be applied to the given file to affect the
  /// sorting.
  SourceFileEdit edit;

  EditSortMembersResult(this.edit);

  factory EditSortMembersResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      SourceFileEdit edit;
      if (json.containsKey('edit')) {
        edit = SourceFileEdit.fromJson(
          jsonDecoder,
          '$jsonPath.edit',
          json['edit'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'edit');
      }
      return EditSortMembersResult(edit);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'edit.sortMembers result', json);
    }
  }

  factory EditSortMembersResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return EditSortMembersResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['edit'] = edit.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is EditSortMembersResult) {
      return edit == other.edit;
    }
    return false;
  }

  @override
  int get hashCode => edit.hashCode;
}

/// ElementDeclaration
///
/// {
///   "name": String
///   "kind": ElementKind
///   "fileIndex": int
///   "offset": int
///   "line": int
///   "column": int
///   "codeOffset": int
///   "codeLength": int
///   "className": optional String
///   "mixinName": optional String
///   "parameters": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ElementDeclaration implements HasToJson {
  /// The name of the declaration.
  String name;

  /// The kind of the element that corresponds to the declaration.
  ElementKind kind;

  /// The index of the file (in the enclosing response).
  int fileIndex;

  /// The offset of the declaration name in the file.
  int offset;

  /// The one-based index of the line containing the declaration name.
  int line;

  /// The one-based index of the column containing the declaration name.
  int column;

  /// The offset of the first character of the declaration code in the file.
  int codeOffset;

  /// The length of the declaration code in the file.
  int codeLength;

  /// The name of the class enclosing this declaration. If the declaration is
  /// not a class member, this field will be absent.
  String? className;

  /// The name of the mixin enclosing this declaration. If the declaration is
  /// not a mixin member, this field will be absent.
  String? mixinName;

  /// The parameter list for the element. If the element is not a method or
  /// function this field will not be defined. If the element doesn't have
  /// parameters (e.g. getter), this field will not be defined. If the element
  /// has zero parameters, this field will have a value of "()". The value
  /// should not be treated as exact presentation of parameters, it is just
  /// approximation of parameters to give the user general idea.
  String? parameters;

  ElementDeclaration(
    this.name,
    this.kind,
    this.fileIndex,
    this.offset,
    this.line,
    this.column,
    this.codeOffset,
    this.codeLength, {
    this.className,
    this.mixinName,
    this.parameters,
  });

  factory ElementDeclaration.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      ElementKind kind;
      if (json.containsKey('kind')) {
        kind = ElementKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kind');
      }
      int fileIndex;
      if (json.containsKey('fileIndex')) {
        fileIndex = jsonDecoder.decodeInt(
          '$jsonPath.fileIndex',
          json['fileIndex'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'fileIndex');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int line;
      if (json.containsKey('line')) {
        line = jsonDecoder.decodeInt('$jsonPath.line', json['line']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'line');
      }
      int column;
      if (json.containsKey('column')) {
        column = jsonDecoder.decodeInt('$jsonPath.column', json['column']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'column');
      }
      int codeOffset;
      if (json.containsKey('codeOffset')) {
        codeOffset = jsonDecoder.decodeInt(
          '$jsonPath.codeOffset',
          json['codeOffset'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'codeOffset');
      }
      int codeLength;
      if (json.containsKey('codeLength')) {
        codeLength = jsonDecoder.decodeInt(
          '$jsonPath.codeLength',
          json['codeLength'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'codeLength');
      }
      String? className;
      if (json.containsKey('className')) {
        className = jsonDecoder.decodeString(
          '$jsonPath.className',
          json['className'],
        );
      }
      String? mixinName;
      if (json.containsKey('mixinName')) {
        mixinName = jsonDecoder.decodeString(
          '$jsonPath.mixinName',
          json['mixinName'],
        );
      }
      String? parameters;
      if (json.containsKey('parameters')) {
        parameters = jsonDecoder.decodeString(
          '$jsonPath.parameters',
          json['parameters'],
        );
      }
      return ElementDeclaration(
        name,
        kind,
        fileIndex,
        offset,
        line,
        column,
        codeOffset,
        codeLength,
        className: className,
        mixinName: mixinName,
        parameters: parameters,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ElementDeclaration', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    result['fileIndex'] = fileIndex;
    result['offset'] = offset;
    result['line'] = line;
    result['column'] = column;
    result['codeOffset'] = codeOffset;
    result['codeLength'] = codeLength;
    var className = this.className;
    if (className != null) {
      result['className'] = className;
    }
    var mixinName = this.mixinName;
    if (mixinName != null) {
      result['mixinName'] = mixinName;
    }
    var parameters = this.parameters;
    if (parameters != null) {
      result['parameters'] = parameters;
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ElementDeclaration) {
      return name == other.name &&
          kind == other.kind &&
          fileIndex == other.fileIndex &&
          offset == other.offset &&
          line == other.line &&
          column == other.column &&
          codeOffset == other.codeOffset &&
          codeLength == other.codeLength &&
          className == other.className &&
          mixinName == other.mixinName &&
          parameters == other.parameters;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    name,
    kind,
    fileIndex,
    offset,
    line,
    column,
    codeOffset,
    codeLength,
    className,
    mixinName,
    parameters,
  );
}

/// ExecutableFile
///
/// {
///   "file": FilePath
///   "kind": ExecutableKind
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutableFile implements HasToJson {
  /// The path of the executable file.
  String file;

  /// The kind of the executable file.
  ExecutableKind kind;

  ExecutableFile(this.file, this.kind);

  factory ExecutableFile.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      ExecutableKind kind;
      if (json.containsKey('kind')) {
        kind = ExecutableKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kind');
      }
      return ExecutableFile(file, kind);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ExecutableFile', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutableFile) {
      return file == other.file && kind == other.kind;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, kind);
}

/// ExecutableKind
///
/// enum {
///   CLIENT
///   EITHER
///   NOT_EXECUTABLE
///   SERVER
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum ExecutableKind {
  CLIENT,

  EITHER,

  NOT_EXECUTABLE,

  SERVER;

  factory ExecutableKind.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'ExecutableKind', json);
  }

  @override
  String toString() => 'ExecutableKind.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// execution.createContext params
///
/// {
///   "contextRoot": FilePath
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionCreateContextParams implements RequestParams {
  /// The path of the Dart or HTML file that will be launched, or the path of
  /// the directory containing the file.
  String contextRoot;

  ExecutionCreateContextParams(this.contextRoot);

  factory ExecutionCreateContextParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String contextRoot;
      if (json.containsKey('contextRoot')) {
        contextRoot =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString(
                '$jsonPath.contextRoot',
                json['contextRoot'],
              ),
            ) ??
            jsonDecoder.decodeString(
              '$jsonPath.contextRoot',
              json['contextRoot'],
            );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'contextRoot');
      }
      return ExecutionCreateContextParams(contextRoot);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'execution.createContext params',
        json,
      );
    }
  }

  factory ExecutionCreateContextParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExecutionCreateContextParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['contextRoot'] =
        clientUriConverter?.toClientFilePath(contextRoot) ?? contextRoot;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'execution.createContext',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutionCreateContextParams) {
      return contextRoot == other.contextRoot;
    }
    return false;
  }

  @override
  int get hashCode => contextRoot.hashCode;
}

/// execution.createContext result
///
/// {
///   "id": ExecutionContextId
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionCreateContextResult implements ResponseResult {
  /// The identifier used to refer to the execution context that was created.
  String id;

  ExecutionCreateContextResult(this.id);

  factory ExecutionCreateContextResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeString('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      return ExecutionCreateContextResult(id);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'execution.createContext result',
        json,
      );
    }
  }

  factory ExecutionCreateContextResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExecutionCreateContextResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['id'] = id;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutionCreateContextResult) {
      return id == other.id;
    }
    return false;
  }

  @override
  int get hashCode => id.hashCode;
}

/// execution.deleteContext params
///
/// {
///   "id": ExecutionContextId
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionDeleteContextParams implements RequestParams {
  /// The identifier of the execution context that is to be deleted.
  String id;

  ExecutionDeleteContextParams(this.id);

  factory ExecutionDeleteContextParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeString('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      return ExecutionDeleteContextParams(id);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'execution.deleteContext params',
        json,
      );
    }
  }

  factory ExecutionDeleteContextParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExecutionDeleteContextParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['id'] = id;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'execution.deleteContext',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutionDeleteContextParams) {
      return id == other.id;
    }
    return false;
  }

  @override
  int get hashCode => id.hashCode;
}

/// execution.deleteContext result
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionDeleteContextResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is ExecutionDeleteContextResult;

  @override
  int get hashCode => 479954425;
}

/// execution.getSuggestions params
///
/// {
///   "code": String
///   "offset": int
///   "contextFile": FilePath
///   "contextOffset": int
///   "variables": List<RuntimeCompletionVariable>
///   "expressions": optional List<RuntimeCompletionExpression>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionGetSuggestionsParams implements RequestParams {
  /// The code to get suggestions in.
  String code;

  /// The offset within the code to get suggestions at.
  int offset;

  /// 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).
  String contextFile;

  /// The offset in the context file, e.g. the line offset in the current
  /// debugger frame.
  int contextOffset;

  /// The runtime context variables that are potentially referenced in the
  /// code.
  List<RuntimeCompletionVariable> variables;

  /// 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.
  List<RuntimeCompletionExpression>? expressions;

  ExecutionGetSuggestionsParams(
    this.code,
    this.offset,
    this.contextFile,
    this.contextOffset,
    this.variables, {
    this.expressions,
  });

  factory ExecutionGetSuggestionsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String code;
      if (json.containsKey('code')) {
        code = jsonDecoder.decodeString('$jsonPath.code', json['code']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'code');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      String contextFile;
      if (json.containsKey('contextFile')) {
        contextFile =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString(
                '$jsonPath.contextFile',
                json['contextFile'],
              ),
            ) ??
            jsonDecoder.decodeString(
              '$jsonPath.contextFile',
              json['contextFile'],
            );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'contextFile');
      }
      int contextOffset;
      if (json.containsKey('contextOffset')) {
        contextOffset = jsonDecoder.decodeInt(
          '$jsonPath.contextOffset',
          json['contextOffset'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'contextOffset');
      }
      List<RuntimeCompletionVariable> variables;
      if (json.containsKey('variables')) {
        variables = jsonDecoder.decodeList(
          '$jsonPath.variables',
          json['variables'],
          (String jsonPath, Object? json) => RuntimeCompletionVariable.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'variables');
      }
      List<RuntimeCompletionExpression>? expressions;
      if (json.containsKey('expressions')) {
        expressions = jsonDecoder.decodeList(
          '$jsonPath.expressions',
          json['expressions'],
          (String jsonPath, Object? json) =>
              RuntimeCompletionExpression.fromJson(
                jsonDecoder,
                jsonPath,
                json,
                clientUriConverter: clientUriConverter,
              ),
        );
      }
      return ExecutionGetSuggestionsParams(
        code,
        offset,
        contextFile,
        contextOffset,
        variables,
        expressions: expressions,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'execution.getSuggestions params',
        json,
      );
    }
  }

  factory ExecutionGetSuggestionsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExecutionGetSuggestionsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['code'] = code;
    result['offset'] = offset;
    result['contextFile'] =
        clientUriConverter?.toClientFilePath(contextFile) ?? contextFile;
    result['contextOffset'] = contextOffset;
    result['variables'] =
        variables
            .map(
              (RuntimeCompletionVariable value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    var expressions = this.expressions;
    if (expressions != null) {
      result['expressions'] =
          expressions
              .map(
                (RuntimeCompletionExpression value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'execution.getSuggestions',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutionGetSuggestionsParams) {
      return code == other.code &&
          offset == other.offset &&
          contextFile == other.contextFile &&
          contextOffset == other.contextOffset &&
          listEqual(
            variables,
            other.variables,
            (RuntimeCompletionVariable a, RuntimeCompletionVariable b) =>
                a == b,
          ) &&
          listEqual(
            expressions,
            other.expressions,
            (RuntimeCompletionExpression a, RuntimeCompletionExpression b) =>
                a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    code,
    offset,
    contextFile,
    contextOffset,
    Object.hashAll(variables),
    Object.hashAll(expressions ?? []),
  );
}

/// execution.getSuggestions result
///
/// {
///   "suggestions": optional List<CompletionSuggestion>
///   "expressions": optional List<RuntimeCompletionExpression>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionGetSuggestionsResult implements ResponseResult {
  /// The completion suggestions. In contrast to usual completion requests,
  /// 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.
  List<CompletionSuggestion>? suggestions;

  /// 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.
  List<RuntimeCompletionExpression>? expressions;

  ExecutionGetSuggestionsResult({this.suggestions, this.expressions});

  factory ExecutionGetSuggestionsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<CompletionSuggestion>? suggestions;
      if (json.containsKey('suggestions')) {
        suggestions = jsonDecoder.decodeList(
          '$jsonPath.suggestions',
          json['suggestions'],
          (String jsonPath, Object? json) => CompletionSuggestion.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      }
      List<RuntimeCompletionExpression>? expressions;
      if (json.containsKey('expressions')) {
        expressions = jsonDecoder.decodeList(
          '$jsonPath.expressions',
          json['expressions'],
          (String jsonPath, Object? json) =>
              RuntimeCompletionExpression.fromJson(
                jsonDecoder,
                jsonPath,
                json,
                clientUriConverter: clientUriConverter,
              ),
        );
      }
      return ExecutionGetSuggestionsResult(
        suggestions: suggestions,
        expressions: expressions,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'execution.getSuggestions result',
        json,
      );
    }
  }

  factory ExecutionGetSuggestionsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExecutionGetSuggestionsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var suggestions = this.suggestions;
    if (suggestions != null) {
      result['suggestions'] =
          suggestions
              .map(
                (CompletionSuggestion value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    var expressions = this.expressions;
    if (expressions != null) {
      result['expressions'] =
          expressions
              .map(
                (RuntimeCompletionExpression value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutionGetSuggestionsResult) {
      return listEqual(
            suggestions,
            other.suggestions,
            (CompletionSuggestion a, CompletionSuggestion b) => a == b,
          ) &&
          listEqual(
            expressions,
            other.expressions,
            (RuntimeCompletionExpression a, RuntimeCompletionExpression b) =>
                a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    Object.hashAll(suggestions ?? []),
    Object.hashAll(expressions ?? []),
  );
}

/// execution.launchData params
///
/// {
///   "file": FilePath
///   "kind": optional ExecutableKind
///   "referencedFiles": optional List<FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionLaunchDataParams implements HasToJson {
  /// The file for which launch data is being provided. This will either be a
  /// Dart library or an HTML file.
  String file;

  /// The kind of the executable file. This field is omitted if the file is not
  /// a Dart file.
  ExecutableKind? kind;

  /// A list of the Dart files that are referenced by the file. This field is
  /// omitted if the file is not an HTML file.
  List<String>? referencedFiles;

  ExecutionLaunchDataParams(this.file, {this.kind, this.referencedFiles});

  factory ExecutionLaunchDataParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      ExecutableKind? kind;
      if (json.containsKey('kind')) {
        kind = ExecutableKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      }
      List<String>? referencedFiles;
      if (json.containsKey('referencedFiles')) {
        referencedFiles = jsonDecoder.decodeList(
          '$jsonPath.referencedFiles',
          json['referencedFiles'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      }
      return ExecutionLaunchDataParams(
        file,
        kind: kind,
        referencedFiles: referencedFiles,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'execution.launchData params', json);
    }
  }

  factory ExecutionLaunchDataParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExecutionLaunchDataParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    var kind = this.kind;
    if (kind != null) {
      result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    }
    var referencedFiles = this.referencedFiles;
    if (referencedFiles != null) {
      result['referencedFiles'] =
          referencedFiles
              .map(
                (String value) =>
                    clientUriConverter?.toClientFilePath(value) ?? value,
              )
              .toList();
    }
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'execution.launchData',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutionLaunchDataParams) {
      return file == other.file &&
          kind == other.kind &&
          listEqual(
            referencedFiles,
            other.referencedFiles,
            (String a, String b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(file, kind, Object.hashAll(referencedFiles ?? []));
}

/// execution.mapUri params
///
/// {
///   "id": ExecutionContextId
///   "file": optional FilePath
///   "uri": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionMapUriParams implements RequestParams {
  /// The identifier of the execution context in which the URI is to be mapped.
  String id;

  /// The path of the file to be mapped into a URI.
  String? file;

  /// The URI to be mapped into a file path.
  String? uri;

  ExecutionMapUriParams(this.id, {this.file, this.uri});

  factory ExecutionMapUriParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeString('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      String? file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      }
      String? uri;
      if (json.containsKey('uri')) {
        uri = jsonDecoder.decodeString('$jsonPath.uri', json['uri']);
      }
      return ExecutionMapUriParams(id, file: file, uri: uri);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'execution.mapUri params', json);
    }
  }

  factory ExecutionMapUriParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExecutionMapUriParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['id'] = id;
    var file = this.file;
    if (file != null) {
      result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    }
    var uri = this.uri;
    if (uri != null) {
      result['uri'] = uri;
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'execution.mapUri',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutionMapUriParams) {
      return id == other.id && file == other.file && uri == other.uri;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(id, file, uri);
}

/// execution.mapUri result
///
/// {
///   "file": optional FilePath
///   "uri": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionMapUriResult implements ResponseResult {
  /// The file to which the URI was mapped. This field is omitted if the uri
  /// field was not given in the request.
  String? file;

  /// The URI to which the file path was mapped. This field is omitted if the
  /// file field was not given in the request.
  String? uri;

  ExecutionMapUriResult({this.file, this.uri});

  factory ExecutionMapUriResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String? file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      }
      String? uri;
      if (json.containsKey('uri')) {
        uri = jsonDecoder.decodeString('$jsonPath.uri', json['uri']);
      }
      return ExecutionMapUriResult(file: file, uri: uri);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'execution.mapUri result', json);
    }
  }

  factory ExecutionMapUriResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExecutionMapUriResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var file = this.file;
    if (file != null) {
      result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    }
    var uri = this.uri;
    if (uri != null) {
      result['uri'] = uri;
    }
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutionMapUriResult) {
      return file == other.file && uri == other.uri;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, uri);
}

/// ExecutionService
///
/// enum {
///   LAUNCH_DATA
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum ExecutionService {
  LAUNCH_DATA;

  factory ExecutionService.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'ExecutionService', json);
  }

  @override
  String toString() => 'ExecutionService.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// execution.setSubscriptions params
///
/// {
///   "subscriptions": List<ExecutionService>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionSetSubscriptionsParams implements RequestParams {
  /// A list of the services being subscribed to.
  List<ExecutionService> subscriptions;

  ExecutionSetSubscriptionsParams(this.subscriptions);

  factory ExecutionSetSubscriptionsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<ExecutionService> subscriptions;
      if (json.containsKey('subscriptions')) {
        subscriptions = jsonDecoder.decodeList(
          '$jsonPath.subscriptions',
          json['subscriptions'],
          (String jsonPath, Object? json) => ExecutionService.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'subscriptions');
      }
      return ExecutionSetSubscriptionsParams(subscriptions);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'execution.setSubscriptions params',
        json,
      );
    }
  }

  factory ExecutionSetSubscriptionsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExecutionSetSubscriptionsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['subscriptions'] =
        subscriptions
            .map(
              (ExecutionService value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'execution.setSubscriptions',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExecutionSetSubscriptionsParams) {
      return listEqual(
        subscriptions,
        other.subscriptions,
        (ExecutionService a, ExecutionService b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(subscriptions);
}

/// execution.setSubscriptions result
///
/// Clients may not extend, implement or mix-in this class.
class ExecutionSetSubscriptionsResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is ExecutionSetSubscriptionsResult;

  @override
  int get hashCode => 287678780;
}

/// ExistingImport
///
/// {
///   "uri": int
///   "elements": List<int>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExistingImport implements HasToJson {
  /// The URI of the imported library. It is an index in the `strings` field,
  /// in the enclosing `ExistingImports` and its `ImportedElementSet` object.
  int uri;

  /// The list of indexes of elements, in the enclosing `ExistingImports`
  /// object.
  List<int> elements;

  ExistingImport(this.uri, this.elements);

  factory ExistingImport.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int uri;
      if (json.containsKey('uri')) {
        uri = jsonDecoder.decodeInt('$jsonPath.uri', json['uri']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'uri');
      }
      List<int> elements;
      if (json.containsKey('elements')) {
        elements = jsonDecoder.decodeList(
          '$jsonPath.elements',
          json['elements'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'elements');
      }
      return ExistingImport(uri, elements);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ExistingImport', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['uri'] = uri;
    result['elements'] = elements;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExistingImport) {
      return uri == other.uri &&
          listEqual(elements, other.elements, (int a, int b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(uri, Object.hashAll(elements));
}

/// ExistingImports
///
/// {
///   "elements": ImportedElementSet
///   "imports": List<ExistingImport>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExistingImports implements HasToJson {
  /// The set of all unique imported elements for all imports.
  ImportedElementSet elements;

  /// The list of imports in the library.
  List<ExistingImport> imports;

  ExistingImports(this.elements, this.imports);

  factory ExistingImports.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      ImportedElementSet elements;
      if (json.containsKey('elements')) {
        elements = ImportedElementSet.fromJson(
          jsonDecoder,
          '$jsonPath.elements',
          json['elements'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'elements');
      }
      List<ExistingImport> imports;
      if (json.containsKey('imports')) {
        imports = jsonDecoder.decodeList(
          '$jsonPath.imports',
          json['imports'],
          (String jsonPath, Object? json) => ExistingImport.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'imports');
      }
      return ExistingImports(elements, imports);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ExistingImports', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['elements'] = elements.toJson(
      clientUriConverter: clientUriConverter,
    );
    result['imports'] =
        imports
            .map(
              (ExistingImport value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExistingImports) {
      return elements == other.elements &&
          listEqual(
            imports,
            other.imports,
            (ExistingImport a, ExistingImport b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(elements, Object.hashAll(imports));
}

/// extractLocalVariable feedback
///
/// {
///   "coveringExpressionOffsets": optional List<int>
///   "coveringExpressionLengths": optional List<int>
///   "names": List<String>
///   "offsets": List<int>
///   "lengths": List<int>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExtractLocalVariableFeedback extends RefactoringFeedback {
  /// The offsets of the expressions that cover the specified selection, from
  /// the down most to the up most.
  List<int>? coveringExpressionOffsets;

  /// The lengths of the expressions that cover the specified selection, from
  /// the down most to the up most.
  List<int>? coveringExpressionLengths;

  /// The proposed names for the local variable.
  List<String> names;

  /// The offsets of the expressions that would be replaced by a reference to
  /// the variable.
  List<int> offsets;

  /// The lengths of the expressions that would be replaced by a reference to
  /// the variable. The lengths correspond to the offsets. In other words, for
  /// a given expression, if the offset of that expression is `offsets[i]`,
  /// then the length of that expression is `lengths[i]`.
  List<int> lengths;

  ExtractLocalVariableFeedback(
    this.names,
    this.offsets,
    this.lengths, {
    this.coveringExpressionOffsets,
    this.coveringExpressionLengths,
  });

  factory ExtractLocalVariableFeedback.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<int>? coveringExpressionOffsets;
      if (json.containsKey('coveringExpressionOffsets')) {
        coveringExpressionOffsets = jsonDecoder.decodeList(
          '$jsonPath.coveringExpressionOffsets',
          json['coveringExpressionOffsets'],
          jsonDecoder.decodeInt,
        );
      }
      List<int>? coveringExpressionLengths;
      if (json.containsKey('coveringExpressionLengths')) {
        coveringExpressionLengths = jsonDecoder.decodeList(
          '$jsonPath.coveringExpressionLengths',
          json['coveringExpressionLengths'],
          jsonDecoder.decodeInt,
        );
      }
      List<String> names;
      if (json.containsKey('names')) {
        names = jsonDecoder.decodeList(
          '$jsonPath.names',
          json['names'],
          jsonDecoder.decodeString,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'names');
      }
      List<int> offsets;
      if (json.containsKey('offsets')) {
        offsets = jsonDecoder.decodeList(
          '$jsonPath.offsets',
          json['offsets'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offsets');
      }
      List<int> lengths;
      if (json.containsKey('lengths')) {
        lengths = jsonDecoder.decodeList(
          '$jsonPath.lengths',
          json['lengths'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'lengths');
      }
      return ExtractLocalVariableFeedback(
        names,
        offsets,
        lengths,
        coveringExpressionOffsets: coveringExpressionOffsets,
        coveringExpressionLengths: coveringExpressionLengths,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'extractLocalVariable feedback',
        json,
      );
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var coveringExpressionOffsets = this.coveringExpressionOffsets;
    if (coveringExpressionOffsets != null) {
      result['coveringExpressionOffsets'] = coveringExpressionOffsets;
    }
    var coveringExpressionLengths = this.coveringExpressionLengths;
    if (coveringExpressionLengths != null) {
      result['coveringExpressionLengths'] = coveringExpressionLengths;
    }
    result['names'] = names;
    result['offsets'] = offsets;
    result['lengths'] = lengths;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExtractLocalVariableFeedback) {
      return listEqual(
            coveringExpressionOffsets,
            other.coveringExpressionOffsets,
            (int a, int b) => a == b,
          ) &&
          listEqual(
            coveringExpressionLengths,
            other.coveringExpressionLengths,
            (int a, int b) => a == b,
          ) &&
          listEqual(names, other.names, (String a, String b) => a == b) &&
          listEqual(offsets, other.offsets, (int a, int b) => a == b) &&
          listEqual(lengths, other.lengths, (int a, int b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    Object.hashAll(coveringExpressionOffsets ?? []),
    Object.hashAll(coveringExpressionLengths ?? []),
    Object.hashAll(names),
    Object.hashAll(offsets),
    Object.hashAll(lengths),
  );
}

/// extractLocalVariable options
///
/// {
///   "name": String
///   "extractAll": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExtractLocalVariableOptions extends RefactoringOptions {
  /// The name that the local variable should be given.
  String name;

  /// True if all occurrences of the expression within the scope in which the
  /// variable will be defined should be replaced by a reference to the local
  /// variable. The expression used to initiate the refactoring will always be
  /// replaced.
  bool extractAll;

  ExtractLocalVariableOptions(this.name, this.extractAll);

  factory ExtractLocalVariableOptions.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      bool extractAll;
      if (json.containsKey('extractAll')) {
        extractAll = jsonDecoder.decodeBool(
          '$jsonPath.extractAll',
          json['extractAll'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'extractAll');
      }
      return ExtractLocalVariableOptions(name, extractAll);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'extractLocalVariable options',
        json,
      );
    }
  }

  factory ExtractLocalVariableOptions.fromRefactoringParams(
    EditGetRefactoringParams refactoringParams,
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExtractLocalVariableOptions.fromJson(
      RequestDecoder(request),
      'options',
      refactoringParams.options,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    result['extractAll'] = extractAll;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExtractLocalVariableOptions) {
      return name == other.name && extractAll == other.extractAll;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(name, extractAll);
}

/// extractMethod feedback
///
/// {
///   "offset": int
///   "length": int
///   "returnType": String
///   "names": List<String>
///   "canCreateGetter": bool
///   "parameters": List<RefactoringMethodParameter>
///   "offsets": List<int>
///   "lengths": List<int>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExtractMethodFeedback extends RefactoringFeedback {
  /// The offset to the beginning of the expression or statements that will be
  /// extracted.
  int offset;

  /// The length of the expression or statements that will be extracted.
  int length;

  /// The proposed return type for the method. If the returned element does not
  /// have a declared return type, this field will contain an empty string.
  String returnType;

  /// The proposed names for the method.
  List<String> names;

  /// True if a getter could be created rather than a method.
  bool canCreateGetter;

  /// The proposed parameters for the method.
  List<RefactoringMethodParameter> parameters;

  /// The offsets of the expressions or statements that would be replaced by an
  /// invocation of the method.
  List<int> offsets;

  /// The lengths of the expressions or statements that would be replaced by an
  /// invocation of the method. The lengths correspond to the offsets. In other
  /// words, for a given expression (or block of statements), if the offset of
  /// that expression is `offsets[i]`, then the length of that expression is
  /// `lengths[i]`.
  List<int> lengths;

  ExtractMethodFeedback(
    this.offset,
    this.length,
    this.returnType,
    this.names,
    this.canCreateGetter,
    this.parameters,
    this.offsets,
    this.lengths,
  );

  factory ExtractMethodFeedback.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      String returnType;
      if (json.containsKey('returnType')) {
        returnType = jsonDecoder.decodeString(
          '$jsonPath.returnType',
          json['returnType'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'returnType');
      }
      List<String> names;
      if (json.containsKey('names')) {
        names = jsonDecoder.decodeList(
          '$jsonPath.names',
          json['names'],
          jsonDecoder.decodeString,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'names');
      }
      bool canCreateGetter;
      if (json.containsKey('canCreateGetter')) {
        canCreateGetter = jsonDecoder.decodeBool(
          '$jsonPath.canCreateGetter',
          json['canCreateGetter'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'canCreateGetter');
      }
      List<RefactoringMethodParameter> parameters;
      if (json.containsKey('parameters')) {
        parameters = jsonDecoder.decodeList(
          '$jsonPath.parameters',
          json['parameters'],
          (String jsonPath, Object? json) =>
              RefactoringMethodParameter.fromJson(
                jsonDecoder,
                jsonPath,
                json,
                clientUriConverter: clientUriConverter,
              ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'parameters');
      }
      List<int> offsets;
      if (json.containsKey('offsets')) {
        offsets = jsonDecoder.decodeList(
          '$jsonPath.offsets',
          json['offsets'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offsets');
      }
      List<int> lengths;
      if (json.containsKey('lengths')) {
        lengths = jsonDecoder.decodeList(
          '$jsonPath.lengths',
          json['lengths'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'lengths');
      }
      return ExtractMethodFeedback(
        offset,
        length,
        returnType,
        names,
        canCreateGetter,
        parameters,
        offsets,
        lengths,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'extractMethod feedback', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['offset'] = offset;
    result['length'] = length;
    result['returnType'] = returnType;
    result['names'] = names;
    result['canCreateGetter'] = canCreateGetter;
    result['parameters'] =
        parameters
            .map(
              (RefactoringMethodParameter value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['offsets'] = offsets;
    result['lengths'] = lengths;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExtractMethodFeedback) {
      return offset == other.offset &&
          length == other.length &&
          returnType == other.returnType &&
          listEqual(names, other.names, (String a, String b) => a == b) &&
          canCreateGetter == other.canCreateGetter &&
          listEqual(
            parameters,
            other.parameters,
            (RefactoringMethodParameter a, RefactoringMethodParameter b) =>
                a == b,
          ) &&
          listEqual(offsets, other.offsets, (int a, int b) => a == b) &&
          listEqual(lengths, other.lengths, (int a, int b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    offset,
    length,
    returnType,
    Object.hashAll(names),
    canCreateGetter,
    Object.hashAll(parameters),
    Object.hashAll(offsets),
    Object.hashAll(lengths),
  );
}

/// extractMethod options
///
/// {
///   "returnType": String
///   "createGetter": bool
///   "name": String
///   "parameters": List<RefactoringMethodParameter>
///   "extractAll": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExtractMethodOptions extends RefactoringOptions {
  /// The return type that should be defined for the method.
  String returnType;

  /// True if a getter should be created rather than a method. It is an error
  /// if this field is true and the list of parameters is non-empty.
  bool createGetter;

  /// The name that the method should be given.
  String name;

  /// The parameters that should be defined for the method.
  ///
  /// It is an error if a REQUIRED or NAMED parameter follows a POSITIONAL
  /// parameter. It is an error if a REQUIRED or POSITIONAL parameter follows a
  /// NAMED parameter.
  ///
  /// - To change the order and/or update proposed parameters, add parameters
  ///   with the same identifiers as proposed.
  /// - To add new parameters, omit their identifier.
  /// - To remove some parameters, omit them in this list.
  List<RefactoringMethodParameter> parameters;

  /// True if all occurrences of the expression or statements should be
  /// replaced by an invocation of the method. The expression or statements
  /// used to initiate the refactoring will always be replaced.
  bool extractAll;

  ExtractMethodOptions(
    this.returnType,
    this.createGetter,
    this.name,
    this.parameters,
    this.extractAll,
  );

  factory ExtractMethodOptions.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String returnType;
      if (json.containsKey('returnType')) {
        returnType = jsonDecoder.decodeString(
          '$jsonPath.returnType',
          json['returnType'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'returnType');
      }
      bool createGetter;
      if (json.containsKey('createGetter')) {
        createGetter = jsonDecoder.decodeBool(
          '$jsonPath.createGetter',
          json['createGetter'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'createGetter');
      }
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      List<RefactoringMethodParameter> parameters;
      if (json.containsKey('parameters')) {
        parameters = jsonDecoder.decodeList(
          '$jsonPath.parameters',
          json['parameters'],
          (String jsonPath, Object? json) =>
              RefactoringMethodParameter.fromJson(
                jsonDecoder,
                jsonPath,
                json,
                clientUriConverter: clientUriConverter,
              ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'parameters');
      }
      bool extractAll;
      if (json.containsKey('extractAll')) {
        extractAll = jsonDecoder.decodeBool(
          '$jsonPath.extractAll',
          json['extractAll'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'extractAll');
      }
      return ExtractMethodOptions(
        returnType,
        createGetter,
        name,
        parameters,
        extractAll,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'extractMethod options', json);
    }
  }

  factory ExtractMethodOptions.fromRefactoringParams(
    EditGetRefactoringParams refactoringParams,
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExtractMethodOptions.fromJson(
      RequestDecoder(request),
      'options',
      refactoringParams.options,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['returnType'] = returnType;
    result['createGetter'] = createGetter;
    result['name'] = name;
    result['parameters'] =
        parameters
            .map(
              (RefactoringMethodParameter value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['extractAll'] = extractAll;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExtractMethodOptions) {
      return returnType == other.returnType &&
          createGetter == other.createGetter &&
          name == other.name &&
          listEqual(
            parameters,
            other.parameters,
            (RefactoringMethodParameter a, RefactoringMethodParameter b) =>
                a == b,
          ) &&
          extractAll == other.extractAll;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    returnType,
    createGetter,
    name,
    Object.hashAll(parameters),
    extractAll,
  );
}

/// extractWidget feedback
///
/// {
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExtractWidgetFeedback extends RefactoringFeedback {
  ExtractWidgetFeedback();

  factory ExtractWidgetFeedback.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      return ExtractWidgetFeedback();
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'extractWidget feedback', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExtractWidgetFeedback) {
      return true;
    }
    return false;
  }

  @override
  int get hashCode => 0;
}

/// extractWidget options
///
/// {
///   "name": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ExtractWidgetOptions extends RefactoringOptions {
  /// The name that the widget class should be given.
  String name;

  ExtractWidgetOptions(this.name);

  factory ExtractWidgetOptions.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      return ExtractWidgetOptions(name);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'extractWidget options', json);
    }
  }

  factory ExtractWidgetOptions.fromRefactoringParams(
    EditGetRefactoringParams refactoringParams,
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ExtractWidgetOptions.fromJson(
      RequestDecoder(request),
      'options',
      refactoringParams.options,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ExtractWidgetOptions) {
      return name == other.name;
    }
    return false;
  }

  @override
  int get hashCode => name.hashCode;
}

/// FileKind
///
/// enum {
///   LIBRARY
///   PART
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum FileKind {
  LIBRARY,

  PART;

  factory FileKind.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'FileKind', json);
  }

  @override
  String toString() => 'FileKind.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// flutter.getWidgetDescription params
///
/// {
///   "file": FilePath
///   "offset": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterGetWidgetDescriptionParams implements RequestParams {
  /// The file where the widget instance is created.
  String file;

  /// The offset in the file where the widget instance is created.
  int offset;

  FlutterGetWidgetDescriptionParams(this.file, this.offset);

  factory FlutterGetWidgetDescriptionParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      return FlutterGetWidgetDescriptionParams(file, offset);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'flutter.getWidgetDescription params',
        json,
      );
    }
  }

  factory FlutterGetWidgetDescriptionParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return FlutterGetWidgetDescriptionParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'flutter.getWidgetDescription',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterGetWidgetDescriptionParams) {
      return file == other.file && offset == other.offset;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset);
}

/// flutter.getWidgetDescription result
///
/// {
///   "properties": List<FlutterWidgetProperty>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterGetWidgetDescriptionResult implements ResponseResult {
  /// 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.
  List<FlutterWidgetProperty> properties;

  FlutterGetWidgetDescriptionResult(this.properties);

  factory FlutterGetWidgetDescriptionResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<FlutterWidgetProperty> properties;
      if (json.containsKey('properties')) {
        properties = jsonDecoder.decodeList(
          '$jsonPath.properties',
          json['properties'],
          (String jsonPath, Object? json) => FlutterWidgetProperty.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'properties');
      }
      return FlutterGetWidgetDescriptionResult(properties);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'flutter.getWidgetDescription result',
        json,
      );
    }
  }

  factory FlutterGetWidgetDescriptionResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return FlutterGetWidgetDescriptionResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['properties'] =
        properties
            .map(
              (FlutterWidgetProperty value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterGetWidgetDescriptionResult) {
      return listEqual(
        properties,
        other.properties,
        (FlutterWidgetProperty a, FlutterWidgetProperty b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(properties);
}

/// FlutterOutline
///
/// {
///   "kind": FlutterOutlineKind
///   "offset": int
///   "length": int
///   "codeOffset": int
///   "codeLength": int
///   "label": optional String
///   "dartElement": optional Element
///   "attributes": optional List<FlutterOutlineAttribute>
///   "className": optional String
///   "parentAssociationLabel": optional String
///   "variableName": optional String
///   "children": optional List<FlutterOutline>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterOutline implements HasToJson {
  /// The kind of the node.
  FlutterOutlineKind kind;

  /// The offset of the first character of the element. This is different than
  /// the offset in the Element, which is the offset of the name of the
  /// element. It can be used, for example, to map locations in the file back
  /// to an outline.
  int offset;

  /// The length of the element.
  int length;

  /// The offset of the first character of the element code, which is neither
  /// documentation, nor annotation.
  int codeOffset;

  /// The length of the element code.
  int codeLength;

  /// The text label of the node children of the node. It is provided for any
  /// FlutterOutlineKind.GENERIC node, where better information is not
  /// available.
  String? label;

  /// If this node is a Dart element, the description of it; omitted otherwise.
  Element? dartElement;

  /// Additional attributes for this node, which might be interesting to
  /// display on the client. These attributes are usually arguments for the
  /// instance creation or the invocation that created the widget.
  List<FlutterOutlineAttribute>? attributes;

  /// If the node creates a new class instance, or a reference to an instance,
  /// this field has the name of the class.
  String? className;

  /// A short text description how this node is associated with the parent
  /// node. For example "appBar" or "body" in Scaffold.
  String? parentAssociationLabel;

  /// If FlutterOutlineKind.VARIABLE, the name of the variable.
  String? variableName;

  /// The children of the node. The field will be omitted if the node has no
  /// children.
  List<FlutterOutline>? children;

  FlutterOutline(
    this.kind,
    this.offset,
    this.length,
    this.codeOffset,
    this.codeLength, {
    this.label,
    this.dartElement,
    this.attributes,
    this.className,
    this.parentAssociationLabel,
    this.variableName,
    this.children,
  });

  factory FlutterOutline.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      FlutterOutlineKind kind;
      if (json.containsKey('kind')) {
        kind = FlutterOutlineKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kind');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      int codeOffset;
      if (json.containsKey('codeOffset')) {
        codeOffset = jsonDecoder.decodeInt(
          '$jsonPath.codeOffset',
          json['codeOffset'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'codeOffset');
      }
      int codeLength;
      if (json.containsKey('codeLength')) {
        codeLength = jsonDecoder.decodeInt(
          '$jsonPath.codeLength',
          json['codeLength'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'codeLength');
      }
      String? label;
      if (json.containsKey('label')) {
        label = jsonDecoder.decodeString('$jsonPath.label', json['label']);
      }
      Element? dartElement;
      if (json.containsKey('dartElement')) {
        dartElement = Element.fromJson(
          jsonDecoder,
          '$jsonPath.dartElement',
          json['dartElement'],
          clientUriConverter: clientUriConverter,
        );
      }
      List<FlutterOutlineAttribute>? attributes;
      if (json.containsKey('attributes')) {
        attributes = jsonDecoder.decodeList(
          '$jsonPath.attributes',
          json['attributes'],
          (String jsonPath, Object? json) => FlutterOutlineAttribute.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      }
      String? className;
      if (json.containsKey('className')) {
        className = jsonDecoder.decodeString(
          '$jsonPath.className',
          json['className'],
        );
      }
      String? parentAssociationLabel;
      if (json.containsKey('parentAssociationLabel')) {
        parentAssociationLabel = jsonDecoder.decodeString(
          '$jsonPath.parentAssociationLabel',
          json['parentAssociationLabel'],
        );
      }
      String? variableName;
      if (json.containsKey('variableName')) {
        variableName = jsonDecoder.decodeString(
          '$jsonPath.variableName',
          json['variableName'],
        );
      }
      List<FlutterOutline>? children;
      if (json.containsKey('children')) {
        children = jsonDecoder.decodeList(
          '$jsonPath.children',
          json['children'],
          (String jsonPath, Object? json) => FlutterOutline.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      }
      return FlutterOutline(
        kind,
        offset,
        length,
        codeOffset,
        codeLength,
        label: label,
        dartElement: dartElement,
        attributes: attributes,
        className: className,
        parentAssociationLabel: parentAssociationLabel,
        variableName: variableName,
        children: children,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'FlutterOutline', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    result['offset'] = offset;
    result['length'] = length;
    result['codeOffset'] = codeOffset;
    result['codeLength'] = codeLength;
    var label = this.label;
    if (label != null) {
      result['label'] = label;
    }
    var dartElement = this.dartElement;
    if (dartElement != null) {
      result['dartElement'] = dartElement.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var attributes = this.attributes;
    if (attributes != null) {
      result['attributes'] =
          attributes
              .map(
                (FlutterOutlineAttribute value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    var className = this.className;
    if (className != null) {
      result['className'] = className;
    }
    var parentAssociationLabel = this.parentAssociationLabel;
    if (parentAssociationLabel != null) {
      result['parentAssociationLabel'] = parentAssociationLabel;
    }
    var variableName = this.variableName;
    if (variableName != null) {
      result['variableName'] = variableName;
    }
    var children = this.children;
    if (children != null) {
      result['children'] =
          children
              .map(
                (FlutterOutline value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterOutline) {
      return kind == other.kind &&
          offset == other.offset &&
          length == other.length &&
          codeOffset == other.codeOffset &&
          codeLength == other.codeLength &&
          label == other.label &&
          dartElement == other.dartElement &&
          listEqual(
            attributes,
            other.attributes,
            (FlutterOutlineAttribute a, FlutterOutlineAttribute b) => a == b,
          ) &&
          className == other.className &&
          parentAssociationLabel == other.parentAssociationLabel &&
          variableName == other.variableName &&
          listEqual(
            children,
            other.children,
            (FlutterOutline a, FlutterOutline b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    kind,
    offset,
    length,
    codeOffset,
    codeLength,
    label,
    dartElement,
    Object.hashAll(attributes ?? []),
    className,
    parentAssociationLabel,
    variableName,
    Object.hashAll(children ?? []),
  );
}

/// FlutterOutlineAttribute
///
/// {
///   "name": String
///   "label": String
///   "literalValueBoolean": optional bool
///   "literalValueInteger": optional int
///   "literalValueString": optional String
///   "nameLocation": optional Location
///   "valueLocation": optional Location
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterOutlineAttribute implements HasToJson {
  /// The name of the attribute.
  String name;

  /// The label of the attribute value, usually the Dart code. It might be
  /// quite long, the client should abbreviate as needed.
  String label;

  /// The boolean literal value of the attribute. This field is absent if the
  /// value is not a boolean literal.
  bool? literalValueBoolean;

  /// The integer literal value of the attribute. This field is absent if the
  /// value is not an integer literal.
  int? literalValueInteger;

  /// The string literal value of the attribute. This field is absent if the
  /// value is not a string literal.
  String? literalValueString;

  /// If the attribute is a named argument, the location of the name, without
  /// the colon.
  Location? nameLocation;

  /// The location of the value.
  ///
  /// This field is always available, but marked optional for backward
  /// compatibility between new clients with older servers.
  Location? valueLocation;

  FlutterOutlineAttribute(
    this.name,
    this.label, {
    this.literalValueBoolean,
    this.literalValueInteger,
    this.literalValueString,
    this.nameLocation,
    this.valueLocation,
  });

  factory FlutterOutlineAttribute.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      String label;
      if (json.containsKey('label')) {
        label = jsonDecoder.decodeString('$jsonPath.label', json['label']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'label');
      }
      bool? literalValueBoolean;
      if (json.containsKey('literalValueBoolean')) {
        literalValueBoolean = jsonDecoder.decodeBool(
          '$jsonPath.literalValueBoolean',
          json['literalValueBoolean'],
        );
      }
      int? literalValueInteger;
      if (json.containsKey('literalValueInteger')) {
        literalValueInteger = jsonDecoder.decodeInt(
          '$jsonPath.literalValueInteger',
          json['literalValueInteger'],
        );
      }
      String? literalValueString;
      if (json.containsKey('literalValueString')) {
        literalValueString = jsonDecoder.decodeString(
          '$jsonPath.literalValueString',
          json['literalValueString'],
        );
      }
      Location? nameLocation;
      if (json.containsKey('nameLocation')) {
        nameLocation = Location.fromJson(
          jsonDecoder,
          '$jsonPath.nameLocation',
          json['nameLocation'],
          clientUriConverter: clientUriConverter,
        );
      }
      Location? valueLocation;
      if (json.containsKey('valueLocation')) {
        valueLocation = Location.fromJson(
          jsonDecoder,
          '$jsonPath.valueLocation',
          json['valueLocation'],
          clientUriConverter: clientUriConverter,
        );
      }
      return FlutterOutlineAttribute(
        name,
        label,
        literalValueBoolean: literalValueBoolean,
        literalValueInteger: literalValueInteger,
        literalValueString: literalValueString,
        nameLocation: nameLocation,
        valueLocation: valueLocation,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'FlutterOutlineAttribute', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    result['label'] = label;
    var literalValueBoolean = this.literalValueBoolean;
    if (literalValueBoolean != null) {
      result['literalValueBoolean'] = literalValueBoolean;
    }
    var literalValueInteger = this.literalValueInteger;
    if (literalValueInteger != null) {
      result['literalValueInteger'] = literalValueInteger;
    }
    var literalValueString = this.literalValueString;
    if (literalValueString != null) {
      result['literalValueString'] = literalValueString;
    }
    var nameLocation = this.nameLocation;
    if (nameLocation != null) {
      result['nameLocation'] = nameLocation.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var valueLocation = this.valueLocation;
    if (valueLocation != null) {
      result['valueLocation'] = valueLocation.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterOutlineAttribute) {
      return name == other.name &&
          label == other.label &&
          literalValueBoolean == other.literalValueBoolean &&
          literalValueInteger == other.literalValueInteger &&
          literalValueString == other.literalValueString &&
          nameLocation == other.nameLocation &&
          valueLocation == other.valueLocation;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    name,
    label,
    literalValueBoolean,
    literalValueInteger,
    literalValueString,
    nameLocation,
    valueLocation,
  );
}

/// FlutterOutlineKind
///
/// enum {
///   DART_ELEMENT
///   GENERIC
///   NEW_INSTANCE
///   INVOCATION
///   VARIABLE
///   PLACEHOLDER
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum FlutterOutlineKind {
  /// A dart element declaration.
  DART_ELEMENT,

  /// A generic Flutter element, without additional information.
  GENERIC,

  /// A new instance creation.
  NEW_INSTANCE,

  /// An invocation of a method, a top-level function, a function expression,
  /// etc.
  INVOCATION,

  /// A reference to a local variable, or a field.
  VARIABLE,

  /// The parent node has a required Widget. The node works as a placeholder
  /// child to drop a new Widget to.
  PLACEHOLDER;

  factory FlutterOutlineKind.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'FlutterOutlineKind', json);
  }

  @override
  String toString() => 'FlutterOutlineKind.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// flutter.outline params
///
/// {
///   "file": FilePath
///   "outline": FlutterOutline
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterOutlineParams implements HasToJson {
  /// The file with which the outline is associated.
  String file;

  /// The outline associated with the file.
  FlutterOutline outline;

  FlutterOutlineParams(this.file, this.outline);

  factory FlutterOutlineParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      FlutterOutline outline;
      if (json.containsKey('outline')) {
        outline = FlutterOutline.fromJson(
          jsonDecoder,
          '$jsonPath.outline',
          json['outline'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'outline');
      }
      return FlutterOutlineParams(file, outline);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'flutter.outline params', json);
    }
  }

  factory FlutterOutlineParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return FlutterOutlineParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['outline'] = outline.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'flutter.outline',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterOutlineParams) {
      return file == other.file && outline == other.outline;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, outline);
}

/// FlutterService
///
/// enum {
///   OUTLINE
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum FlutterService {
  OUTLINE;

  factory FlutterService.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'FlutterService', json);
  }

  @override
  String toString() => 'FlutterService.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// flutter.setSubscriptions params
///
/// {
///   "subscriptions": Map<FlutterService, List<FilePath>>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterSetSubscriptionsParams implements RequestParams {
  /// A table mapping services to a list of the files being subscribed to the
  /// service.
  Map<FlutterService, List<String>> subscriptions;

  FlutterSetSubscriptionsParams(this.subscriptions);

  factory FlutterSetSubscriptionsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Map<FlutterService, List<String>> subscriptions;
      if (json.containsKey('subscriptions')) {
        subscriptions = jsonDecoder.decodeMap(
          '$jsonPath.subscriptions',
          json['subscriptions'],
          keyDecoder:
              (String jsonPath, Object? json) => FlutterService.fromJson(
                jsonDecoder,
                jsonPath,
                json,
                clientUriConverter: clientUriConverter,
              ),
          valueDecoder:
              (String jsonPath, Object? json) => jsonDecoder.decodeList(
                jsonPath,
                json,
                (String jsonPath, Object? json) =>
                    clientUriConverter?.fromClientFilePath(
                      jsonDecoder.decodeString(jsonPath, json),
                    ) ??
                    jsonDecoder.decodeString(jsonPath, json),
              ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'subscriptions');
      }
      return FlutterSetSubscriptionsParams(subscriptions);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'flutter.setSubscriptions params',
        json,
      );
    }
  }

  factory FlutterSetSubscriptionsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return FlutterSetSubscriptionsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['subscriptions'] = mapMap(
      subscriptions,
      keyCallback:
          (FlutterService value) =>
              value.toJson(clientUriConverter: clientUriConverter),
      valueCallback:
          (List<String> value) =>
              value
                  .map(
                    (String value) =>
                        clientUriConverter?.toClientFilePath(value) ?? value,
                  )
                  .toList(),
    );
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'flutter.setSubscriptions',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterSetSubscriptionsParams) {
      return mapEqual(
        subscriptions,
        other.subscriptions,
        (List<String> a, List<String> b) =>
            listEqual(a, b, (String a, String b) => a == b),
      );
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hashAll([...subscriptions.keys, ...subscriptions.values]);
}

/// flutter.setSubscriptions result
///
/// Clients may not extend, implement or mix-in this class.
class FlutterSetSubscriptionsResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is FlutterSetSubscriptionsResult;

  @override
  int get hashCode => 628296315;
}

/// flutter.setWidgetPropertyValue params
///
/// {
///   "id": int
///   "value": optional FlutterWidgetPropertyValue
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterSetWidgetPropertyValueParams implements RequestParams {
  /// 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.
  int id;

  /// 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.
  FlutterWidgetPropertyValue? value;

  FlutterSetWidgetPropertyValueParams(this.id, {this.value});

  factory FlutterSetWidgetPropertyValueParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeInt('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      FlutterWidgetPropertyValue? value;
      if (json.containsKey('value')) {
        value = FlutterWidgetPropertyValue.fromJson(
          jsonDecoder,
          '$jsonPath.value',
          json['value'],
          clientUriConverter: clientUriConverter,
        );
      }
      return FlutterSetWidgetPropertyValueParams(id, value: value);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'flutter.setWidgetPropertyValue params',
        json,
      );
    }
  }

  factory FlutterSetWidgetPropertyValueParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return FlutterSetWidgetPropertyValueParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['id'] = id;
    var value = this.value;
    if (value != null) {
      result['value'] = value.toJson(clientUriConverter: clientUriConverter);
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'flutter.setWidgetPropertyValue',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterSetWidgetPropertyValueParams) {
      return id == other.id && value == other.value;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(id, value);
}

/// flutter.setWidgetPropertyValue result
///
/// {
///   "change": SourceChange
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterSetWidgetPropertyValueResult implements ResponseResult {
  /// The change that should be applied.
  SourceChange change;

  FlutterSetWidgetPropertyValueResult(this.change);

  factory FlutterSetWidgetPropertyValueResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      SourceChange change;
      if (json.containsKey('change')) {
        change = SourceChange.fromJson(
          jsonDecoder,
          '$jsonPath.change',
          json['change'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'change');
      }
      return FlutterSetWidgetPropertyValueResult(change);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'flutter.setWidgetPropertyValue result',
        json,
      );
    }
  }

  factory FlutterSetWidgetPropertyValueResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return FlutterSetWidgetPropertyValueResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['change'] = change.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterSetWidgetPropertyValueResult) {
      return change == other.change;
    }
    return false;
  }

  @override
  int get hashCode => change.hashCode;
}

/// FlutterWidgetProperty
///
/// {
///   "documentation": optional String
///   "expression": optional String
///   "id": int
///   "isRequired": bool
///   "isSafeToUpdate": bool
///   "name": String
///   "children": optional List<FlutterWidgetProperty>
///   "editor": optional FlutterWidgetPropertyEditor
///   "value": optional FlutterWidgetPropertyValue
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterWidgetProperty implements HasToJson {
  /// The documentation of the property to show to the user. Omitted if the
  /// server does not know the documentation, e.g. because the corresponding
  /// field is not documented.
  String? documentation;

  /// If the value of this property is set, the Dart code of the expression of
  /// this property.
  String? expression;

  /// The unique identifier of the property, must be passed back to the server
  /// when updating the property value. Identifiers become invalid on any
  /// source code change.
  int id;

  /// True if the property is required, e.g. because it corresponds to a
  /// required parameter of a constructor.
  bool isRequired;

  /// If the property expression is a concrete value (e.g. a literal, or an
  /// enum constant), then it is safe to replace the expression with another
  /// concrete value. In this case this field is true. Otherwise, for example
  /// when the expression is a reference to a field, so that its value is
  /// provided from outside, this field is false.
  bool isSafeToUpdate;

  /// The name of the property to display to the user.
  String name;

  /// The list of children properties, if any. For example any property of type
  /// `EdgeInsets` will have four children properties of type `double` - left /
  /// top / right / bottom.
  List<FlutterWidgetProperty>? children;

  /// The editor that should be used by the client. This field is omitted if
  /// the server does not know the editor for this property, for example
  /// because it does not have one of the supported types.
  FlutterWidgetPropertyEditor? editor;

  /// If the expression is set, and the server knows the value of the
  /// expression, this field is set.
  FlutterWidgetPropertyValue? value;

  FlutterWidgetProperty(
    this.id,
    this.isRequired,
    this.isSafeToUpdate,
    this.name, {
    this.documentation,
    this.expression,
    this.children,
    this.editor,
    this.value,
  });

  factory FlutterWidgetProperty.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String? documentation;
      if (json.containsKey('documentation')) {
        documentation = jsonDecoder.decodeString(
          '$jsonPath.documentation',
          json['documentation'],
        );
      }
      String? expression;
      if (json.containsKey('expression')) {
        expression = jsonDecoder.decodeString(
          '$jsonPath.expression',
          json['expression'],
        );
      }
      int id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeInt('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      bool isRequired;
      if (json.containsKey('isRequired')) {
        isRequired = jsonDecoder.decodeBool(
          '$jsonPath.isRequired',
          json['isRequired'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'isRequired');
      }
      bool isSafeToUpdate;
      if (json.containsKey('isSafeToUpdate')) {
        isSafeToUpdate = jsonDecoder.decodeBool(
          '$jsonPath.isSafeToUpdate',
          json['isSafeToUpdate'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'isSafeToUpdate');
      }
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      List<FlutterWidgetProperty>? children;
      if (json.containsKey('children')) {
        children = jsonDecoder.decodeList(
          '$jsonPath.children',
          json['children'],
          (String jsonPath, Object? json) => FlutterWidgetProperty.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      }
      FlutterWidgetPropertyEditor? editor;
      if (json.containsKey('editor')) {
        editor = FlutterWidgetPropertyEditor.fromJson(
          jsonDecoder,
          '$jsonPath.editor',
          json['editor'],
          clientUriConverter: clientUriConverter,
        );
      }
      FlutterWidgetPropertyValue? value;
      if (json.containsKey('value')) {
        value = FlutterWidgetPropertyValue.fromJson(
          jsonDecoder,
          '$jsonPath.value',
          json['value'],
          clientUriConverter: clientUriConverter,
        );
      }
      return FlutterWidgetProperty(
        id,
        isRequired,
        isSafeToUpdate,
        name,
        documentation: documentation,
        expression: expression,
        children: children,
        editor: editor,
        value: value,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'FlutterWidgetProperty', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var documentation = this.documentation;
    if (documentation != null) {
      result['documentation'] = documentation;
    }
    var expression = this.expression;
    if (expression != null) {
      result['expression'] = expression;
    }
    result['id'] = id;
    result['isRequired'] = isRequired;
    result['isSafeToUpdate'] = isSafeToUpdate;
    result['name'] = name;
    var children = this.children;
    if (children != null) {
      result['children'] =
          children
              .map(
                (FlutterWidgetProperty value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    var editor = this.editor;
    if (editor != null) {
      result['editor'] = editor.toJson(clientUriConverter: clientUriConverter);
    }
    var value = this.value;
    if (value != null) {
      result['value'] = value.toJson(clientUriConverter: clientUriConverter);
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterWidgetProperty) {
      return documentation == other.documentation &&
          expression == other.expression &&
          id == other.id &&
          isRequired == other.isRequired &&
          isSafeToUpdate == other.isSafeToUpdate &&
          name == other.name &&
          listEqual(
            children,
            other.children,
            (FlutterWidgetProperty a, FlutterWidgetProperty b) => a == b,
          ) &&
          editor == other.editor &&
          value == other.value;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    documentation,
    expression,
    id,
    isRequired,
    isSafeToUpdate,
    name,
    Object.hashAll(children ?? []),
    editor,
    value,
  );
}

/// FlutterWidgetPropertyEditor
///
/// {
///   "kind": FlutterWidgetPropertyEditorKind
///   "enumItems": optional List<FlutterWidgetPropertyValueEnumItem>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterWidgetPropertyEditor implements HasToJson {
  FlutterWidgetPropertyEditorKind kind;

  List<FlutterWidgetPropertyValueEnumItem>? enumItems;

  FlutterWidgetPropertyEditor(this.kind, {this.enumItems});

  factory FlutterWidgetPropertyEditor.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      FlutterWidgetPropertyEditorKind kind;
      if (json.containsKey('kind')) {
        kind = FlutterWidgetPropertyEditorKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kind');
      }
      List<FlutterWidgetPropertyValueEnumItem>? enumItems;
      if (json.containsKey('enumItems')) {
        enumItems = jsonDecoder.decodeList(
          '$jsonPath.enumItems',
          json['enumItems'],
          (String jsonPath, Object? json) =>
              FlutterWidgetPropertyValueEnumItem.fromJson(
                jsonDecoder,
                jsonPath,
                json,
                clientUriConverter: clientUriConverter,
              ),
        );
      }
      return FlutterWidgetPropertyEditor(kind, enumItems: enumItems);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'FlutterWidgetPropertyEditor', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    var enumItems = this.enumItems;
    if (enumItems != null) {
      result['enumItems'] =
          enumItems
              .map(
                (FlutterWidgetPropertyValueEnumItem value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterWidgetPropertyEditor) {
      return kind == other.kind &&
          listEqual(
            enumItems,
            other.enumItems,
            (
              FlutterWidgetPropertyValueEnumItem a,
              FlutterWidgetPropertyValueEnumItem b,
            ) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(kind, Object.hashAll(enumItems ?? []));
}

/// FlutterWidgetPropertyEditorKind
///
/// enum {
///   BOOL
///   DOUBLE
///   ENUM
///   ENUM_LIKE
///   INT
///   STRING
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum FlutterWidgetPropertyEditorKind {
  /// The editor for a property of type `bool`.
  BOOL,

  /// The editor for a property of the type `double`.
  DOUBLE,

  /// The editor for choosing an item of an enumeration, see the `enumItems`
  /// field of `FlutterWidgetPropertyEditor`.
  ENUM,

  /// The editor for either choosing a pre-defined item from a list of provided
  /// static field references (like `ENUM`), or specifying a free-form
  /// expression.
  ENUM_LIKE,

  /// The editor for a property of type `int`.
  INT,

  /// The editor for a property of the type `String`.
  STRING;

  factory FlutterWidgetPropertyEditorKind.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(
      jsonPath,
      'FlutterWidgetPropertyEditorKind',
      json,
    );
  }

  @override
  String toString() => 'FlutterWidgetPropertyEditorKind.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// FlutterWidgetPropertyValue
///
/// {
///   "boolValue": optional bool
///   "doubleValue": optional double
///   "intValue": optional int
///   "stringValue": optional String
///   "enumValue": optional FlutterWidgetPropertyValueEnumItem
///   "expression": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterWidgetPropertyValue implements HasToJson {
  bool? boolValue;

  double? doubleValue;

  int? intValue;

  String? stringValue;

  FlutterWidgetPropertyValueEnumItem? enumValue;

  /// A free-form expression, which will be used as the value as is.
  String? expression;

  FlutterWidgetPropertyValue({
    this.boolValue,
    this.doubleValue,
    this.intValue,
    this.stringValue,
    this.enumValue,
    this.expression,
  });

  factory FlutterWidgetPropertyValue.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      bool? boolValue;
      if (json.containsKey('boolValue')) {
        boolValue = jsonDecoder.decodeBool(
          '$jsonPath.boolValue',
          json['boolValue'],
        );
      }
      double? doubleValue;
      if (json.containsKey('doubleValue')) {
        doubleValue = jsonDecoder.decodeDouble(
          '$jsonPath.doubleValue',
          json['doubleValue'] as Object,
        );
      }
      int? intValue;
      if (json.containsKey('intValue')) {
        intValue = jsonDecoder.decodeInt(
          '$jsonPath.intValue',
          json['intValue'],
        );
      }
      String? stringValue;
      if (json.containsKey('stringValue')) {
        stringValue = jsonDecoder.decodeString(
          '$jsonPath.stringValue',
          json['stringValue'],
        );
      }
      FlutterWidgetPropertyValueEnumItem? enumValue;
      if (json.containsKey('enumValue')) {
        enumValue = FlutterWidgetPropertyValueEnumItem.fromJson(
          jsonDecoder,
          '$jsonPath.enumValue',
          json['enumValue'],
          clientUriConverter: clientUriConverter,
        );
      }
      String? expression;
      if (json.containsKey('expression')) {
        expression = jsonDecoder.decodeString(
          '$jsonPath.expression',
          json['expression'],
        );
      }
      return FlutterWidgetPropertyValue(
        boolValue: boolValue,
        doubleValue: doubleValue,
        intValue: intValue,
        stringValue: stringValue,
        enumValue: enumValue,
        expression: expression,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'FlutterWidgetPropertyValue', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var boolValue = this.boolValue;
    if (boolValue != null) {
      result['boolValue'] = boolValue;
    }
    var doubleValue = this.doubleValue;
    if (doubleValue != null) {
      result['doubleValue'] = doubleValue;
    }
    var intValue = this.intValue;
    if (intValue != null) {
      result['intValue'] = intValue;
    }
    var stringValue = this.stringValue;
    if (stringValue != null) {
      result['stringValue'] = stringValue;
    }
    var enumValue = this.enumValue;
    if (enumValue != null) {
      result['enumValue'] = enumValue.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var expression = this.expression;
    if (expression != null) {
      result['expression'] = expression;
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterWidgetPropertyValue) {
      return boolValue == other.boolValue &&
          doubleValue == other.doubleValue &&
          intValue == other.intValue &&
          stringValue == other.stringValue &&
          enumValue == other.enumValue &&
          expression == other.expression;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    boolValue,
    doubleValue,
    intValue,
    stringValue,
    enumValue,
    expression,
  );
}

/// FlutterWidgetPropertyValueEnumItem
///
/// {
///   "libraryUri": String
///   "className": String
///   "name": String
///   "documentation": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class FlutterWidgetPropertyValueEnumItem implements HasToJson {
  /// The URI of the library containing the `className`. When the enum item is
  /// passed back, this will allow the server to import the corresponding
  /// library if necessary.
  String libraryUri;

  /// The name of the class or enum.
  String className;

  /// The name of the field in the enumeration, or the static field in the
  /// class.
  String name;

  /// The documentation to show to the user. Omitted if the server does not
  /// know the documentation, e.g. because the corresponding field is not
  /// documented.
  String? documentation;

  FlutterWidgetPropertyValueEnumItem(
    this.libraryUri,
    this.className,
    this.name, {
    this.documentation,
  });

  factory FlutterWidgetPropertyValueEnumItem.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String libraryUri;
      if (json.containsKey('libraryUri')) {
        libraryUri = jsonDecoder.decodeString(
          '$jsonPath.libraryUri',
          json['libraryUri'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'libraryUri');
      }
      String className;
      if (json.containsKey('className')) {
        className = jsonDecoder.decodeString(
          '$jsonPath.className',
          json['className'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'className');
      }
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      String? documentation;
      if (json.containsKey('documentation')) {
        documentation = jsonDecoder.decodeString(
          '$jsonPath.documentation',
          json['documentation'],
        );
      }
      return FlutterWidgetPropertyValueEnumItem(
        libraryUri,
        className,
        name,
        documentation: documentation,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'FlutterWidgetPropertyValueEnumItem',
        json,
      );
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['libraryUri'] = libraryUri;
    result['className'] = className;
    result['name'] = name;
    var documentation = this.documentation;
    if (documentation != null) {
      result['documentation'] = documentation;
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is FlutterWidgetPropertyValueEnumItem) {
      return libraryUri == other.libraryUri &&
          className == other.className &&
          name == other.name &&
          documentation == other.documentation;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(libraryUri, className, name, documentation);
}

/// GeneralAnalysisService
///
/// enum {
///   ANALYZED_FILES
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum GeneralAnalysisService {
  ANALYZED_FILES;

  factory GeneralAnalysisService.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'GeneralAnalysisService', json);
  }

  @override
  String toString() => 'GeneralAnalysisService.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// HoverInformation
///
/// {
///   "offset": int
///   "length": int
///   "containingLibraryPath": optional String
///   "containingLibraryName": optional String
///   "containingClassDescription": optional String
///   "dartdoc": optional String
///   "elementDescription": optional String
///   "elementKind": optional String
///   "isDeprecated": optional bool
///   "parameter": optional String
///   "propagatedType": optional String
///   "staticType": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class HoverInformation implements HasToJson {
  /// The offset of the range of characters that encompasses the cursor
  /// position and has the same hover information as the cursor position.
  int offset;

  /// The length of the range of characters that encompasses the cursor
  /// position and has the same hover information as the cursor position.
  int length;

  /// The path to the defining compilation unit of the library in which the
  /// referenced element is declared. This data is omitted if there is no
  /// referenced element, or if the element is declared inside an HTML file.
  String? containingLibraryPath;

  /// The URI of the containing library, examples here include "dart:core",
  /// "package:.." and file uris represented by the path on disk, "/..". The
  /// data is omitted if the element is declared inside an HTML file.
  String? containingLibraryName;

  /// A human-readable description of the class declaring the element being
  /// referenced. This data is omitted if there is no referenced element, or if
  /// the element is not a class member.
  String? containingClassDescription;

  /// The dartdoc associated with the referenced element. 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.
  String? dartdoc;

  /// A human-readable description of the element being referenced. This data
  /// is omitted if there is no referenced element.
  String? elementDescription;

  /// A human-readable description of the kind of element being referenced
  /// (such as "class" or "function type alias"). This data is omitted if there
  /// is no referenced element.
  String? elementKind;

  /// True if the referenced element is deprecated.
  bool? isDeprecated;

  /// A human-readable description of the parameter corresponding to the
  /// expression being hovered over. This data is omitted if the location is
  /// not in an argument to a function.
  String? parameter;

  /// The name of the propagated type of the expression. This data is omitted
  /// if the location does not correspond to an expression or if there is no
  /// propagated type information.
  String? propagatedType;

  /// The name of the static type of the expression. This data is omitted if
  /// the location does not correspond to an expression.
  String? staticType;

  HoverInformation(
    this.offset,
    this.length, {
    this.containingLibraryPath,
    this.containingLibraryName,
    this.containingClassDescription,
    this.dartdoc,
    this.elementDescription,
    this.elementKind,
    this.isDeprecated,
    this.parameter,
    this.propagatedType,
    this.staticType,
  });

  factory HoverInformation.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      String? containingLibraryPath;
      if (json.containsKey('containingLibraryPath')) {
        containingLibraryPath = jsonDecoder.decodeString(
          '$jsonPath.containingLibraryPath',
          json['containingLibraryPath'],
        );
      }
      String? containingLibraryName;
      if (json.containsKey('containingLibraryName')) {
        containingLibraryName = jsonDecoder.decodeString(
          '$jsonPath.containingLibraryName',
          json['containingLibraryName'],
        );
      }
      String? containingClassDescription;
      if (json.containsKey('containingClassDescription')) {
        containingClassDescription = jsonDecoder.decodeString(
          '$jsonPath.containingClassDescription',
          json['containingClassDescription'],
        );
      }
      String? dartdoc;
      if (json.containsKey('dartdoc')) {
        dartdoc = jsonDecoder.decodeString(
          '$jsonPath.dartdoc',
          json['dartdoc'],
        );
      }
      String? elementDescription;
      if (json.containsKey('elementDescription')) {
        elementDescription = jsonDecoder.decodeString(
          '$jsonPath.elementDescription',
          json['elementDescription'],
        );
      }
      String? elementKind;
      if (json.containsKey('elementKind')) {
        elementKind = jsonDecoder.decodeString(
          '$jsonPath.elementKind',
          json['elementKind'],
        );
      }
      bool? isDeprecated;
      if (json.containsKey('isDeprecated')) {
        isDeprecated = jsonDecoder.decodeBool(
          '$jsonPath.isDeprecated',
          json['isDeprecated'],
        );
      }
      String? parameter;
      if (json.containsKey('parameter')) {
        parameter = jsonDecoder.decodeString(
          '$jsonPath.parameter',
          json['parameter'],
        );
      }
      String? propagatedType;
      if (json.containsKey('propagatedType')) {
        propagatedType = jsonDecoder.decodeString(
          '$jsonPath.propagatedType',
          json['propagatedType'],
        );
      }
      String? staticType;
      if (json.containsKey('staticType')) {
        staticType = jsonDecoder.decodeString(
          '$jsonPath.staticType',
          json['staticType'],
        );
      }
      return HoverInformation(
        offset,
        length,
        containingLibraryPath: containingLibraryPath,
        containingLibraryName: containingLibraryName,
        containingClassDescription: containingClassDescription,
        dartdoc: dartdoc,
        elementDescription: elementDescription,
        elementKind: elementKind,
        isDeprecated: isDeprecated,
        parameter: parameter,
        propagatedType: propagatedType,
        staticType: staticType,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'HoverInformation', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['offset'] = offset;
    result['length'] = length;
    var containingLibraryPath = this.containingLibraryPath;
    if (containingLibraryPath != null) {
      result['containingLibraryPath'] = containingLibraryPath;
    }
    var containingLibraryName = this.containingLibraryName;
    if (containingLibraryName != null) {
      result['containingLibraryName'] = containingLibraryName;
    }
    var containingClassDescription = this.containingClassDescription;
    if (containingClassDescription != null) {
      result['containingClassDescription'] = containingClassDescription;
    }
    var dartdoc = this.dartdoc;
    if (dartdoc != null) {
      result['dartdoc'] = dartdoc;
    }
    var elementDescription = this.elementDescription;
    if (elementDescription != null) {
      result['elementDescription'] = elementDescription;
    }
    var elementKind = this.elementKind;
    if (elementKind != null) {
      result['elementKind'] = elementKind;
    }
    var isDeprecated = this.isDeprecated;
    if (isDeprecated != null) {
      result['isDeprecated'] = isDeprecated;
    }
    var parameter = this.parameter;
    if (parameter != null) {
      result['parameter'] = parameter;
    }
    var propagatedType = this.propagatedType;
    if (propagatedType != null) {
      result['propagatedType'] = propagatedType;
    }
    var staticType = this.staticType;
    if (staticType != null) {
      result['staticType'] = staticType;
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is HoverInformation) {
      return offset == other.offset &&
          length == other.length &&
          containingLibraryPath == other.containingLibraryPath &&
          containingLibraryName == other.containingLibraryName &&
          containingClassDescription == other.containingClassDescription &&
          dartdoc == other.dartdoc &&
          elementDescription == other.elementDescription &&
          elementKind == other.elementKind &&
          isDeprecated == other.isDeprecated &&
          parameter == other.parameter &&
          propagatedType == other.propagatedType &&
          staticType == other.staticType;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    offset,
    length,
    containingLibraryPath,
    containingLibraryName,
    containingClassDescription,
    dartdoc,
    elementDescription,
    elementKind,
    isDeprecated,
    parameter,
    propagatedType,
    staticType,
  );
}

/// ImplementedClass
///
/// {
///   "offset": int
///   "length": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ImplementedClass implements HasToJson {
  /// The offset of the name of the implemented class.
  int offset;

  /// The length of the name of the implemented class.
  int length;

  ImplementedClass(this.offset, this.length);

  factory ImplementedClass.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      return ImplementedClass(offset, length);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ImplementedClass', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['offset'] = offset;
    result['length'] = length;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ImplementedClass) {
      return offset == other.offset && length == other.length;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(offset, length);
}

/// ImplementedMember
///
/// {
///   "offset": int
///   "length": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ImplementedMember implements HasToJson {
  /// The offset of the name of the implemented member.
  int offset;

  /// The length of the name of the implemented member.
  int length;

  ImplementedMember(this.offset, this.length);

  factory ImplementedMember.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      return ImplementedMember(offset, length);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ImplementedMember', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['offset'] = offset;
    result['length'] = length;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ImplementedMember) {
      return offset == other.offset && length == other.length;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(offset, length);
}

/// ImportedElementSet
///
/// {
///   "strings": List<String>
///   "uris": List<int>
///   "names": List<int>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ImportedElementSet implements HasToJson {
  /// The list of unique strings in this object.
  List<String> strings;

  /// The library URI part of the element. It is an index in the `strings`
  /// field.
  List<int> uris;

  /// The name part of a the element. It is an index in the `strings` field.
  List<int> names;

  ImportedElementSet(this.strings, this.uris, this.names);

  factory ImportedElementSet.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> strings;
      if (json.containsKey('strings')) {
        strings = jsonDecoder.decodeList(
          '$jsonPath.strings',
          json['strings'],
          jsonDecoder.decodeString,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'strings');
      }
      List<int> uris;
      if (json.containsKey('uris')) {
        uris = jsonDecoder.decodeList(
          '$jsonPath.uris',
          json['uris'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'uris');
      }
      List<int> names;
      if (json.containsKey('names')) {
        names = jsonDecoder.decodeList(
          '$jsonPath.names',
          json['names'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'names');
      }
      return ImportedElementSet(strings, uris, names);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ImportedElementSet', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['strings'] = strings;
    result['uris'] = uris;
    result['names'] = names;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ImportedElementSet) {
      return listEqual(
            strings,
            other.strings,
            (String a, String b) => a == b,
          ) &&
          listEqual(uris, other.uris, (int a, int b) => a == b) &&
          listEqual(names, other.names, (int a, int b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    Object.hashAll(strings),
    Object.hashAll(uris),
    Object.hashAll(names),
  );
}

/// ImportedElements
///
/// {
///   "path": FilePath
///   "prefix": String
///   "elements": List<String>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ImportedElements implements HasToJson {
  /// The absolute and normalized path of the file containing the library.
  String path;

  /// The prefix that was used when importing the library into the original
  /// source.
  String prefix;

  /// The names of the elements imported from the library.
  List<String> elements;

  ImportedElements(this.path, this.prefix, this.elements);

  factory ImportedElements.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String path;
      if (json.containsKey('path')) {
        path =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.path', json['path']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.path', json['path']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'path');
      }
      String prefix;
      if (json.containsKey('prefix')) {
        prefix = jsonDecoder.decodeString('$jsonPath.prefix', json['prefix']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'prefix');
      }
      List<String> elements;
      if (json.containsKey('elements')) {
        elements = jsonDecoder.decodeList(
          '$jsonPath.elements',
          json['elements'],
          jsonDecoder.decodeString,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'elements');
      }
      return ImportedElements(path, prefix, elements);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ImportedElements', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['path'] = clientUriConverter?.toClientFilePath(path) ?? path;
    result['prefix'] = prefix;
    result['elements'] = elements;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ImportedElements) {
      return path == other.path &&
          prefix == other.prefix &&
          listEqual(elements, other.elements, (String a, String b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(path, prefix, Object.hashAll(elements));
}

/// inlineLocalVariable feedback
///
/// {
///   "name": String
///   "occurrences": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class InlineLocalVariableFeedback extends RefactoringFeedback {
  /// The name of the variable being inlined.
  String name;

  /// The number of times the variable occurs.
  int occurrences;

  InlineLocalVariableFeedback(this.name, this.occurrences);

  factory InlineLocalVariableFeedback.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      int occurrences;
      if (json.containsKey('occurrences')) {
        occurrences = jsonDecoder.decodeInt(
          '$jsonPath.occurrences',
          json['occurrences'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'occurrences');
      }
      return InlineLocalVariableFeedback(name, occurrences);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'inlineLocalVariable feedback',
        json,
      );
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    result['occurrences'] = occurrences;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is InlineLocalVariableFeedback) {
      return name == other.name && occurrences == other.occurrences;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(name, occurrences);
}

/// inlineLocalVariable options
///
/// Clients may not extend, implement or mix-in this class.
class InlineLocalVariableOptions extends RefactoringOptions
    implements HasToJson {
  @override
  bool operator ==(Object other) => other is InlineLocalVariableOptions;

  @override
  int get hashCode => 540364977;
}

/// inlineMethod feedback
///
/// {
///   "className": optional String
///   "methodName": String
///   "isDeclaration": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class InlineMethodFeedback extends RefactoringFeedback {
  /// The name of the class enclosing the method being inlined. If not a class
  /// member is being inlined, this field will be absent.
  String? className;

  /// The name of the method (or function) being inlined.
  String methodName;

  /// True if the declaration of the method is selected. So all references
  /// should be inlined.
  bool isDeclaration;

  InlineMethodFeedback(this.methodName, this.isDeclaration, {this.className});

  factory InlineMethodFeedback.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String? className;
      if (json.containsKey('className')) {
        className = jsonDecoder.decodeString(
          '$jsonPath.className',
          json['className'],
        );
      }
      String methodName;
      if (json.containsKey('methodName')) {
        methodName = jsonDecoder.decodeString(
          '$jsonPath.methodName',
          json['methodName'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'methodName');
      }
      bool isDeclaration;
      if (json.containsKey('isDeclaration')) {
        isDeclaration = jsonDecoder.decodeBool(
          '$jsonPath.isDeclaration',
          json['isDeclaration'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'isDeclaration');
      }
      return InlineMethodFeedback(
        methodName,
        isDeclaration,
        className: className,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'inlineMethod feedback', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var className = this.className;
    if (className != null) {
      result['className'] = className;
    }
    result['methodName'] = methodName;
    result['isDeclaration'] = isDeclaration;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is InlineMethodFeedback) {
      return className == other.className &&
          methodName == other.methodName &&
          isDeclaration == other.isDeclaration;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(className, methodName, isDeclaration);
}

/// inlineMethod options
///
/// {
///   "deleteSource": bool
///   "inlineAll": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class InlineMethodOptions extends RefactoringOptions {
  /// True if the method being inlined should be removed. It is an error if
  /// this field is true and inlineAll is false.
  bool deleteSource;

  /// True if all invocations of the method should be inlined, or false if only
  /// the invocation site used to create this refactoring should be inlined.
  bool inlineAll;

  InlineMethodOptions(this.deleteSource, this.inlineAll);

  factory InlineMethodOptions.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      bool deleteSource;
      if (json.containsKey('deleteSource')) {
        deleteSource = jsonDecoder.decodeBool(
          '$jsonPath.deleteSource',
          json['deleteSource'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'deleteSource');
      }
      bool inlineAll;
      if (json.containsKey('inlineAll')) {
        inlineAll = jsonDecoder.decodeBool(
          '$jsonPath.inlineAll',
          json['inlineAll'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'inlineAll');
      }
      return InlineMethodOptions(deleteSource, inlineAll);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'inlineMethod options', json);
    }
  }

  factory InlineMethodOptions.fromRefactoringParams(
    EditGetRefactoringParams refactoringParams,
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return InlineMethodOptions.fromJson(
      RequestDecoder(request),
      'options',
      refactoringParams.options,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['deleteSource'] = deleteSource;
    result['inlineAll'] = inlineAll;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is InlineMethodOptions) {
      return deleteSource == other.deleteSource && inlineAll == other.inlineAll;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(deleteSource, inlineAll);
}

/// LibraryPathSet
///
/// {
///   "scope": FilePath
///   "libraryPaths": List<FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class LibraryPathSet implements HasToJson {
  /// The filepath for which this request's libraries should be active in
  /// completion suggestions. This object associates filesystem regions to
  /// libraries and library directories of interest to the client.
  String scope;

  /// The paths of the libraries of interest to the client for completion
  /// suggestions.
  List<String> libraryPaths;

  LibraryPathSet(this.scope, this.libraryPaths);

  factory LibraryPathSet.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String scope;
      if (json.containsKey('scope')) {
        scope =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.scope', json['scope']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.scope', json['scope']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'scope');
      }
      List<String> libraryPaths;
      if (json.containsKey('libraryPaths')) {
        libraryPaths = jsonDecoder.decodeList(
          '$jsonPath.libraryPaths',
          json['libraryPaths'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'libraryPaths');
      }
      return LibraryPathSet(scope, libraryPaths);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'LibraryPathSet', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['scope'] = clientUriConverter?.toClientFilePath(scope) ?? scope;
    result['libraryPaths'] =
        libraryPaths
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is LibraryPathSet) {
      return scope == other.scope &&
          listEqual(
            libraryPaths,
            other.libraryPaths,
            (String a, String b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(scope, Object.hashAll(libraryPaths));
}

/// lsp.handle params
///
/// {
///   "lspMessage": object
/// }
///
/// Clients may not extend, implement or mix-in this class.
class LspHandleParams implements RequestParams {
  /// The LSP RequestMessage.
  Object lspMessage;

  LspHandleParams(this.lspMessage);

  factory LspHandleParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Object lspMessage;
      if (json.containsKey('lspMessage')) {
        lspMessage = json['lspMessage'] as Object;
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'lspMessage');
      }
      return LspHandleParams(lspMessage);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'lsp.handle params', json);
    }
  }

  factory LspHandleParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return LspHandleParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['lspMessage'] = lspMessage;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'lsp.handle',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is LspHandleParams) {
      return lspMessage == other.lspMessage;
    }
    return false;
  }

  @override
  int get hashCode => lspMessage.hashCode;
}

/// lsp.handle result
///
/// {
///   "lspResponse": object
/// }
///
/// Clients may not extend, implement or mix-in this class.
class LspHandleResult implements ResponseResult {
  /// The LSP ResponseMessage returned by the handler.
  Object lspResponse;

  LspHandleResult(this.lspResponse);

  factory LspHandleResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Object lspResponse;
      if (json.containsKey('lspResponse')) {
        lspResponse = json['lspResponse'] as Object;
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'lspResponse');
      }
      return LspHandleResult(lspResponse);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'lsp.handle result', json);
    }
  }

  factory LspHandleResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return LspHandleResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['lspResponse'] = lspResponse;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is LspHandleResult) {
      return lspResponse == other.lspResponse;
    }
    return false;
  }

  @override
  int get hashCode => lspResponse.hashCode;
}

/// lsp.notification params
///
/// {
///   "lspNotification": object
/// }
///
/// Clients may not extend, implement or mix-in this class.
class LspNotificationParams implements HasToJson {
  /// The LSP NotificationMessage sent by the server.
  Object lspNotification;

  LspNotificationParams(this.lspNotification);

  factory LspNotificationParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Object lspNotification;
      if (json.containsKey('lspNotification')) {
        lspNotification = json['lspNotification'] as Object;
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'lspNotification');
      }
      return LspNotificationParams(lspNotification);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'lsp.notification params', json);
    }
  }

  factory LspNotificationParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return LspNotificationParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['lspNotification'] = lspNotification;
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'lsp.notification',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is LspNotificationParams) {
      return lspNotification == other.lspNotification;
    }
    return false;
  }

  @override
  int get hashCode => lspNotification.hashCode;
}

/// MessageAction
///
/// {
///   "label": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class MessageAction implements HasToJson {
  /// The label of the button to be displayed, and the value to be returned to
  /// the server if the button is clicked.
  String label;

  MessageAction(this.label);

  factory MessageAction.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String label;
      if (json.containsKey('label')) {
        label = jsonDecoder.decodeString('$jsonPath.label', json['label']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'label');
      }
      return MessageAction(label);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'MessageAction', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['label'] = label;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is MessageAction) {
      return label == other.label;
    }
    return false;
  }

  @override
  int get hashCode => label.hashCode;
}

/// MessageType
///
/// enum {
///   ERROR
///   WARNING
///   INFO
///   LOG
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum MessageType {
  /// The message is an error message.
  ERROR,

  /// The message is a warning message.
  WARNING,

  /// The message is an informational message.
  INFO,

  /// The message is a log message.
  LOG;

  factory MessageType.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'MessageType', json);
  }

  @override
  String toString() => 'MessageType.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// moveFile feedback
///
/// Clients may not extend, implement or mix-in this class.
class MoveFileFeedback extends RefactoringFeedback implements HasToJson {
  @override
  bool operator ==(Object other) => other is MoveFileFeedback;

  @override
  int get hashCode => 438975893;
}

/// moveFile options
///
/// {
///   "newFile": FilePath
/// }
///
/// Clients may not extend, implement or mix-in this class.
class MoveFileOptions extends RefactoringOptions {
  /// The new file path to which the given file is being moved.
  String newFile;

  MoveFileOptions(this.newFile);

  factory MoveFileOptions.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String newFile;
      if (json.containsKey('newFile')) {
        newFile =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.newFile', json['newFile']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.newFile', json['newFile']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'newFile');
      }
      return MoveFileOptions(newFile);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'moveFile options', json);
    }
  }

  factory MoveFileOptions.fromRefactoringParams(
    EditGetRefactoringParams refactoringParams,
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return MoveFileOptions.fromJson(
      RequestDecoder(request),
      'options',
      refactoringParams.options,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['newFile'] =
        clientUriConverter?.toClientFilePath(newFile) ?? newFile;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is MoveFileOptions) {
      return newFile == other.newFile;
    }
    return false;
  }

  @override
  int get hashCode => newFile.hashCode;
}

/// OverriddenMember
///
/// {
///   "element": Element
///   "className": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class OverriddenMember implements HasToJson {
  /// The element that is being overridden.
  Element element;

  /// The name of the class in which the member is defined.
  String className;

  OverriddenMember(this.element, this.className);

  factory OverriddenMember.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Element element;
      if (json.containsKey('element')) {
        element = Element.fromJson(
          jsonDecoder,
          '$jsonPath.element',
          json['element'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'element');
      }
      String className;
      if (json.containsKey('className')) {
        className = jsonDecoder.decodeString(
          '$jsonPath.className',
          json['className'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'className');
      }
      return OverriddenMember(element, className);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'OverriddenMember', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['element'] = element.toJson(clientUriConverter: clientUriConverter);
    result['className'] = className;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is OverriddenMember) {
      return element == other.element && className == other.className;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(element, className);
}

/// Override
///
/// {
///   "offset": int
///   "length": int
///   "superclassMember": optional OverriddenMember
///   "interfaceMembers": optional List<OverriddenMember>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class Override implements HasToJson {
  /// The offset of the name of the overriding member.
  int offset;

  /// The length of the name of the overriding member.
  int length;

  /// The member inherited from a superclass that is overridden by the
  /// overriding member. The field is omitted if there is no superclass member,
  /// in which case there must be at least one interface member.
  OverriddenMember? superclassMember;

  /// The members inherited from interfaces that are overridden by the
  /// overriding member. The field is omitted if there are no interface
  /// members, in which case there must be a superclass member.
  List<OverriddenMember>? interfaceMembers;

  Override(
    this.offset,
    this.length, {
    this.superclassMember,
    this.interfaceMembers,
  });

  factory Override.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      OverriddenMember? superclassMember;
      if (json.containsKey('superclassMember')) {
        superclassMember = OverriddenMember.fromJson(
          jsonDecoder,
          '$jsonPath.superclassMember',
          json['superclassMember'],
          clientUriConverter: clientUriConverter,
        );
      }
      List<OverriddenMember>? interfaceMembers;
      if (json.containsKey('interfaceMembers')) {
        interfaceMembers = jsonDecoder.decodeList(
          '$jsonPath.interfaceMembers',
          json['interfaceMembers'],
          (String jsonPath, Object? json) => OverriddenMember.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      }
      return Override(
        offset,
        length,
        superclassMember: superclassMember,
        interfaceMembers: interfaceMembers,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'Override', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['offset'] = offset;
    result['length'] = length;
    var superclassMember = this.superclassMember;
    if (superclassMember != null) {
      result['superclassMember'] = superclassMember.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var interfaceMembers = this.interfaceMembers;
    if (interfaceMembers != null) {
      result['interfaceMembers'] =
          interfaceMembers
              .map(
                (OverriddenMember value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is Override) {
      return offset == other.offset &&
          length == other.length &&
          superclassMember == other.superclassMember &&
          listEqual(
            interfaceMembers,
            other.interfaceMembers,
            (OverriddenMember a, OverriddenMember b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    offset,
    length,
    superclassMember,
    Object.hashAll(interfaceMembers ?? []),
  );
}

/// PostfixTemplateDescriptor
///
/// {
///   "name": String
///   "key": String
///   "example": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class PostfixTemplateDescriptor implements HasToJson {
  /// The template name, shown in the UI.
  String name;

  /// The unique template key, not shown in the UI.
  String key;

  /// A short example of the transformation performed when the template is
  /// applied.
  String example;

  PostfixTemplateDescriptor(this.name, this.key, this.example);

  factory PostfixTemplateDescriptor.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      String key;
      if (json.containsKey('key')) {
        key = jsonDecoder.decodeString('$jsonPath.key', json['key']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'key');
      }
      String example;
      if (json.containsKey('example')) {
        example = jsonDecoder.decodeString(
          '$jsonPath.example',
          json['example'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'example');
      }
      return PostfixTemplateDescriptor(name, key, example);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'PostfixTemplateDescriptor', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    result['key'] = key;
    result['example'] = example;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is PostfixTemplateDescriptor) {
      return name == other.name && key == other.key && example == other.example;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(name, key, example);
}

/// PubStatus
///
/// {
///   "isListingPackageDirs": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class PubStatus implements HasToJson {
  /// True if the server is currently running pub to produce a list of package
  /// directories.
  bool isListingPackageDirs;

  PubStatus(this.isListingPackageDirs);

  factory PubStatus.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      bool isListingPackageDirs;
      if (json.containsKey('isListingPackageDirs')) {
        isListingPackageDirs = jsonDecoder.decodeBool(
          '$jsonPath.isListingPackageDirs',
          json['isListingPackageDirs'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'isListingPackageDirs');
      }
      return PubStatus(isListingPackageDirs);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'PubStatus', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['isListingPackageDirs'] = isListingPackageDirs;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is PubStatus) {
      return isListingPackageDirs == other.isListingPackageDirs;
    }
    return false;
  }

  @override
  int get hashCode => isListingPackageDirs.hashCode;
}

/// RefactoringFeedback
///
/// {
/// }
///
/// Clients may not extend, implement or mix-in this class.
class RefactoringFeedback implements HasToJson {
  RefactoringFeedback();

  static RefactoringFeedback? fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json,
    Map<Object?, Object?> responseJson, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return refactoringFeedbackFromJson(
      jsonDecoder,
      jsonPath,
      json,
      responseJson,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is RefactoringFeedback) {
      return true;
    }
    return false;
  }

  @override
  int get hashCode => 0;
}

/// RefactoringOptions
///
/// {
/// }
///
/// Clients may not extend, implement or mix-in this class.
class RefactoringOptions implements HasToJson {
  RefactoringOptions();

  static RefactoringOptions? fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json,
    RefactoringKind kind, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return refactoringOptionsFromJson(
      jsonDecoder,
      jsonPath,
      json,
      kind,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is RefactoringOptions) {
      return true;
    }
    return false;
  }

  @override
  int get hashCode => 0;
}

/// rename feedback
///
/// {
///   "offset": int
///   "length": int
///   "elementKindName": String
///   "oldName": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class RenameFeedback extends RefactoringFeedback {
  /// The offset to the beginning of the name selected to be renamed, or -1 if
  /// the name does not exist yet.
  int offset;

  /// The length of the name selected to be renamed.
  int length;

  /// The human-readable description of the kind of element being renamed (such
  /// as "class" or "function type alias").
  String elementKindName;

  /// The old name of the element before the refactoring.
  String oldName;

  RenameFeedback(this.offset, this.length, this.elementKindName, this.oldName);

  factory RenameFeedback.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      String elementKindName;
      if (json.containsKey('elementKindName')) {
        elementKindName = jsonDecoder.decodeString(
          '$jsonPath.elementKindName',
          json['elementKindName'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'elementKindName');
      }
      String oldName;
      if (json.containsKey('oldName')) {
        oldName = jsonDecoder.decodeString(
          '$jsonPath.oldName',
          json['oldName'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'oldName');
      }
      return RenameFeedback(offset, length, elementKindName, oldName);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'rename feedback', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['offset'] = offset;
    result['length'] = length;
    result['elementKindName'] = elementKindName;
    result['oldName'] = oldName;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is RenameFeedback) {
      return offset == other.offset &&
          length == other.length &&
          elementKindName == other.elementKindName &&
          oldName == other.oldName;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(offset, length, elementKindName, oldName);
}

/// rename options
///
/// {
///   "newName": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class RenameOptions extends RefactoringOptions {
  /// The name that the element should have after the refactoring.
  String newName;

  RenameOptions(this.newName);

  factory RenameOptions.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String newName;
      if (json.containsKey('newName')) {
        newName = jsonDecoder.decodeString(
          '$jsonPath.newName',
          json['newName'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'newName');
      }
      return RenameOptions(newName);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'rename options', json);
    }
  }

  factory RenameOptions.fromRefactoringParams(
    EditGetRefactoringParams refactoringParams,
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return RenameOptions.fromJson(
      RequestDecoder(request),
      'options',
      refactoringParams.options,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['newName'] = newName;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is RenameOptions) {
      return newName == other.newName;
    }
    return false;
  }

  @override
  int get hashCode => newName.hashCode;
}

/// RequestError
///
/// {
///   "code": RequestErrorCode
///   "message": String
///   "stackTrace": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class RequestError implements HasToJson {
  /// A code that uniquely identifies the error that occurred.
  RequestErrorCode code;

  /// A short description of the error.
  String message;

  /// The stack trace associated with processing the request, used for
  /// debugging the server.
  String? stackTrace;

  RequestError(this.code, this.message, {this.stackTrace});

  factory RequestError.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      RequestErrorCode code;
      if (json.containsKey('code')) {
        code = RequestErrorCode.fromJson(
          jsonDecoder,
          '$jsonPath.code',
          json['code'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'code');
      }
      String message;
      if (json.containsKey('message')) {
        message = jsonDecoder.decodeString(
          '$jsonPath.message',
          json['message'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'message');
      }
      String? stackTrace;
      if (json.containsKey('stackTrace')) {
        stackTrace = jsonDecoder.decodeString(
          '$jsonPath.stackTrace',
          json['stackTrace'],
        );
      }
      return RequestError(code, message, stackTrace: stackTrace);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'RequestError', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['code'] = code.toJson(clientUriConverter: clientUriConverter);
    result['message'] = message;
    var stackTrace = this.stackTrace;
    if (stackTrace != null) {
      result['stackTrace'] = stackTrace;
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is RequestError) {
      return code == other.code &&
          message == other.message &&
          stackTrace == other.stackTrace;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(code, message, stackTrace);
}

/// RequestErrorCode
///
/// enum {
///   CONTENT_MODIFIED
///   DEBUG_PORT_COULD_NOT_BE_OPENED
///   FILE_NOT_ANALYZED
///   FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED
///   FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET
///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION
///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID
///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED
///   FORMAT_INVALID_FILE
///   FORMAT_WITH_ERRORS
///   GET_ERRORS_INVALID_FILE
///   GET_FIXES_INVALID_FILE
///   GET_IMPORTED_ELEMENTS_INVALID_FILE
///   GET_NAVIGATION_INVALID_FILE
///   GET_REACHABLE_SOURCES_INVALID_FILE
///   GET_SIGNATURE_INVALID_FILE
///   GET_SIGNATURE_INVALID_OFFSET
///   GET_SIGNATURE_UNKNOWN_FUNCTION
///   IMPORT_ELEMENTS_INVALID_FILE
///   INVALID_ANALYSIS_ROOT
///   INVALID_EXECUTION_CONTEXT
///   INVALID_FILE_PATH_FORMAT
///   INVALID_OVERLAY_CHANGE
///   INVALID_PARAMETER
///   INVALID_REQUEST
///   ORGANIZE_DIRECTIVES_ERROR
///   REFACTORING_REQUEST_CANCELLED
///   SERVER_ALREADY_STARTED
///   SERVER_ERROR
///   SORT_MEMBERS_INVALID_FILE
///   SORT_MEMBERS_PARSE_ERRORS
///   UNKNOWN_REQUEST
///   UNSUPPORTED_FEATURE
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum RequestErrorCode {
  /// An "analysis.getErrors" or "analysis.getNavigation" request could not be
  /// satisfied because the content of the file changed before the requested
  /// results could be computed.
  CONTENT_MODIFIED,

  /// The server was unable to open a port for the diagnostic server.
  DEBUG_PORT_COULD_NOT_BE_OPENED,

  /// A request specified a FilePath which does not match a file in an analysis
  /// root, or the requested operation is not available for the file.
  FILE_NOT_ANALYZED,

  /// A file was change while widget descriptions were being computed.
  FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED,

  /// The given location does not have a supported widget.
  FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET,

  /// The given property expression is invalid, e.g. has a syntax error.
  FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION,

  /// The given property identifier is not valid. It might have never been
  /// valid, or a change to code invalidated it, or its TTL was exceeded.
  FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID,

  /// The value of the property cannot be removed, for example because the
  /// corresponding constructor argument is required, and the server does not
  /// know what default value to use.
  FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED,

  /// An "edit.format" request specified a FilePath which does not match a Dart
  /// file in an analysis root.
  FORMAT_INVALID_FILE,

  /// An "edit.format" request specified a file that contains syntax errors.
  FORMAT_WITH_ERRORS,

  /// An "analysis.getErrors" request specified a FilePath which does not match
  /// a file currently subject to analysis.
  GET_ERRORS_INVALID_FILE,

  /// An "edit.getFixes" request specified a FilePath which does not match a
  /// file currently subject to analysis.
  GET_FIXES_INVALID_FILE,

  /// An "analysis.getImportedElements" request specified a FilePath that does
  /// not match a file currently subject to analysis.
  GET_IMPORTED_ELEMENTS_INVALID_FILE,

  /// An "analysis.getNavigation" request specified a FilePath which does not
  /// match a file currently subject to analysis.
  GET_NAVIGATION_INVALID_FILE,

  /// An "analysis.getReachableSources" request specified a FilePath which does
  /// not match a file currently subject to analysis.
  GET_REACHABLE_SOURCES_INVALID_FILE,

  /// An "analysis.getSignature" request specified a FilePath which does not
  /// match a file currently subject to analysis.
  GET_SIGNATURE_INVALID_FILE,

  /// An "analysis.getSignature" request specified an offset which is not a
  /// valid location within for the contents of the file specified FilePath.
  GET_SIGNATURE_INVALID_OFFSET,

  /// An "analysis.getSignature" request specified an offset that could not be
  /// matched to a function call.
  GET_SIGNATURE_UNKNOWN_FUNCTION,

  /// An "edit.importElements" request specified a FilePath that does not match
  /// a file currently subject to analysis.
  IMPORT_ELEMENTS_INVALID_FILE,

  /// A path passed as an argument to a request (such as analysis.reanalyze) is
  /// required to be an analysis root, but isn't.
  INVALID_ANALYSIS_ROOT,

  /// The context root used to create an execution context does not exist.
  INVALID_EXECUTION_CONTEXT,

  /// The format of the given file path is invalid, e.g. is not absolute and
  /// normalized.
  INVALID_FILE_PATH_FORMAT,

  /// An "analysis.updateContent" request contained a ChangeContentOverlay
  /// object which can't be applied, due to an edit having an offset or length
  /// that is out of range.
  INVALID_OVERLAY_CHANGE,

  /// One of the method parameters was invalid.
  INVALID_PARAMETER,

  /// A malformed request was received.
  INVALID_REQUEST,

  /// An "edit.organizeDirectives" request specified a Dart file that cannot be
  /// analyzed. The reason is described in the message.
  ORGANIZE_DIRECTIVES_ERROR,

  /// Another refactoring request was received during processing of this one.
  REFACTORING_REQUEST_CANCELLED,

  /// The analysis server has already been started (and hence won't accept new
  /// connections).
  ///
  /// This error is included for future expansion; at present the analysis
  /// server can only speak to one client at a time so this error will never
  /// occur.
  SERVER_ALREADY_STARTED,

  /// An internal error occurred in the analysis server. Also see the
  /// server.error notification.
  SERVER_ERROR,

  /// An "edit.sortMembers" request specified a FilePath which does not match a
  /// Dart file in an analysis root.
  SORT_MEMBERS_INVALID_FILE,

  /// An "edit.sortMembers" request specified a Dart file that has scan or
  /// parse errors.
  SORT_MEMBERS_PARSE_ERRORS,

  /// A request was received which the analysis server does not recognize, or
  /// cannot handle in its current configuration.
  UNKNOWN_REQUEST,

  /// The analysis server was requested to perform an action which is not
  /// supported.
  ///
  /// This is a legacy error; it will be removed before the API reaches version
  /// 1.0.
  UNSUPPORTED_FEATURE;

  factory RequestErrorCode.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'RequestErrorCode', json);
  }

  @override
  String toString() => 'RequestErrorCode.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// RuntimeCompletionExpression
///
/// {
///   "offset": int
///   "length": int
///   "type": optional RuntimeCompletionExpressionType
/// }
///
/// Clients may not extend, implement or mix-in this class.
class RuntimeCompletionExpression implements HasToJson {
  /// The offset of the expression in the code for completion.
  int offset;

  /// The length of the expression in the code for completion.
  int length;

  /// When the expression is sent from the server to the client, the type is
  /// omitted. The client should fill the type when it sends the request to the
  /// server again.
  RuntimeCompletionExpressionType? type;

  RuntimeCompletionExpression(this.offset, this.length, {this.type});

  factory RuntimeCompletionExpression.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      int length;
      if (json.containsKey('length')) {
        length = jsonDecoder.decodeInt('$jsonPath.length', json['length']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'length');
      }
      RuntimeCompletionExpressionType? type;
      if (json.containsKey('type')) {
        type = RuntimeCompletionExpressionType.fromJson(
          jsonDecoder,
          '$jsonPath.type',
          json['type'],
          clientUriConverter: clientUriConverter,
        );
      }
      return RuntimeCompletionExpression(offset, length, type: type);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'RuntimeCompletionExpression', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['offset'] = offset;
    result['length'] = length;
    var type = this.type;
    if (type != null) {
      result['type'] = type.toJson(clientUriConverter: clientUriConverter);
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is RuntimeCompletionExpression) {
      return offset == other.offset &&
          length == other.length &&
          type == other.type;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(offset, length, type);
}

/// RuntimeCompletionExpressionType
///
/// {
///   "libraryPath": optional FilePath
///   "kind": RuntimeCompletionExpressionTypeKind
///   "name": optional String
///   "typeArguments": optional List<RuntimeCompletionExpressionType>
///   "returnType": optional RuntimeCompletionExpressionType
///   "parameterTypes": optional List<RuntimeCompletionExpressionType>
///   "parameterNames": optional List<String>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class RuntimeCompletionExpressionType implements HasToJson {
  /// The path of the library that has this type. Omitted if the type is not
  /// declared in any library, e.g. "dynamic", or "void".
  String? libraryPath;

  /// The kind of the type.
  RuntimeCompletionExpressionTypeKind kind;

  /// The name of the type. Omitted if the type does not have a name, e.g. an
  /// inline function type.
  String? name;

  /// The type arguments of the type. Omitted if the type does not have type
  /// parameters.
  List<RuntimeCompletionExpressionType>? typeArguments;

  /// If the type is a function type, the return type of the function. Omitted
  /// if the type is not a function type.
  RuntimeCompletionExpressionType? returnType;

  /// If the type is a function type, the types of the function parameters of
  /// all kinds - required, optional positional, and optional named. Omitted if
  /// the type is not a function type.
  List<RuntimeCompletionExpressionType>? parameterTypes;

  /// If the type is a function type, the names of the function parameters of
  /// all kinds - required, optional positional, and optional named. The names
  /// of positional parameters are empty strings. Omitted if the type is not a
  /// function type.
  List<String>? parameterNames;

  RuntimeCompletionExpressionType(
    this.kind, {
    this.libraryPath,
    this.name,
    this.typeArguments,
    this.returnType,
    this.parameterTypes,
    this.parameterNames,
  });

  factory RuntimeCompletionExpressionType.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String? libraryPath;
      if (json.containsKey('libraryPath')) {
        libraryPath =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString(
                '$jsonPath.libraryPath',
                json['libraryPath'],
              ),
            ) ??
            jsonDecoder.decodeString(
              '$jsonPath.libraryPath',
              json['libraryPath'],
            );
      }
      RuntimeCompletionExpressionTypeKind kind;
      if (json.containsKey('kind')) {
        kind = RuntimeCompletionExpressionTypeKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kind');
      }
      String? name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      }
      List<RuntimeCompletionExpressionType>? typeArguments;
      if (json.containsKey('typeArguments')) {
        typeArguments = jsonDecoder.decodeList(
          '$jsonPath.typeArguments',
          json['typeArguments'],
          (String jsonPath, Object? json) =>
              RuntimeCompletionExpressionType.fromJson(
                jsonDecoder,
                jsonPath,
                json,
                clientUriConverter: clientUriConverter,
              ),
        );
      }
      RuntimeCompletionExpressionType? returnType;
      if (json.containsKey('returnType')) {
        returnType = RuntimeCompletionExpressionType.fromJson(
          jsonDecoder,
          '$jsonPath.returnType',
          json['returnType'],
          clientUriConverter: clientUriConverter,
        );
      }
      List<RuntimeCompletionExpressionType>? parameterTypes;
      if (json.containsKey('parameterTypes')) {
        parameterTypes = jsonDecoder.decodeList(
          '$jsonPath.parameterTypes',
          json['parameterTypes'],
          (String jsonPath, Object? json) =>
              RuntimeCompletionExpressionType.fromJson(
                jsonDecoder,
                jsonPath,
                json,
                clientUriConverter: clientUriConverter,
              ),
        );
      }
      List<String>? parameterNames;
      if (json.containsKey('parameterNames')) {
        parameterNames = jsonDecoder.decodeList(
          '$jsonPath.parameterNames',
          json['parameterNames'],
          jsonDecoder.decodeString,
        );
      }
      return RuntimeCompletionExpressionType(
        kind,
        libraryPath: libraryPath,
        name: name,
        typeArguments: typeArguments,
        returnType: returnType,
        parameterTypes: parameterTypes,
        parameterNames: parameterNames,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'RuntimeCompletionExpressionType',
        json,
      );
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var libraryPath = this.libraryPath;
    if (libraryPath != null) {
      result['libraryPath'] =
          clientUriConverter?.toClientFilePath(libraryPath) ?? libraryPath;
    }
    result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    var name = this.name;
    if (name != null) {
      result['name'] = name;
    }
    var typeArguments = this.typeArguments;
    if (typeArguments != null) {
      result['typeArguments'] =
          typeArguments
              .map(
                (RuntimeCompletionExpressionType value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    var returnType = this.returnType;
    if (returnType != null) {
      result['returnType'] = returnType.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var parameterTypes = this.parameterTypes;
    if (parameterTypes != null) {
      result['parameterTypes'] =
          parameterTypes
              .map(
                (RuntimeCompletionExpressionType value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    var parameterNames = this.parameterNames;
    if (parameterNames != null) {
      result['parameterNames'] = parameterNames;
    }
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is RuntimeCompletionExpressionType) {
      return libraryPath == other.libraryPath &&
          kind == other.kind &&
          name == other.name &&
          listEqual(
            typeArguments,
            other.typeArguments,
            (
              RuntimeCompletionExpressionType a,
              RuntimeCompletionExpressionType b,
            ) => a == b,
          ) &&
          returnType == other.returnType &&
          listEqual(
            parameterTypes,
            other.parameterTypes,
            (
              RuntimeCompletionExpressionType a,
              RuntimeCompletionExpressionType b,
            ) => a == b,
          ) &&
          listEqual(
            parameterNames,
            other.parameterNames,
            (String a, String b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    libraryPath,
    kind,
    name,
    Object.hashAll(typeArguments ?? []),
    returnType,
    Object.hashAll(parameterTypes ?? []),
    Object.hashAll(parameterNames ?? []),
  );
}

/// RuntimeCompletionExpressionTypeKind
///
/// enum {
///   DYNAMIC
///   FUNCTION
///   INTERFACE
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum RuntimeCompletionExpressionTypeKind {
  DYNAMIC,

  FUNCTION,

  INTERFACE;

  factory RuntimeCompletionExpressionTypeKind.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(
      jsonPath,
      'RuntimeCompletionExpressionTypeKind',
      json,
    );
  }

  @override
  String toString() => 'RuntimeCompletionExpressionTypeKind.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// RuntimeCompletionVariable
///
/// {
///   "name": String
///   "type": RuntimeCompletionExpressionType
/// }
///
/// Clients may not extend, implement or mix-in this class.
class RuntimeCompletionVariable implements HasToJson {
  /// The name of the variable. The name "this" has a special meaning and is
  /// used as an implicit target for runtime completion, and in explicit "this"
  /// references.
  String name;

  /// The type of the variable.
  RuntimeCompletionExpressionType type;

  RuntimeCompletionVariable(this.name, this.type);

  factory RuntimeCompletionVariable.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      RuntimeCompletionExpressionType type;
      if (json.containsKey('type')) {
        type = RuntimeCompletionExpressionType.fromJson(
          jsonDecoder,
          '$jsonPath.type',
          json['type'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'type');
      }
      return RuntimeCompletionVariable(name, type);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'RuntimeCompletionVariable', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    result['type'] = type.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is RuntimeCompletionVariable) {
      return name == other.name && type == other.type;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(name, type);
}

/// search.findElementReferences params
///
/// {
///   "file": FilePath
///   "offset": int
///   "includePotential": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchFindElementReferencesParams implements RequestParams {
  /// The file containing the declaration of or reference to the element used
  /// to define the search.
  String file;

  /// The offset within the file of the declaration of or reference to the
  /// element.
  int offset;

  /// True if potential matches are to be included in the results.
  bool includePotential;

  SearchFindElementReferencesParams(
    this.file,
    this.offset,
    this.includePotential,
  );

  factory SearchFindElementReferencesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      bool includePotential;
      if (json.containsKey('includePotential')) {
        includePotential = jsonDecoder.decodeBool(
          '$jsonPath.includePotential',
          json['includePotential'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'includePotential');
      }
      return SearchFindElementReferencesParams(file, offset, includePotential);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.findElementReferences params',
        json,
      );
    }
  }

  factory SearchFindElementReferencesParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchFindElementReferencesParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    result['includePotential'] = includePotential;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'search.findElementReferences',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchFindElementReferencesParams) {
      return file == other.file &&
          offset == other.offset &&
          includePotential == other.includePotential;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset, includePotential);
}

/// search.findElementReferences result
///
/// {
///   "id": optional SearchId
///   "element": optional Element
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchFindElementReferencesResult implements ResponseResult {
  /// 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.
  String? id;

  /// 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.
  Element? element;

  SearchFindElementReferencesResult({this.id, this.element});

  factory SearchFindElementReferencesResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String? id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeString('$jsonPath.id', json['id']);
      }
      Element? element;
      if (json.containsKey('element')) {
        element = Element.fromJson(
          jsonDecoder,
          '$jsonPath.element',
          json['element'],
          clientUriConverter: clientUriConverter,
        );
      }
      return SearchFindElementReferencesResult(id: id, element: element);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.findElementReferences result',
        json,
      );
    }
  }

  factory SearchFindElementReferencesResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchFindElementReferencesResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var id = this.id;
    if (id != null) {
      result['id'] = id;
    }
    var element = this.element;
    if (element != null) {
      result['element'] = element.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchFindElementReferencesResult) {
      return id == other.id && element == other.element;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(id, element);
}

/// search.findMemberDeclarations params
///
/// {
///   "name": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchFindMemberDeclarationsParams implements RequestParams {
  /// The name of the declarations to be found.
  String name;

  SearchFindMemberDeclarationsParams(this.name);

  factory SearchFindMemberDeclarationsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      return SearchFindMemberDeclarationsParams(name);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.findMemberDeclarations params',
        json,
      );
    }
  }

  factory SearchFindMemberDeclarationsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchFindMemberDeclarationsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'search.findMemberDeclarations',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchFindMemberDeclarationsParams) {
      return name == other.name;
    }
    return false;
  }

  @override
  int get hashCode => name.hashCode;
}

/// search.findMemberDeclarations result
///
/// {
///   "id": SearchId
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchFindMemberDeclarationsResult implements ResponseResult {
  /// The identifier used to associate results with this search request.
  String id;

  SearchFindMemberDeclarationsResult(this.id);

  factory SearchFindMemberDeclarationsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeString('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      return SearchFindMemberDeclarationsResult(id);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.findMemberDeclarations result',
        json,
      );
    }
  }

  factory SearchFindMemberDeclarationsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchFindMemberDeclarationsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['id'] = id;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchFindMemberDeclarationsResult) {
      return id == other.id;
    }
    return false;
  }

  @override
  int get hashCode => id.hashCode;
}

/// search.findMemberReferences params
///
/// {
///   "name": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchFindMemberReferencesParams implements RequestParams {
  /// The name of the references to be found.
  String name;

  SearchFindMemberReferencesParams(this.name);

  factory SearchFindMemberReferencesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String name;
      if (json.containsKey('name')) {
        name = jsonDecoder.decodeString('$jsonPath.name', json['name']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'name');
      }
      return SearchFindMemberReferencesParams(name);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.findMemberReferences params',
        json,
      );
    }
  }

  factory SearchFindMemberReferencesParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchFindMemberReferencesParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['name'] = name;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'search.findMemberReferences',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchFindMemberReferencesParams) {
      return name == other.name;
    }
    return false;
  }

  @override
  int get hashCode => name.hashCode;
}

/// search.findMemberReferences result
///
/// {
///   "id": SearchId
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchFindMemberReferencesResult implements ResponseResult {
  /// The identifier used to associate results with this search request.
  String id;

  SearchFindMemberReferencesResult(this.id);

  factory SearchFindMemberReferencesResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeString('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      return SearchFindMemberReferencesResult(id);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.findMemberReferences result',
        json,
      );
    }
  }

  factory SearchFindMemberReferencesResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchFindMemberReferencesResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['id'] = id;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchFindMemberReferencesResult) {
      return id == other.id;
    }
    return false;
  }

  @override
  int get hashCode => id.hashCode;
}

/// search.findTopLevelDeclarations params
///
/// {
///   "pattern": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchFindTopLevelDeclarationsParams implements RequestParams {
  /// The regular expression used to match the names of the declarations to be
  /// found.
  String pattern;

  SearchFindTopLevelDeclarationsParams(this.pattern);

  factory SearchFindTopLevelDeclarationsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String pattern;
      if (json.containsKey('pattern')) {
        pattern = jsonDecoder.decodeString(
          '$jsonPath.pattern',
          json['pattern'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'pattern');
      }
      return SearchFindTopLevelDeclarationsParams(pattern);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.findTopLevelDeclarations params',
        json,
      );
    }
  }

  factory SearchFindTopLevelDeclarationsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchFindTopLevelDeclarationsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['pattern'] = pattern;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'search.findTopLevelDeclarations',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchFindTopLevelDeclarationsParams) {
      return pattern == other.pattern;
    }
    return false;
  }

  @override
  int get hashCode => pattern.hashCode;
}

/// search.findTopLevelDeclarations result
///
/// {
///   "id": SearchId
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchFindTopLevelDeclarationsResult implements ResponseResult {
  /// The identifier used to associate results with this search request.
  String id;

  SearchFindTopLevelDeclarationsResult(this.id);

  factory SearchFindTopLevelDeclarationsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeString('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      return SearchFindTopLevelDeclarationsResult(id);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.findTopLevelDeclarations result',
        json,
      );
    }
  }

  factory SearchFindTopLevelDeclarationsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchFindTopLevelDeclarationsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['id'] = id;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchFindTopLevelDeclarationsResult) {
      return id == other.id;
    }
    return false;
  }

  @override
  int get hashCode => id.hashCode;
}

/// search.getElementDeclarations params
///
/// {
///   "file": optional FilePath
///   "pattern": optional String
///   "maxResults": optional int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchGetElementDeclarationsParams implements RequestParams {
  /// If this field is provided, return only declarations in this file. If this
  /// field is missing, return declarations in all files.
  String? file;

  /// The regular expression used to match the names of declarations. If this
  /// field is missing, return all declarations.
  String? pattern;

  /// The maximum number of declarations to return. If this field is missing,
  /// return all matching declarations.
  int? maxResults;

  SearchGetElementDeclarationsParams({
    this.file,
    this.pattern,
    this.maxResults,
  });

  factory SearchGetElementDeclarationsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String? file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      }
      String? pattern;
      if (json.containsKey('pattern')) {
        pattern = jsonDecoder.decodeString(
          '$jsonPath.pattern',
          json['pattern'],
        );
      }
      int? maxResults;
      if (json.containsKey('maxResults')) {
        maxResults = jsonDecoder.decodeInt(
          '$jsonPath.maxResults',
          json['maxResults'],
        );
      }
      return SearchGetElementDeclarationsParams(
        file: file,
        pattern: pattern,
        maxResults: maxResults,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.getElementDeclarations params',
        json,
      );
    }
  }

  factory SearchGetElementDeclarationsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchGetElementDeclarationsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var file = this.file;
    if (file != null) {
      result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    }
    var pattern = this.pattern;
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    var maxResults = this.maxResults;
    if (maxResults != null) {
      result['maxResults'] = maxResults;
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'search.getElementDeclarations',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchGetElementDeclarationsParams) {
      return file == other.file &&
          pattern == other.pattern &&
          maxResults == other.maxResults;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, pattern, maxResults);
}

/// search.getElementDeclarations result
///
/// {
///   "declarations": List<ElementDeclaration>
///   "files": List<FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchGetElementDeclarationsResult implements ResponseResult {
  /// The list of declarations.
  List<ElementDeclaration> declarations;

  /// The list of the paths of files with declarations.
  List<String> files;

  SearchGetElementDeclarationsResult(this.declarations, this.files);

  factory SearchGetElementDeclarationsResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<ElementDeclaration> declarations;
      if (json.containsKey('declarations')) {
        declarations = jsonDecoder.decodeList(
          '$jsonPath.declarations',
          json['declarations'],
          (String jsonPath, Object? json) => ElementDeclaration.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'declarations');
      }
      List<String> files;
      if (json.containsKey('files')) {
        files = jsonDecoder.decodeList(
          '$jsonPath.files',
          json['files'],
          (String jsonPath, Object? json) =>
              clientUriConverter?.fromClientFilePath(
                jsonDecoder.decodeString(jsonPath, json),
              ) ??
              jsonDecoder.decodeString(jsonPath, json),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'files');
      }
      return SearchGetElementDeclarationsResult(declarations, files);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.getElementDeclarations result',
        json,
      );
    }
  }

  factory SearchGetElementDeclarationsResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchGetElementDeclarationsResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['declarations'] =
        declarations
            .map(
              (ElementDeclaration value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['files'] =
        files
            .map(
              (String value) =>
                  clientUriConverter?.toClientFilePath(value) ?? value,
            )
            .toList();
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchGetElementDeclarationsResult) {
      return listEqual(
            declarations,
            other.declarations,
            (ElementDeclaration a, ElementDeclaration b) => a == b,
          ) &&
          listEqual(files, other.files, (String a, String b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(Object.hashAll(declarations), Object.hashAll(files));
}

/// search.getTypeHierarchy params
///
/// {
///   "file": FilePath
///   "offset": int
///   "superOnly": optional bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchGetTypeHierarchyParams implements RequestParams {
  /// The file containing the declaration or reference to the type for which a
  /// hierarchy is being requested.
  String file;

  /// The offset of the name of the type within the file.
  int offset;

  /// True if the client is only requesting superclasses and interfaces
  /// hierarchy.
  bool? superOnly;

  SearchGetTypeHierarchyParams(this.file, this.offset, {this.superOnly});

  factory SearchGetTypeHierarchyParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String file;
      if (json.containsKey('file')) {
        file =
            clientUriConverter?.fromClientFilePath(
              jsonDecoder.decodeString('$jsonPath.file', json['file']),
            ) ??
            jsonDecoder.decodeString('$jsonPath.file', json['file']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'file');
      }
      int offset;
      if (json.containsKey('offset')) {
        offset = jsonDecoder.decodeInt('$jsonPath.offset', json['offset']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'offset');
      }
      bool? superOnly;
      if (json.containsKey('superOnly')) {
        superOnly = jsonDecoder.decodeBool(
          '$jsonPath.superOnly',
          json['superOnly'],
        );
      }
      return SearchGetTypeHierarchyParams(file, offset, superOnly: superOnly);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.getTypeHierarchy params',
        json,
      );
    }
  }

  factory SearchGetTypeHierarchyParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchGetTypeHierarchyParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['file'] = clientUriConverter?.toClientFilePath(file) ?? file;
    result['offset'] = offset;
    var superOnly = this.superOnly;
    if (superOnly != null) {
      result['superOnly'] = superOnly;
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'search.getTypeHierarchy',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchGetTypeHierarchyParams) {
      return file == other.file &&
          offset == other.offset &&
          superOnly == other.superOnly;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(file, offset, superOnly);
}

/// search.getTypeHierarchy result
///
/// {
///   "hierarchyItems": optional List<TypeHierarchyItem>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchGetTypeHierarchyResult implements ResponseResult {
  /// 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.
  List<TypeHierarchyItem>? hierarchyItems;

  SearchGetTypeHierarchyResult({this.hierarchyItems});

  factory SearchGetTypeHierarchyResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<TypeHierarchyItem>? hierarchyItems;
      if (json.containsKey('hierarchyItems')) {
        hierarchyItems = jsonDecoder.decodeList(
          '$jsonPath.hierarchyItems',
          json['hierarchyItems'],
          (String jsonPath, Object? json) => TypeHierarchyItem.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      }
      return SearchGetTypeHierarchyResult(hierarchyItems: hierarchyItems);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'search.getTypeHierarchy result',
        json,
      );
    }
  }

  factory SearchGetTypeHierarchyResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchGetTypeHierarchyResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var hierarchyItems = this.hierarchyItems;
    if (hierarchyItems != null) {
      result['hierarchyItems'] =
          hierarchyItems
              .map(
                (TypeHierarchyItem value) =>
                    value.toJson(clientUriConverter: clientUriConverter),
              )
              .toList();
    }
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchGetTypeHierarchyResult) {
      return listEqual(
        hierarchyItems,
        other.hierarchyItems,
        (TypeHierarchyItem a, TypeHierarchyItem b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(hierarchyItems ?? []);
}

/// SearchResult
///
/// {
///   "location": Location
///   "kind": SearchResultKind
///   "isPotential": bool
///   "path": List<Element>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchResult implements HasToJson {
  /// The location of the code that matched the search criteria.
  Location location;

  /// The kind of element that was found or the kind of reference that was
  /// found.
  SearchResultKind kind;

  /// True if the result is a potential match but cannot be confirmed to be a
  /// match. For example, if all references to a method m defined in some class
  /// were requested, and a reference to a method m from an unknown class were
  /// found, it would be marked as being a potential match.
  bool isPotential;

  /// The elements that contain the result, starting with the most immediately
  /// enclosing ancestor and ending with the library.
  List<Element> path;

  SearchResult(this.location, this.kind, this.isPotential, this.path);

  factory SearchResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Location location;
      if (json.containsKey('location')) {
        location = Location.fromJson(
          jsonDecoder,
          '$jsonPath.location',
          json['location'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'location');
      }
      SearchResultKind kind;
      if (json.containsKey('kind')) {
        kind = SearchResultKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kind');
      }
      bool isPotential;
      if (json.containsKey('isPotential')) {
        isPotential = jsonDecoder.decodeBool(
          '$jsonPath.isPotential',
          json['isPotential'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'isPotential');
      }
      List<Element> path;
      if (json.containsKey('path')) {
        path = jsonDecoder.decodeList(
          '$jsonPath.path',
          json['path'],
          (String jsonPath, Object? json) => Element.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'path');
      }
      return SearchResult(location, kind, isPotential, path);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'SearchResult', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['location'] = location.toJson(
      clientUriConverter: clientUriConverter,
    );
    result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    result['isPotential'] = isPotential;
    result['path'] =
        path
            .map(
              (Element value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchResult) {
      return location == other.location &&
          kind == other.kind &&
          isPotential == other.isPotential &&
          listEqual(path, other.path, (Element a, Element b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(location, kind, isPotential, Object.hashAll(path));
}

/// SearchResultKind
///
/// enum {
///   DECLARATION
///   INVOCATION
///   READ
///   READ_WRITE
///   REFERENCE
///   UNKNOWN
///   WRITE
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum SearchResultKind {
  /// The declaration of an element.
  DECLARATION,

  /// The invocation of a function or method.
  INVOCATION,

  /// A reference to a field, parameter or variable where it is being read.
  READ,

  /// A reference to a field, parameter or variable where it is being read and
  /// written.
  READ_WRITE,

  /// A reference to an element.
  REFERENCE,

  /// Some other kind of search result.
  UNKNOWN,

  /// A reference to a field, parameter or variable where it is being written.
  WRITE;

  factory SearchResultKind.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'SearchResultKind', json);
  }

  @override
  String toString() => 'SearchResultKind.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// search.results params
///
/// {
///   "id": SearchId
///   "results": List<SearchResult>
///   "isLast": bool
/// }
///
/// Clients may not extend, implement or mix-in this class.
class SearchResultsParams implements HasToJson {
  /// The id associated with the search.
  String id;

  /// The search results being reported.
  List<SearchResult> results;

  /// True if this is that last set of results that will be returned for the
  /// indicated search.
  bool isLast;

  SearchResultsParams(this.id, this.results, this.isLast);

  factory SearchResultsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeString('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      List<SearchResult> results;
      if (json.containsKey('results')) {
        results = jsonDecoder.decodeList(
          '$jsonPath.results',
          json['results'],
          (String jsonPath, Object? json) => SearchResult.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'results');
      }
      bool isLast;
      if (json.containsKey('isLast')) {
        isLast = jsonDecoder.decodeBool('$jsonPath.isLast', json['isLast']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'isLast');
      }
      return SearchResultsParams(id, results, isLast);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'search.results params', json);
    }
  }

  factory SearchResultsParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return SearchResultsParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['id'] = id;
    result['results'] =
        results
            .map(
              (SearchResult value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    result['isLast'] = isLast;
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'search.results',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is SearchResultsParams) {
      return id == other.id &&
          listEqual(
            results,
            other.results,
            (SearchResult a, SearchResult b) => a == b,
          ) &&
          isLast == other.isLast;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(id, Object.hashAll(results), isLast);
}

/// server.cancelRequest params
///
/// {
///   "id": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerCancelRequestParams implements RequestParams {
  /// The id of the request that should be cancelled.
  String id;

  ServerCancelRequestParams(this.id);

  factory ServerCancelRequestParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String id;
      if (json.containsKey('id')) {
        id = jsonDecoder.decodeString('$jsonPath.id', json['id']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'id');
      }
      return ServerCancelRequestParams(id);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'server.cancelRequest params', json);
    }
  }

  factory ServerCancelRequestParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerCancelRequestParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['id'] = id;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'server.cancelRequest',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerCancelRequestParams) {
      return id == other.id;
    }
    return false;
  }

  @override
  int get hashCode => id.hashCode;
}

/// server.cancelRequest result
///
/// Clients may not extend, implement or mix-in this class.
class ServerCancelRequestResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is ServerCancelRequestResult;

  @override
  int get hashCode => 183255719;
}

/// server.connected params
///
/// {
///   "version": String
///   "pid": int
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerConnectedParams implements HasToJson {
  /// The version number of the analysis server.
  String version;

  /// The process id of the analysis server process.
  int pid;

  ServerConnectedParams(this.version, this.pid);

  factory ServerConnectedParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String version;
      if (json.containsKey('version')) {
        version = jsonDecoder.decodeString(
          '$jsonPath.version',
          json['version'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'version');
      }
      int pid;
      if (json.containsKey('pid')) {
        pid = jsonDecoder.decodeInt('$jsonPath.pid', json['pid']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'pid');
      }
      return ServerConnectedParams(version, pid);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'server.connected params', json);
    }
  }

  factory ServerConnectedParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerConnectedParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['version'] = version;
    result['pid'] = pid;
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'server.connected',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerConnectedParams) {
      return version == other.version && pid == other.pid;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(version, pid);
}

/// server.error params
///
/// {
///   "isFatal": bool
///   "message": String
///   "stackTrace": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerErrorParams implements HasToJson {
  /// True if the error is a fatal error, meaning that the server will shutdown
  /// automatically after sending this notification.
  bool isFatal;

  /// The error message indicating what kind of error was encountered.
  String message;

  /// The stack trace associated with the generation of the error, used for
  /// debugging the server.
  String stackTrace;

  ServerErrorParams(this.isFatal, this.message, this.stackTrace);

  factory ServerErrorParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      bool isFatal;
      if (json.containsKey('isFatal')) {
        isFatal = jsonDecoder.decodeBool('$jsonPath.isFatal', json['isFatal']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'isFatal');
      }
      String message;
      if (json.containsKey('message')) {
        message = jsonDecoder.decodeString(
          '$jsonPath.message',
          json['message'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'message');
      }
      String stackTrace;
      if (json.containsKey('stackTrace')) {
        stackTrace = jsonDecoder.decodeString(
          '$jsonPath.stackTrace',
          json['stackTrace'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'stackTrace');
      }
      return ServerErrorParams(isFatal, message, stackTrace);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'server.error params', json);
    }
  }

  factory ServerErrorParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerErrorParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['isFatal'] = isFatal;
    result['message'] = message;
    result['stackTrace'] = stackTrace;
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'server.error',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerErrorParams) {
      return isFatal == other.isFatal &&
          message == other.message &&
          stackTrace == other.stackTrace;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(isFatal, message, stackTrace);
}

/// server.getVersion params
///
/// Clients may not extend, implement or mix-in this class.
class ServerGetVersionParams implements RequestParams {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(id, 'server.getVersion');
  }

  @override
  bool operator ==(Object other) => other is ServerGetVersionParams;

  @override
  int get hashCode => 55877452;
}

/// server.getVersion result
///
/// {
///   "version": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerGetVersionResult implements ResponseResult {
  /// The version number of the analysis server.
  String version;

  ServerGetVersionResult(this.version);

  factory ServerGetVersionResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String version;
      if (json.containsKey('version')) {
        version = jsonDecoder.decodeString(
          '$jsonPath.version',
          json['version'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'version');
      }
      return ServerGetVersionResult(version);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'server.getVersion result', json);
    }
  }

  factory ServerGetVersionResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerGetVersionResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['version'] = version;
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerGetVersionResult) {
      return version == other.version;
    }
    return false;
  }

  @override
  int get hashCode => version.hashCode;
}

/// ServerLogEntry
///
/// {
///   "time": int
///   "kind": ServerLogEntryKind
///   "data": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerLogEntry implements HasToJson {
  /// The time (milliseconds since epoch) at which the server created this log
  /// entry.
  int time;

  /// The kind of the entry, used to determine how to interpret the "data"
  /// field.
  ServerLogEntryKind kind;

  /// The payload of the entry, the actual format is determined by the "kind"
  /// field.
  String data;

  ServerLogEntry(this.time, this.kind, this.data);

  factory ServerLogEntry.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      int time;
      if (json.containsKey('time')) {
        time = jsonDecoder.decodeInt('$jsonPath.time', json['time']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'time');
      }
      ServerLogEntryKind kind;
      if (json.containsKey('kind')) {
        kind = ServerLogEntryKind.fromJson(
          jsonDecoder,
          '$jsonPath.kind',
          json['kind'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'kind');
      }
      String data;
      if (json.containsKey('data')) {
        data = jsonDecoder.decodeString('$jsonPath.data', json['data']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'data');
      }
      return ServerLogEntry(time, kind, data);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'ServerLogEntry', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['time'] = time;
    result['kind'] = kind.toJson(clientUriConverter: clientUriConverter);
    result['data'] = data;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerLogEntry) {
      return time == other.time && kind == other.kind && data == other.data;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(time, kind, data);
}

/// ServerLogEntryKind
///
/// enum {
///   NOTIFICATION
///   RAW
///   REQUEST
///   RESPONSE
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum ServerLogEntryKind {
  /// A notification from the server, such as "analysis.highlights". The "data"
  /// field contains a JSON object with abbreviated notification.
  NOTIFICATION,

  /// Arbitrary string, describing some event that happened in the server, e.g.
  /// starting a file analysis, and details which files were accessed. These
  /// entries are not structured, but provide context information about
  /// requests and notification, and can be related by "time" for further
  /// manual analysis.
  RAW,

  /// A request from the client, as the server views it, e.g.
  /// "edit.getAssists". The "data" field contains a JSON object with
  /// abbreviated request.
  REQUEST,

  /// Various counters and measurements related to execution of a request. The
  /// "data" field contains a JSON object with following fields:
  ///
  /// - "id" - the id of the request - copied from the request.
  /// - "method" - the method of the request, e.g. "edit.getAssists".
  /// - "clientRequestTime" - the time (milliseconds since epoch) at which the
  ///   client made the request - copied from the request.
  /// - "serverRequestTime" - the time (milliseconds since epoch) at which the
  ///   server received and decoded the JSON request.
  /// - "responseTime" - the time (milliseconds since epoch) at which the
  ///   server created the response to be encoded into JSON and sent to the
  ///   client.
  RESPONSE;

  factory ServerLogEntryKind.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'ServerLogEntryKind', json);
  }

  @override
  String toString() => 'ServerLogEntryKind.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// server.log params
///
/// {
///   "entry": ServerLogEntry
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerLogParams implements HasToJson {
  ServerLogEntry entry;

  ServerLogParams(this.entry);

  factory ServerLogParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      ServerLogEntry entry;
      if (json.containsKey('entry')) {
        entry = ServerLogEntry.fromJson(
          jsonDecoder,
          '$jsonPath.entry',
          json['entry'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'entry');
      }
      return ServerLogParams(entry);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'server.log params', json);
    }
  }

  factory ServerLogParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerLogParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['entry'] = entry.toJson(clientUriConverter: clientUriConverter);
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'server.log',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerLogParams) {
      return entry == other.entry;
    }
    return false;
  }

  @override
  int get hashCode => entry.hashCode;
}

/// server.openUrlRequest params
///
/// {
///   "url": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerOpenUrlRequestParams implements RequestParams {
  /// The URL to be opened.
  String url;

  ServerOpenUrlRequestParams(this.url);

  factory ServerOpenUrlRequestParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String url;
      if (json.containsKey('url')) {
        url = jsonDecoder.decodeString('$jsonPath.url', json['url']);
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'url');
      }
      return ServerOpenUrlRequestParams(url);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'server.openUrlRequest params',
        json,
      );
    }
  }

  factory ServerOpenUrlRequestParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerOpenUrlRequestParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['url'] = url;
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'server.openUrlRequest',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerOpenUrlRequestParams) {
      return url == other.url;
    }
    return false;
  }

  @override
  int get hashCode => url.hashCode;
}

/// server.openUrlRequest result
///
/// Clients may not extend, implement or mix-in this class.
class ServerOpenUrlRequestResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is ServerOpenUrlRequestResult;

  @override
  int get hashCode => 561630021;
}

/// server.pluginError params
///
/// {
///   "message": String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerPluginErrorParams implements HasToJson {
  /// The error message indicating what kind of error was encountered.
  String message;

  ServerPluginErrorParams(this.message);

  factory ServerPluginErrorParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String message;
      if (json.containsKey('message')) {
        message = jsonDecoder.decodeString(
          '$jsonPath.message',
          json['message'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'message');
      }
      return ServerPluginErrorParams(message);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'server.pluginError params', json);
    }
  }

  factory ServerPluginErrorParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerPluginErrorParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['message'] = message;
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'server.pluginError',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerPluginErrorParams) {
      return message == other.message;
    }
    return false;
  }

  @override
  int get hashCode => message.hashCode;
}

/// ServerService
///
/// enum {
///   LOG
///   STATUS
/// }
///
/// Clients may not extend, implement or mix-in this class.
enum ServerService {
  LOG,

  STATUS;

  factory ServerService.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    if (json is String) {
      try {
        return values.byName(json);
      } catch (_) {
        // Fall through
      }
    }
    throw jsonDecoder.mismatch(jsonPath, 'ServerService', json);
  }

  @override
  String toString() => 'ServerService.$name';

  String toJson({required ClientUriConverter? clientUriConverter}) => name;
}

/// server.setClientCapabilities params
///
/// {
///   "requests": List<String>
///   "supportsUris": optional bool
///   "lspCapabilities": optional object
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerSetClientCapabilitiesParams implements RequestParams {
  /// The names of the requests that the server can safely send to the client.
  /// Only requests whose name is in the list will be sent.
  ///
  /// A request should only be included in the list if the client will
  /// unconditionally honor the request.
  ///
  /// The default, used before this request is received, is an empty list.
  ///
  /// The following is a list of the names of the requests that can be
  /// specified:
  ///
  /// - `openUrlRequest`
  /// - `showMessageRequest`
  List<String> requests;

  /// True if the client supports the server sending URIs in place of file
  /// paths.
  ///
  /// In this mode, the server will use URIs in all protocol fields with the
  /// type `FilePath`. Returned URIs may be `file://` URIs or custom schemes.
  /// The client can fetch the file contents for URIs with custom schemes (and
  /// receive modification events) through the LSP protocol (see the "lsp"
  /// domain).
  ///
  /// LSP notifications are automatically enabled when the client sets this
  /// capability.
  bool? supportsUris;

  /// LSP capabilities of the client as defined by the Language Server Protocol
  /// specification.
  ///
  /// If custom LSP capabilities are to be used, the setClientCapabilities
  /// request should be called before any LSP requests are made to the server.
  ///
  /// If LSP capabilities are not provided or no setClientCapabilities request
  /// is made, a very basic set of capabilities will be assumed.
  Object? lspCapabilities;

  ServerSetClientCapabilitiesParams(
    this.requests, {
    this.supportsUris,
    this.lspCapabilities,
  });

  factory ServerSetClientCapabilitiesParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<String> requests;
      if (json.containsKey('requests')) {
        requests = jsonDecoder.decodeList(
          '$jsonPath.requests',
          json['requests'],
          jsonDecoder.decodeString,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'requests');
      }
      bool? supportsUris;
      if (json.containsKey('supportsUris')) {
        supportsUris = jsonDecoder.decodeBool(
          '$jsonPath.supportsUris',
          json['supportsUris'],
        );
      }
      Object? lspCapabilities;
      if (json.containsKey('lspCapabilities')) {
        lspCapabilities = json['lspCapabilities'] as Object;
      }
      return ServerSetClientCapabilitiesParams(
        requests,
        supportsUris: supportsUris,
        lspCapabilities: lspCapabilities,
      );
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'server.setClientCapabilities params',
        json,
      );
    }
  }

  factory ServerSetClientCapabilitiesParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerSetClientCapabilitiesParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['requests'] = requests;
    var supportsUris = this.supportsUris;
    if (supportsUris != null) {
      result['supportsUris'] = supportsUris;
    }
    var lspCapabilities = this.lspCapabilities;
    if (lspCapabilities != null) {
      result['lspCapabilities'] = lspCapabilities;
    }
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'server.setClientCapabilities',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerSetClientCapabilitiesParams) {
      return listEqual(
            requests,
            other.requests,
            (String a, String b) => a == b,
          ) &&
          supportsUris == other.supportsUris &&
          lspCapabilities == other.lspCapabilities;
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(Object.hashAll(requests), supportsUris, lspCapabilities);
}

/// server.setClientCapabilities result
///
/// Clients may not extend, implement or mix-in this class.
class ServerSetClientCapabilitiesResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is ServerSetClientCapabilitiesResult;

  @override
  int get hashCode => 806805916;
}

/// server.setSubscriptions params
///
/// {
///   "subscriptions": List<ServerService>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerSetSubscriptionsParams implements RequestParams {
  /// A list of the services being subscribed to.
  List<ServerService> subscriptions;

  ServerSetSubscriptionsParams(this.subscriptions);

  factory ServerSetSubscriptionsParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      List<ServerService> subscriptions;
      if (json.containsKey('subscriptions')) {
        subscriptions = jsonDecoder.decodeList(
          '$jsonPath.subscriptions',
          json['subscriptions'],
          (String jsonPath, Object? json) => ServerService.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'subscriptions');
      }
      return ServerSetSubscriptionsParams(subscriptions);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'server.setSubscriptions params',
        json,
      );
    }
  }

  factory ServerSetSubscriptionsParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerSetSubscriptionsParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['subscriptions'] =
        subscriptions
            .map(
              (ServerService value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'server.setSubscriptions',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerSetSubscriptionsParams) {
      return listEqual(
        subscriptions,
        other.subscriptions,
        (ServerService a, ServerService b) => a == b,
      );
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll(subscriptions);
}

/// server.setSubscriptions result
///
/// Clients may not extend, implement or mix-in this class.
class ServerSetSubscriptionsResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is ServerSetSubscriptionsResult;

  @override
  int get hashCode => 748820900;
}

/// server.showMessageRequest params
///
/// {
///   "type": MessageType
///   "message": String
///   "actions": List<MessageAction>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerShowMessageRequestParams implements RequestParams {
  /// The type of the message.
  MessageType type;

  /// The message to be displayed.
  String message;

  /// The labels of the buttons by which the user can dismiss the message.
  List<MessageAction> actions;

  ServerShowMessageRequestParams(this.type, this.message, this.actions);

  factory ServerShowMessageRequestParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      MessageType type;
      if (json.containsKey('type')) {
        type = MessageType.fromJson(
          jsonDecoder,
          '$jsonPath.type',
          json['type'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'type');
      }
      String message;
      if (json.containsKey('message')) {
        message = jsonDecoder.decodeString(
          '$jsonPath.message',
          json['message'],
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'message');
      }
      List<MessageAction> actions;
      if (json.containsKey('actions')) {
        actions = jsonDecoder.decodeList(
          '$jsonPath.actions',
          json['actions'],
          (String jsonPath, Object? json) => MessageAction.fromJson(
            jsonDecoder,
            jsonPath,
            json,
            clientUriConverter: clientUriConverter,
          ),
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'actions');
      }
      return ServerShowMessageRequestParams(type, message, actions);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'server.showMessageRequest params',
        json,
      );
    }
  }

  factory ServerShowMessageRequestParams.fromRequest(
    Request request, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerShowMessageRequestParams.fromJson(
      RequestDecoder(request),
      'params',
      request.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['type'] = type.toJson(clientUriConverter: clientUriConverter);
    result['message'] = message;
    result['actions'] =
        actions
            .map(
              (MessageAction value) =>
                  value.toJson(clientUriConverter: clientUriConverter),
            )
            .toList();
    return result;
  }

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(
      id,
      'server.showMessageRequest',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerShowMessageRequestParams) {
      return type == other.type &&
          message == other.message &&
          listEqual(
            actions,
            other.actions,
            (MessageAction a, MessageAction b) => a == b,
          );
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(type, message, Object.hashAll(actions));
}

/// server.showMessageRequest result
///
/// {
///   "action": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerShowMessageRequestResult implements ResponseResult {
  /// The label of the action that was selected by the user. May be omitted or
  /// `null` if the user dismissed the message without clicking an action
  /// button.
  String? action;

  ServerShowMessageRequestResult({this.action});

  factory ServerShowMessageRequestResult.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      String? action;
      if (json.containsKey('action')) {
        action = jsonDecoder.decodeString('$jsonPath.action', json['action']);
      }
      return ServerShowMessageRequestResult(action: action);
    } else {
      throw jsonDecoder.mismatch(
        jsonPath,
        'server.showMessageRequest result',
        json,
      );
    }
  }

  factory ServerShowMessageRequestResult.fromResponse(
    Response response, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerShowMessageRequestResult.fromJson(
      ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
      'result',
      response.result,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var action = this.action;
    if (action != null) {
      result['action'] = action;
    }
    return result;
  }

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id, result: toJson(clientUriConverter: clientUriConverter));
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerShowMessageRequestResult) {
      return action == other.action;
    }
    return false;
  }

  @override
  int get hashCode => action.hashCode;
}

/// server.shutdown params
///
/// Clients may not extend, implement or mix-in this class.
class ServerShutdownParams implements RequestParams {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Request toRequest(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Request(id, 'server.shutdown');
  }

  @override
  bool operator ==(Object other) => other is ServerShutdownParams;

  @override
  int get hashCode => 366630911;
}

/// server.shutdown result
///
/// Clients may not extend, implement or mix-in this class.
class ServerShutdownResult implements ResponseResult {
  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) => {};

  @override
  Response toResponse(
    String id, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return Response(id);
  }

  @override
  bool operator ==(Object other) => other is ServerShutdownResult;

  @override
  int get hashCode => 193626532;
}

/// server.status params
///
/// {
///   "analysis": optional AnalysisStatus
///   "pub": optional PubStatus
/// }
///
/// Clients may not extend, implement or mix-in this class.
class ServerStatusParams implements HasToJson {
  /// The current status of analysis, including whether analysis is being
  /// performed and if so what is being analyzed.
  AnalysisStatus? analysis;

  /// 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.
  PubStatus? pub;

  ServerStatusParams({this.analysis, this.pub});

  factory ServerStatusParams.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      AnalysisStatus? analysis;
      if (json.containsKey('analysis')) {
        analysis = AnalysisStatus.fromJson(
          jsonDecoder,
          '$jsonPath.analysis',
          json['analysis'],
          clientUriConverter: clientUriConverter,
        );
      }
      PubStatus? pub;
      if (json.containsKey('pub')) {
        pub = PubStatus.fromJson(
          jsonDecoder,
          '$jsonPath.pub',
          json['pub'],
          clientUriConverter: clientUriConverter,
        );
      }
      return ServerStatusParams(analysis: analysis, pub: pub);
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'server.status params', json);
    }
  }

  factory ServerStatusParams.fromNotification(
    Notification notification, {
    required ClientUriConverter? clientUriConverter,
  }) {
    return ServerStatusParams.fromJson(
      ResponseDecoder(null),
      'params',
      notification.params,
      clientUriConverter: clientUriConverter,
    );
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    var analysis = this.analysis;
    if (analysis != null) {
      result['analysis'] = analysis.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var pub = this.pub;
    if (pub != null) {
      result['pub'] = pub.toJson(clientUriConverter: clientUriConverter);
    }
    return result;
  }

  Notification toNotification({
    required ClientUriConverter? clientUriConverter,
  }) {
    return Notification(
      'server.status',
      toJson(clientUriConverter: clientUriConverter),
    );
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is ServerStatusParams) {
      return analysis == other.analysis && pub == other.pub;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(analysis, pub);
}

/// TypeHierarchyItem
///
/// {
///   "classElement": Element
///   "displayName": optional String
///   "memberElement": optional Element
///   "superclass": optional int
///   "interfaces": List<int>
///   "mixins": List<int>
///   "subclasses": List<int>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class TypeHierarchyItem implements HasToJson {
  /// The class element represented by this item.
  Element classElement;

  /// The name to be displayed for the class. This field will be omitted if the
  /// display name is the same as the name of the element. The display name is
  /// different if there is additional type information to be displayed, such
  /// as type arguments.
  String? displayName;

  /// The member in the class corresponding to the member on which the
  /// hierarchy was requested. This field will be omitted if the hierarchy was
  /// not requested for a member or if the class does not have a corresponding
  /// member.
  Element? memberElement;

  /// The index of the item representing the superclass of this class. This
  /// field will be omitted if this item represents the class Object.
  int? superclass;

  /// The indexes of the items representing the interfaces implemented by this
  /// class. The list will be empty if there are no implemented interfaces.
  List<int> interfaces;

  /// The indexes of the items representing the mixins referenced by this
  /// class. The list will be empty if there are no classes mixed into this
  /// class.
  List<int> mixins;

  /// The indexes of the items representing the subtypes of this class. The
  /// list will be empty if there are no subtypes or if this item represents a
  /// supertype of the pivot type.
  List<int> subclasses;

  TypeHierarchyItem(
    this.classElement, {
    this.displayName,
    this.memberElement,
    this.superclass,
    List<int>? interfaces,
    List<int>? mixins,
    List<int>? subclasses,
  }) : interfaces = interfaces ?? <int>[],
       mixins = mixins ?? <int>[],
       subclasses = subclasses ?? <int>[];

  factory TypeHierarchyItem.fromJson(
    JsonDecoder jsonDecoder,
    String jsonPath,
    Object? json, {
    required ClientUriConverter? clientUriConverter,
  }) {
    json ??= {};
    if (json is Map) {
      Element classElement;
      if (json.containsKey('classElement')) {
        classElement = Element.fromJson(
          jsonDecoder,
          '$jsonPath.classElement',
          json['classElement'],
          clientUriConverter: clientUriConverter,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'classElement');
      }
      String? displayName;
      if (json.containsKey('displayName')) {
        displayName = jsonDecoder.decodeString(
          '$jsonPath.displayName',
          json['displayName'],
        );
      }
      Element? memberElement;
      if (json.containsKey('memberElement')) {
        memberElement = Element.fromJson(
          jsonDecoder,
          '$jsonPath.memberElement',
          json['memberElement'],
          clientUriConverter: clientUriConverter,
        );
      }
      int? superclass;
      if (json.containsKey('superclass')) {
        superclass = jsonDecoder.decodeInt(
          '$jsonPath.superclass',
          json['superclass'],
        );
      }
      List<int> interfaces;
      if (json.containsKey('interfaces')) {
        interfaces = jsonDecoder.decodeList(
          '$jsonPath.interfaces',
          json['interfaces'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'interfaces');
      }
      List<int> mixins;
      if (json.containsKey('mixins')) {
        mixins = jsonDecoder.decodeList(
          '$jsonPath.mixins',
          json['mixins'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'mixins');
      }
      List<int> subclasses;
      if (json.containsKey('subclasses')) {
        subclasses = jsonDecoder.decodeList(
          '$jsonPath.subclasses',
          json['subclasses'],
          jsonDecoder.decodeInt,
        );
      } else {
        throw jsonDecoder.mismatch(jsonPath, 'subclasses');
      }
      return TypeHierarchyItem(
        classElement,
        displayName: displayName,
        memberElement: memberElement,
        superclass: superclass,
        interfaces: interfaces,
        mixins: mixins,
        subclasses: subclasses,
      );
    } else {
      throw jsonDecoder.mismatch(jsonPath, 'TypeHierarchyItem', json);
    }
  }

  @override
  Map<String, Object> toJson({
    required ClientUriConverter? clientUriConverter,
  }) {
    var result = <String, Object>{};
    result['classElement'] = classElement.toJson(
      clientUriConverter: clientUriConverter,
    );
    var displayName = this.displayName;
    if (displayName != null) {
      result['displayName'] = displayName;
    }
    var memberElement = this.memberElement;
    if (memberElement != null) {
      result['memberElement'] = memberElement.toJson(
        clientUriConverter: clientUriConverter,
      );
    }
    var superclass = this.superclass;
    if (superclass != null) {
      result['superclass'] = superclass;
    }
    result['interfaces'] = interfaces;
    result['mixins'] = mixins;
    result['subclasses'] = subclasses;
    return result;
  }

  @override
  String toString() => json.encode(toJson(clientUriConverter: null));

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchyItem) {
      return classElement == other.classElement &&
          displayName == other.displayName &&
          memberElement == other.memberElement &&
          superclass == other.superclass &&
          listEqual(interfaces, other.interfaces, (int a, int b) => a == b) &&
          listEqual(mixins, other.mixins, (int a, int b) => a == b) &&
          listEqual(subclasses, other.subclasses, (int a, int b) => a == b);
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
    classElement,
    displayName,
    memberElement,
    superclass,
    Object.hashAll(interfaces),
    Object.hashAll(mixins),
    Object.hashAll(subclasses),
  );
}
