// Copyright (c) 2018, 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/lsp_spec/generate_all.dart".

import 'dart:core' hide deprecated;
import 'dart:core' as core show deprecated;
import 'dart:convert' show JsonEncoder;
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/json_parsing.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart';

const jsonEncoder = JsonEncoder.withIndent('    ');

/// A special text edit with an additional change annotation.
///
/// @since 3.16.0.
class AnnotatedTextEdit implements TextEdit, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    AnnotatedTextEdit.canParse,
    AnnotatedTextEdit.fromJson,
  );

  AnnotatedTextEdit({
    required this.annotationId,
    required this.newText,
    required this.range,
  });
  static AnnotatedTextEdit fromJson(Map<String, Object?> json) {
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String;
    final newTextJson = json['newText'];
    final newText = newTextJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return AnnotatedTextEdit(
      annotationId: annotationId,
      newText: newText,
      range: range,
    );
  }

  /// The actual identifier of the change annotation
  final String annotationId;

  /// The string to be inserted. For delete operations use an empty string.
  @override
  final String newText;

  /// The range of the text document to be manipulated. To insert text into a
  /// document create a range where start === end.
  @override
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['annotationId'] = annotationId;
    result['newText'] = newText;
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('annotationId');
      try {
        if (!obj.containsKey('annotationId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final annotationId = obj['annotationId'];
        if (annotationId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (annotationId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('newText');
      try {
        if (!obj.containsKey('newText')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newText = obj['newText'];
        if (newText == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type AnnotatedTextEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is AnnotatedTextEdit &&
        other.runtimeType == AnnotatedTextEdit &&
        annotationId == other.annotationId &&
        newText == other.newText &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        annotationId,
        newText,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters passed via a apply workspace edit request.
class ApplyWorkspaceEditParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ApplyWorkspaceEditParams.canParse,
    ApplyWorkspaceEditParams.fromJson,
  );

  ApplyWorkspaceEditParams({
    required this.edit,
    this.label,
  });
  static ApplyWorkspaceEditParams fromJson(Map<String, Object?> json) {
    final editJson = json['edit'];
    final edit = WorkspaceEdit.fromJson(editJson as Map<String, Object?>);
    final labelJson = json['label'];
    final label = labelJson as String?;
    return ApplyWorkspaceEditParams(
      edit: edit,
      label: label,
    );
  }

  /// The edits to apply.
  final WorkspaceEdit edit;

  /// An optional label of the workspace edit. This label is presented in the
  /// user interface for example on an undo stack to undo the workspace edit.
  final String? label;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('edit');
      try {
        if (!obj.containsKey('edit')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final edit = obj['edit'];
        if (edit == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!WorkspaceEdit.canParse(edit, reporter)) {
          reporter.reportError('must be of type WorkspaceEdit');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        final label = obj['label'];
        if (label != null && label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ApplyWorkspaceEditParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ApplyWorkspaceEditParams &&
        other.runtimeType == ApplyWorkspaceEditParams &&
        edit == other.edit &&
        label == other.label;
  }

  @override
  int get hashCode => Object.hash(
        edit,
        label,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result returned from the apply workspace edit request.
///
/// @since 3.17 renamed from ApplyWorkspaceEditResponse
class ApplyWorkspaceEditResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ApplyWorkspaceEditResult.canParse,
    ApplyWorkspaceEditResult.fromJson,
  );

  ApplyWorkspaceEditResult({
    required this.applied,
    this.failedChange,
    this.failureReason,
  });
  static ApplyWorkspaceEditResult fromJson(Map<String, Object?> json) {
    final appliedJson = json['applied'];
    final applied = appliedJson as bool;
    final failedChangeJson = json['failedChange'];
    final failedChange = failedChangeJson as int?;
    final failureReasonJson = json['failureReason'];
    final failureReason = failureReasonJson as String?;
    return ApplyWorkspaceEditResult(
      applied: applied,
      failedChange: failedChange,
      failureReason: failureReason,
    );
  }

  /// Indicates whether the edit was applied or not.
  final bool applied;

  /// Depending on the client's failure handling strategy `failedChange` might
  /// contain the index of the change that failed. This property is only
  /// available if the client signals a `failureHandlingStrategy` in its client
  /// capabilities.
  final int? failedChange;

  /// An optional textual description for why the edit was not applied. This may
  /// be used by the server for diagnostic logging or to provide a suitable
  /// error for a request that triggered the edit.
  final String? failureReason;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['applied'] = applied;
    if (failedChange != null) {
      result['failedChange'] = failedChange;
    }
    if (failureReason != null) {
      result['failureReason'] = failureReason;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('applied');
      try {
        if (!obj.containsKey('applied')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final applied = obj['applied'];
        if (applied == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (applied is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('failedChange');
      try {
        final failedChange = obj['failedChange'];
        if (failedChange != null && failedChange is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('failureReason');
      try {
        final failureReason = obj['failureReason'];
        if (failureReason != null && failureReason is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ApplyWorkspaceEditResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ApplyWorkspaceEditResult &&
        other.runtimeType == ApplyWorkspaceEditResult &&
        applied == other.applied &&
        failedChange == other.failedChange &&
        failureReason == other.failureReason;
  }

  @override
  int get hashCode => Object.hash(
        applied,
        failedChange,
        failureReason,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A base for all symbol information.
class BaseSymbolInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    BaseSymbolInformation.canParse,
    BaseSymbolInformation.fromJson,
  );

  BaseSymbolInformation({
    this.containerName,
    required this.kind,
    required this.name,
    this.tags,
  });
  static BaseSymbolInformation fromJson(Map<String, Object?> json) {
    if (SymbolInformation.canParse(json, nullLspJsonReporter)) {
      return SymbolInformation.fromJson(json);
    }
    if (WorkspaceSymbol.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbol.fromJson(json);
    }
    final containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final nameJson = json['name'];
    final name = nameJson as String;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return BaseSymbolInformation(
      containerName: containerName,
      kind: kind,
      name: name,
      tags: tags,
    );
  }

  /// The name of the symbol containing this symbol. This information is for
  /// user interface purposes (e.g. to render a qualifier in the user interface
  /// if necessary). It can't be used to re-infer a hierarchy for the document
  /// symbols.
  final String? containerName;

  /// The kind of this symbol.
  final SymbolKind kind;

  /// The name of this symbol.
  final String name;

  /// Tags for this symbol.
  ///
  /// @since 3.16.0
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (containerName != null) {
      result['containerName'] = containerName;
    }
    result['kind'] = kind.toJson();
    result['name'] = name;
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('containerName');
      try {
        final containerName = obj['containerName'];
        if (containerName != null && containerName is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type BaseSymbolInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is BaseSymbolInformation &&
        other.runtimeType == BaseSymbolInformation &&
        containerName == other.containerName &&
        kind == other.kind &&
        name == other.name &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        containerName,
        kind,
        name,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class CallHierarchyClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyClientCapabilities.canParse,
    CallHierarchyClientCapabilities.fromJson,
  );

  CallHierarchyClientCapabilities({
    this.dynamicRegistration,
  });
  static CallHierarchyClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return CallHierarchyClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CallHierarchyClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyClientCapabilities &&
        other.runtimeType == CallHierarchyClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents an incoming call, e.g. a caller of a method or constructor.
///
/// @since 3.16.0
class CallHierarchyIncomingCall implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyIncomingCall.canParse,
    CallHierarchyIncomingCall.fromJson,
  );

  CallHierarchyIncomingCall({
    required this.from,
    required this.fromRanges,
  });
  static CallHierarchyIncomingCall fromJson(Map<String, Object?> json) {
    final fromJson = json['from'];
    final from = CallHierarchyItem.fromJson(fromJson as Map<String, Object?>);
    final fromRangesJson = json['fromRanges'];
    final fromRanges = (fromRangesJson as List<Object?>)
        .map((item) => Range.fromJson(item as Map<String, Object?>))
        .toList();
    return CallHierarchyIncomingCall(
      from: from,
      fromRanges: fromRanges,
    );
  }

  /// The item that makes the call.
  final CallHierarchyItem from;

  /// The ranges at which the calls appear. This is relative to the caller
  /// denoted by `this.from`.
  final List<Range> fromRanges;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['from'] = from.toJson();
    result['fromRanges'] = fromRanges.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('from');
      try {
        if (!obj.containsKey('from')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final from = obj['from'];
        if (from == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!CallHierarchyItem.canParse(from, reporter)) {
          reporter.reportError('must be of type CallHierarchyItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('fromRanges');
      try {
        if (!obj.containsKey('fromRanges')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final fromRanges = obj['fromRanges'];
        if (fromRanges == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (fromRanges is! List<Object?> ||
            fromRanges.any((item) => !Range.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Range>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CallHierarchyIncomingCall');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyIncomingCall &&
        other.runtimeType == CallHierarchyIncomingCall &&
        from == other.from &&
        listEqual(fromRanges, other.fromRanges, (Range a, Range b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        from,
        lspHashCode(fromRanges),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameter of a `callHierarchy/incomingCalls` request.
///
/// @since 3.16.0
class CallHierarchyIncomingCallsParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyIncomingCallsParams.canParse,
    CallHierarchyIncomingCallsParams.fromJson,
  );

  CallHierarchyIncomingCallsParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static CallHierarchyIncomingCallsParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = CallHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return CallHierarchyIncomingCallsParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final CallHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['item'] = item.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('item');
      try {
        if (!obj.containsKey('item')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final item = obj['item'];
        if (item == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!CallHierarchyItem.canParse(item, reporter)) {
          reporter.reportError('must be of type CallHierarchyItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CallHierarchyIncomingCallsParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyIncomingCallsParams &&
        other.runtimeType == CallHierarchyIncomingCallsParams &&
        item == other.item &&
        partialResultToken == other.partialResultToken &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        item,
        partialResultToken,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents programming constructs like functions or constructors in the
/// context of call hierarchy.
///
/// @since 3.16.0
class CallHierarchyItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyItem.canParse,
    CallHierarchyItem.fromJson,
  );

  CallHierarchyItem({
    this.data,
    this.detail,
    required this.kind,
    required this.name,
    required this.range,
    required this.selectionRange,
    this.tags,
    required this.uri,
  });
  static CallHierarchyItem fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final nameJson = json['name'];
    final name = nameJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final selectionRangeJson = json['selectionRange'];
    final selectionRange =
        Range.fromJson(selectionRangeJson as Map<String, Object?>);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return CallHierarchyItem(
      data: data,
      detail: detail,
      kind: kind,
      name: name,
      range: range,
      selectionRange: selectionRange,
      tags: tags,
      uri: uri,
    );
  }

  /// A data entry field that is preserved between a call hierarchy prepare and
  /// incoming calls or outgoing calls requests.
  final Object? data;

  /// More detail for this item, e.g. the signature of a function.
  final String? detail;

  /// The kind of this item.
  final SymbolKind kind;

  /// The name of this item.
  final String name;

  /// The range enclosing this symbol not including leading/trailing whitespace
  /// but everything else, e.g. comments and code.
  final Range range;

  /// The range that should be selected and revealed when this symbol is being
  /// picked, e.g. the name of a function. Must be contained by the `range`.
  final Range selectionRange;

  /// Tags for this item.
  final List<SymbolTag>? tags;

  /// The resource identifier of this item.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    if (detail != null) {
      result['detail'] = detail;
    }
    result['kind'] = kind.toJson();
    result['name'] = name;
    result['range'] = range.toJson();
    result['selectionRange'] = selectionRange.toJson();
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('detail');
      try {
        final detail = obj['detail'];
        if (detail != null && detail is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRange');
      try {
        if (!obj.containsKey('selectionRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final selectionRange = obj['selectionRange'];
        if (selectionRange == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(selectionRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CallHierarchyItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyItem &&
        other.runtimeType == CallHierarchyItem &&
        data == other.data &&
        detail == other.detail &&
        kind == other.kind &&
        name == other.name &&
        range == other.range &&
        selectionRange == other.selectionRange &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        data,
        detail,
        kind,
        name,
        range,
        selectionRange,
        lspHashCode(tags),
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Call hierarchy options used during static registration.
///
/// @since 3.16.0
class CallHierarchyOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyOptions.canParse,
    CallHierarchyOptions.fromJson,
  );

  CallHierarchyOptions({
    this.workDoneProgress,
  });
  static CallHierarchyOptions fromJson(Map<String, Object?> json) {
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CallHierarchyOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CallHierarchyOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyOptions &&
        other.runtimeType == CallHierarchyOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents an outgoing call, e.g. calling a getter from a method or a method
/// from a constructor etc.
///
/// @since 3.16.0
class CallHierarchyOutgoingCall implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyOutgoingCall.canParse,
    CallHierarchyOutgoingCall.fromJson,
  );

  CallHierarchyOutgoingCall({
    required this.fromRanges,
    required this.to,
  });
  static CallHierarchyOutgoingCall fromJson(Map<String, Object?> json) {
    final fromRangesJson = json['fromRanges'];
    final fromRanges = (fromRangesJson as List<Object?>)
        .map((item) => Range.fromJson(item as Map<String, Object?>))
        .toList();
    final toJson = json['to'];
    final to = CallHierarchyItem.fromJson(toJson as Map<String, Object?>);
    return CallHierarchyOutgoingCall(
      fromRanges: fromRanges,
      to: to,
    );
  }

  /// The range at which this item is called. This is the range relative to the
  /// caller, e.g the item passed to `provideCallHierarchyOutgoingCalls` and not
  /// `this.to`.
  final List<Range> fromRanges;

  /// The item that is called.
  final CallHierarchyItem to;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['fromRanges'] = fromRanges.map((item) => item.toJson()).toList();
    result['to'] = to.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('fromRanges');
      try {
        if (!obj.containsKey('fromRanges')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final fromRanges = obj['fromRanges'];
        if (fromRanges == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (fromRanges is! List<Object?> ||
            fromRanges.any((item) => !Range.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Range>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('to');
      try {
        if (!obj.containsKey('to')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final to = obj['to'];
        if (to == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!CallHierarchyItem.canParse(to, reporter)) {
          reporter.reportError('must be of type CallHierarchyItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CallHierarchyOutgoingCall');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyOutgoingCall &&
        other.runtimeType == CallHierarchyOutgoingCall &&
        listEqual(fromRanges, other.fromRanges, (Range a, Range b) => a == b) &&
        to == other.to;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(fromRanges),
        to,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameter of a `callHierarchy/outgoingCalls` request.
///
/// @since 3.16.0
class CallHierarchyOutgoingCallsParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyOutgoingCallsParams.canParse,
    CallHierarchyOutgoingCallsParams.fromJson,
  );

  CallHierarchyOutgoingCallsParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static CallHierarchyOutgoingCallsParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = CallHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return CallHierarchyOutgoingCallsParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final CallHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['item'] = item.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('item');
      try {
        if (!obj.containsKey('item')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final item = obj['item'];
        if (item == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!CallHierarchyItem.canParse(item, reporter)) {
          reporter.reportError('must be of type CallHierarchyItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CallHierarchyOutgoingCallsParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyOutgoingCallsParams &&
        other.runtimeType == CallHierarchyOutgoingCallsParams &&
        item == other.item &&
        partialResultToken == other.partialResultToken &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        item,
        partialResultToken,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameter of a `textDocument/prepareCallHierarchy` request.
///
/// @since 3.16.0
class CallHierarchyPrepareParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyPrepareParams.canParse,
    CallHierarchyPrepareParams.fromJson,
  );

  CallHierarchyPrepareParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static CallHierarchyPrepareParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return CallHierarchyPrepareParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CallHierarchyPrepareParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyPrepareParams &&
        other.runtimeType == CallHierarchyPrepareParams &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Call hierarchy options used during static or dynamic registration.
///
/// @since 3.16.0
class CallHierarchyRegistrationOptions
    implements
        CallHierarchyOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyRegistrationOptions.canParse,
    CallHierarchyRegistrationOptions.fromJson,
  );

  CallHierarchyRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static CallHierarchyRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CallHierarchyRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CallHierarchyRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyRegistrationOptions &&
        other.runtimeType == CallHierarchyRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CancelParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CancelParams.canParse,
    CancelParams.fromJson,
  );

  CancelParams({
    required this.id,
  });
  static CancelParams fromJson(Map<String, Object?> json) {
    final idJson = json['id'];
    final id = idJson is int
        ? Either2<int, String>.t1(idJson)
        : (idJson is String
            ? Either2<int, String>.t2(idJson)
            : (throw '''$idJson was not one of (int, String)'''));
    return CancelParams(
      id: id,
    );
  }

  /// The request id to cancel.
  final Either2<int, String> id;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final id = obj['id'];
        if (id == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (id is! int && id is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CancelParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CancelParams &&
        other.runtimeType == CancelParams &&
        id == other.id;
  }

  @override
  int get hashCode => id.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Additional information that describes document changes.
///
/// @since 3.16.0
class ChangeAnnotation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ChangeAnnotation.canParse,
    ChangeAnnotation.fromJson,
  );

  ChangeAnnotation({
    this.description,
    required this.label,
    this.needsConfirmation,
  });
  static ChangeAnnotation fromJson(Map<String, Object?> json) {
    final descriptionJson = json['description'];
    final description = descriptionJson as String?;
    final labelJson = json['label'];
    final label = labelJson as String;
    final needsConfirmationJson = json['needsConfirmation'];
    final needsConfirmation = needsConfirmationJson as bool?;
    return ChangeAnnotation(
      description: description,
      label: label,
      needsConfirmation: needsConfirmation,
    );
  }

  /// A human-readable string which is rendered less prominent in the user
  /// interface.
  final String? description;

  /// A human-readable string describing the actual change. The string is
  /// rendered prominent in the user interface.
  final String label;

  /// A flag which indicates that user confirmation is needed before applying
  /// the change.
  final bool? needsConfirmation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (description != null) {
      result['description'] = description;
    }
    result['label'] = label;
    if (needsConfirmation != null) {
      result['needsConfirmation'] = needsConfirmation;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('description');
      try {
        final description = obj['description'];
        if (description != null && description is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final label = obj['label'];
        if (label == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('needsConfirmation');
      try {
        final needsConfirmation = obj['needsConfirmation'];
        if (needsConfirmation != null && needsConfirmation is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ChangeAnnotation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ChangeAnnotation &&
        other.runtimeType == ChangeAnnotation &&
        description == other.description &&
        label == other.label &&
        needsConfirmation == other.needsConfirmation;
  }

  @override
  int get hashCode => Object.hash(
        description,
        label,
        needsConfirmation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines the capabilities provided by the client.
class ClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ClientCapabilities.canParse,
    ClientCapabilities.fromJson,
  );

  ClientCapabilities({
    this.experimental,
    this.general,
    this.notebookDocument,
    this.textDocument,
    this.window,
    this.workspace,
  });
  static ClientCapabilities fromJson(Map<String, Object?> json) {
    final experimentalJson = json['experimental'];
    final experimental = experimentalJson;
    final generalJson = json['general'];
    final general = generalJson != null
        ? GeneralClientCapabilities.fromJson(
            generalJson as Map<String, Object?>)
        : null;
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument = notebookDocumentJson != null
        ? NotebookDocumentClientCapabilities.fromJson(
            notebookDocumentJson as Map<String, Object?>)
        : null;
    final textDocumentJson = json['textDocument'];
    final textDocument = textDocumentJson != null
        ? TextDocumentClientCapabilities.fromJson(
            textDocumentJson as Map<String, Object?>)
        : null;
    final windowJson = json['window'];
    final window = windowJson != null
        ? WindowClientCapabilities.fromJson(windowJson as Map<String, Object?>)
        : null;
    final workspaceJson = json['workspace'];
    final workspace = workspaceJson != null
        ? WorkspaceClientCapabilities.fromJson(
            workspaceJson as Map<String, Object?>)
        : null;
    return ClientCapabilities(
      experimental: experimental,
      general: general,
      notebookDocument: notebookDocument,
      textDocument: textDocument,
      window: window,
      workspace: workspace,
    );
  }

  /// Experimental client capabilities.
  final Object? experimental;

  /// General client capabilities.
  ///
  /// @since 3.16.0
  final GeneralClientCapabilities? general;

  /// Capabilities specific to the notebook document support.
  ///
  /// @since 3.17.0
  final NotebookDocumentClientCapabilities? notebookDocument;

  /// Text document specific client capabilities.
  final TextDocumentClientCapabilities? textDocument;

  /// Window specific client capabilities.
  final WindowClientCapabilities? window;

  /// Workspace specific client capabilities.
  final WorkspaceClientCapabilities? workspace;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (experimental != null) {
      result['experimental'] = experimental;
    }
    if (general != null) {
      result['general'] = general?.toJson();
    }
    if (notebookDocument != null) {
      result['notebookDocument'] = notebookDocument?.toJson();
    }
    if (textDocument != null) {
      result['textDocument'] = textDocument?.toJson();
    }
    if (window != null) {
      result['window'] = window?.toJson();
    }
    if (workspace != null) {
      result['workspace'] = workspace?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('general');
      try {
        final general = obj['general'];
        if (general != null &&
            !GeneralClientCapabilities.canParse(general, reporter)) {
          reporter.reportError('must be of type GeneralClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookDocument');
      try {
        final notebookDocument = obj['notebookDocument'];
        if (notebookDocument != null &&
            !NotebookDocumentClientCapabilities.canParse(
                notebookDocument, reporter)) {
          reporter.reportError(
              'must be of type NotebookDocumentClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        final textDocument = obj['textDocument'];
        if (textDocument != null &&
            !TextDocumentClientCapabilities.canParse(textDocument, reporter)) {
          reporter
              .reportError('must be of type TextDocumentClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('window');
      try {
        final window = obj['window'];
        if (window != null &&
            !WindowClientCapabilities.canParse(window, reporter)) {
          reporter.reportError('must be of type WindowClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspace');
      try {
        final workspace = obj['workspace'];
        if (workspace != null &&
            !WorkspaceClientCapabilities.canParse(workspace, reporter)) {
          reporter.reportError('must be of type WorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ClientCapabilities &&
        other.runtimeType == ClientCapabilities &&
        experimental == other.experimental &&
        general == other.general &&
        notebookDocument == other.notebookDocument &&
        textDocument == other.textDocument &&
        window == other.window &&
        workspace == other.workspace;
  }

  @override
  int get hashCode => Object.hash(
        experimental,
        general,
        notebookDocument,
        textDocument,
        window,
        workspace,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A code action represents a change that can be performed in code, e.g. to fix
/// a problem or to refactor code.
///
/// A CodeAction must set either `edit` and/or a `command`. If both are
/// supplied, the `edit` is applied first, then the `command` is executed.
class CodeAction implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeAction.canParse,
    CodeAction.fromJson,
  );

  CodeAction({
    this.command,
    this.data,
    this.diagnostics,
    this.disabled,
    this.edit,
    this.isPreferred,
    this.kind,
    required this.title,
  });
  static CodeAction fromJson(Map<String, Object?> json) {
    final commandJson = json['command'];
    final command = commandJson != null
        ? Command.fromJson(commandJson as Map<String, Object?>)
        : null;
    final dataJson = json['data'];
    final data = dataJson;
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = (diagnosticsJson as List<Object?>?)
        ?.map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final disabledJson = json['disabled'];
    final disabled = disabledJson != null
        ? CodeActionDisabled.fromJson(disabledJson as Map<String, Object?>)
        : null;
    final editJson = json['edit'];
    final edit = editJson != null
        ? WorkspaceEdit.fromJson(editJson as Map<String, Object?>)
        : null;
    final isPreferredJson = json['isPreferred'];
    final isPreferred = isPreferredJson as bool?;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? CodeActionKind.fromJson(kindJson as String) : null;
    final titleJson = json['title'];
    final title = titleJson as String;
    return CodeAction(
      command: command,
      data: data,
      diagnostics: diagnostics,
      disabled: disabled,
      edit: edit,
      isPreferred: isPreferred,
      kind: kind,
      title: title,
    );
  }

  /// A command this code action executes. If a code action provides an edit and
  /// a command, first the edit is executed and then the command.
  final Command? command;

  /// A data entry field that is preserved on a code action between a
  /// `textDocument/codeAction` and a `codeAction/resolve` request.
  ///
  /// @since 3.16.0
  final Object? data;

  /// The diagnostics that this code action resolves.
  final List<Diagnostic>? diagnostics;

  /// Marks that the code action cannot currently be applied.
  ///
  /// Clients should follow the following guidelines regarding disabled code
  /// actions:
  ///
  ///   - Disabled code actions are not shown in automatic
  /// [lightbulbs](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
  ///     code action menus.
  ///
  ///   - Disabled actions are shown as faded out in the code action menu when
  /// the user requests a more specific type
  ///     of code action, such as refactorings.
  ///
  ///   - If the user has a
  /// [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions)
  ///     that auto applies a code action and only disabled code actions are
  /// returned, the client should show the user an
  ///     error message with `reason` in the editor.
  ///
  /// @since 3.16.0
  final CodeActionDisabled? disabled;

  /// The workspace edit this code action performs.
  final WorkspaceEdit? edit;

  /// Marks this as a preferred action. Preferred actions are used by the `auto
  /// fix` command and can be targeted by keybindings.
  ///
  /// A quick fix should be marked preferred if it properly addresses the
  /// underlying error. A refactoring should be marked preferred if it is the
  /// most reasonable choice of actions to take.
  ///
  /// @since 3.15.0
  final bool? isPreferred;

  /// The kind of the code action.
  ///
  /// Used to filter code actions.
  final CodeActionKind? kind;

  /// A short, human-readable, title for this code action.
  final String title;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (command != null) {
      result['command'] = command?.toJson();
    }
    if (data != null) {
      result['data'] = data;
    }
    if (diagnostics != null) {
      result['diagnostics'] =
          diagnostics?.map((item) => item.toJson()).toList();
    }
    if (disabled != null) {
      result['disabled'] = disabled?.toJson();
    }
    if (edit != null) {
      result['edit'] = edit?.toJson();
    }
    if (isPreferred != null) {
      result['isPreferred'] = isPreferred;
    }
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['title'] = title;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('command');
      try {
        final command = obj['command'];
        if (command != null && !Command.canParse(command, reporter)) {
          reporter.reportError('must be of type Command');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('diagnostics');
      try {
        final diagnostics = obj['diagnostics'];
        if (diagnostics != null &&
            (diagnostics is! List<Object?> ||
                diagnostics
                    .any((item) => !Diagnostic.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('disabled');
      try {
        final disabled = obj['disabled'];
        if (disabled != null &&
            !CodeActionDisabled.canParse(disabled, reporter)) {
          reporter.reportError('must be of type CodeActionDisabled');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('edit');
      try {
        final edit = obj['edit'];
        if (edit != null && !WorkspaceEdit.canParse(edit, reporter)) {
          reporter.reportError('must be of type WorkspaceEdit');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('isPreferred');
      try {
        final isPreferred = obj['isPreferred'];
        if (isPreferred != null && isPreferred is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !CodeActionKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type CodeActionKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('title');
      try {
        if (!obj.containsKey('title')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final title = obj['title'];
        if (title == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (title is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeAction');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeAction &&
        other.runtimeType == CodeAction &&
        command == other.command &&
        data == other.data &&
        listEqual(diagnostics, other.diagnostics,
            (Diagnostic a, Diagnostic b) => a == b) &&
        disabled == other.disabled &&
        edit == other.edit &&
        isPreferred == other.isPreferred &&
        kind == other.kind &&
        title == other.title;
  }

  @override
  int get hashCode => Object.hash(
        command,
        data,
        lspHashCode(diagnostics),
        disabled,
        edit,
        isPreferred,
        kind,
        title,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The Client Capabilities of a CodeActionRequest.
class CodeActionClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionClientCapabilities.canParse,
    CodeActionClientCapabilities.fromJson,
  );

  CodeActionClientCapabilities({
    this.codeActionLiteralSupport,
    this.dataSupport,
    this.disabledSupport,
    this.dynamicRegistration,
    this.honorsChangeAnnotations,
    this.isPreferredSupport,
    this.resolveSupport,
  });
  static CodeActionClientCapabilities fromJson(Map<String, Object?> json) {
    final codeActionLiteralSupportJson = json['codeActionLiteralSupport'];
    final codeActionLiteralSupport = codeActionLiteralSupportJson != null
        ? CodeActionClientCapabilitiesCodeActionLiteralSupport.fromJson(
            codeActionLiteralSupportJson as Map<String, Object?>)
        : null;
    final dataSupportJson = json['dataSupport'];
    final dataSupport = dataSupportJson as bool?;
    final disabledSupportJson = json['disabledSupport'];
    final disabledSupport = disabledSupportJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final honorsChangeAnnotationsJson = json['honorsChangeAnnotations'];
    final honorsChangeAnnotations = honorsChangeAnnotationsJson as bool?;
    final isPreferredSupportJson = json['isPreferredSupport'];
    final isPreferredSupport = isPreferredSupportJson as bool?;
    final resolveSupportJson = json['resolveSupport'];
    final resolveSupport = resolveSupportJson != null
        ? CodeActionClientCapabilitiesResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    return CodeActionClientCapabilities(
      codeActionLiteralSupport: codeActionLiteralSupport,
      dataSupport: dataSupport,
      disabledSupport: disabledSupport,
      dynamicRegistration: dynamicRegistration,
      honorsChangeAnnotations: honorsChangeAnnotations,
      isPreferredSupport: isPreferredSupport,
      resolveSupport: resolveSupport,
    );
  }

  /// The client support code action literals of type `CodeAction` as a valid
  /// response of the `textDocument/codeAction` request. If the property is not
  /// set the request can only return `Command` literals.
  ///
  /// @since 3.8.0
  final CodeActionClientCapabilitiesCodeActionLiteralSupport?
      codeActionLiteralSupport;

  /// Whether code action supports the `data` property which is preserved
  /// between a `textDocument/codeAction` and a `codeAction/resolve` request.
  ///
  /// @since 3.16.0
  final bool? dataSupport;

  /// Whether code action supports the `disabled` property.
  ///
  /// @since 3.16.0
  final bool? disabledSupport;

  /// Whether code action supports dynamic registration.
  final bool? dynamicRegistration;

  /// Whether the client honors the change annotations in text edits and
  /// resource operations returned via the `CodeAction#edit` property by for
  /// example presenting the workspace edit in the user interface and asking for
  /// confirmation.
  ///
  /// @since 3.16.0
  final bool? honorsChangeAnnotations;

  /// Whether code action supports the `isPreferred` property.
  ///
  /// @since 3.15.0
  final bool? isPreferredSupport;

  /// Whether the client supports resolving additional code action properties
  /// via a separate `codeAction/resolve` request.
  ///
  /// @since 3.16.0
  final CodeActionClientCapabilitiesResolveSupport? resolveSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (codeActionLiteralSupport != null) {
      result['codeActionLiteralSupport'] = codeActionLiteralSupport?.toJson();
    }
    if (dataSupport != null) {
      result['dataSupport'] = dataSupport;
    }
    if (disabledSupport != null) {
      result['disabledSupport'] = disabledSupport;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (honorsChangeAnnotations != null) {
      result['honorsChangeAnnotations'] = honorsChangeAnnotations;
    }
    if (isPreferredSupport != null) {
      result['isPreferredSupport'] = isPreferredSupport;
    }
    if (resolveSupport != null) {
      result['resolveSupport'] = resolveSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('codeActionLiteralSupport');
      try {
        final codeActionLiteralSupport = obj['codeActionLiteralSupport'];
        if (codeActionLiteralSupport != null &&
            !CodeActionClientCapabilitiesCodeActionLiteralSupport.canParse(
                codeActionLiteralSupport, reporter)) {
          reporter.reportError(
              'must be of type CodeActionClientCapabilitiesCodeActionLiteralSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dataSupport');
      try {
        final dataSupport = obj['dataSupport'];
        if (dataSupport != null && dataSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('disabledSupport');
      try {
        final disabledSupport = obj['disabledSupport'];
        if (disabledSupport != null && disabledSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('honorsChangeAnnotations');
      try {
        final honorsChangeAnnotations = obj['honorsChangeAnnotations'];
        if (honorsChangeAnnotations != null &&
            honorsChangeAnnotations is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('isPreferredSupport');
      try {
        final isPreferredSupport = obj['isPreferredSupport'];
        if (isPreferredSupport != null && isPreferredSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveSupport');
      try {
        final resolveSupport = obj['resolveSupport'];
        if (resolveSupport != null &&
            !CodeActionClientCapabilitiesResolveSupport.canParse(
                resolveSupport, reporter)) {
          reporter.reportError(
              'must be of type CodeActionClientCapabilitiesResolveSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeActionClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionClientCapabilities &&
        other.runtimeType == CodeActionClientCapabilities &&
        codeActionLiteralSupport == other.codeActionLiteralSupport &&
        dataSupport == other.dataSupport &&
        disabledSupport == other.disabledSupport &&
        dynamicRegistration == other.dynamicRegistration &&
        honorsChangeAnnotations == other.honorsChangeAnnotations &&
        isPreferredSupport == other.isPreferredSupport &&
        resolveSupport == other.resolveSupport;
  }

  @override
  int get hashCode => Object.hash(
        codeActionLiteralSupport,
        dataSupport,
        disabledSupport,
        dynamicRegistration,
        honorsChangeAnnotations,
        isPreferredSupport,
        resolveSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CodeActionClientCapabilitiesCodeActionLiteralSupport
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionClientCapabilitiesCodeActionLiteralSupport.canParse,
    CodeActionClientCapabilitiesCodeActionLiteralSupport.fromJson,
  );

  CodeActionClientCapabilitiesCodeActionLiteralSupport({
    required this.codeActionKind,
  });
  static CodeActionClientCapabilitiesCodeActionLiteralSupport fromJson(
      Map<String, Object?> json) {
    final codeActionKindJson = json['codeActionKind'];
    final codeActionKind = CodeActionLiteralSupportCodeActionKind.fromJson(
        codeActionKindJson as Map<String, Object?>);
    return CodeActionClientCapabilitiesCodeActionLiteralSupport(
      codeActionKind: codeActionKind,
    );
  }

  /// The code action kind is support with the following value set.
  final CodeActionLiteralSupportCodeActionKind codeActionKind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['codeActionKind'] = codeActionKind.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('codeActionKind');
      try {
        if (!obj.containsKey('codeActionKind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final codeActionKind = obj['codeActionKind'];
        if (codeActionKind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!CodeActionLiteralSupportCodeActionKind.canParse(
            codeActionKind, reporter)) {
          reporter.reportError(
              'must be of type CodeActionLiteralSupportCodeActionKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type CodeActionClientCapabilitiesCodeActionLiteralSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionClientCapabilitiesCodeActionLiteralSupport &&
        other.runtimeType ==
            CodeActionClientCapabilitiesCodeActionLiteralSupport &&
        codeActionKind == other.codeActionKind;
  }

  @override
  int get hashCode => codeActionKind.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CodeActionClientCapabilitiesResolveSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionClientCapabilitiesResolveSupport.canParse,
    CodeActionClientCapabilitiesResolveSupport.fromJson,
  );

  CodeActionClientCapabilitiesResolveSupport({
    required this.properties,
  });
  static CodeActionClientCapabilitiesResolveSupport fromJson(
      Map<String, Object?> json) {
    final propertiesJson = json['properties'];
    final properties = (propertiesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return CodeActionClientCapabilitiesResolveSupport(
      properties: properties,
    );
  }

  /// The properties that a client can resolve lazily.
  final List<String> properties;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('properties');
      try {
        if (!obj.containsKey('properties')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final properties = obj['properties'];
        if (properties == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (properties is! List<Object?> ||
            properties.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type CodeActionClientCapabilitiesResolveSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionClientCapabilitiesResolveSupport &&
        other.runtimeType == CodeActionClientCapabilitiesResolveSupport &&
        listEqual(properties, other.properties, (String a, String b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(properties);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Contains additional diagnostic information about the context in which a code
/// action is run.
class CodeActionContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionContext.canParse,
    CodeActionContext.fromJson,
  );

  CodeActionContext({
    required this.diagnostics,
    this.only,
    this.triggerKind,
  });
  static CodeActionContext fromJson(Map<String, Object?> json) {
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = (diagnosticsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final onlyJson = json['only'];
    final only = (onlyJson as List<Object?>?)
        ?.map((item) => CodeActionKind.fromJson(item as String))
        .toList();
    final triggerKindJson = json['triggerKind'];
    final triggerKind = triggerKindJson != null
        ? CodeActionTriggerKind.fromJson(triggerKindJson as int)
        : null;
    return CodeActionContext(
      diagnostics: diagnostics,
      only: only,
      triggerKind: triggerKind,
    );
  }

  /// An array of diagnostics known on the client side overlapping the range
  /// provided to the `textDocument/codeAction` request. They are provided so
  /// that the server knows which errors are currently presented to the user for
  /// the given range. There is no guarantee that these accurately reflect the
  /// error state of the resource. The primary parameter to compute code actions
  /// is the provided range.
  final List<Diagnostic> diagnostics;

  /// Requested kind of actions to return.
  ///
  /// Actions not of this kind are filtered out by the client before being
  /// shown. So servers can omit computing them.
  final List<CodeActionKind>? only;

  /// The reason why code actions were requested.
  ///
  /// @since 3.17.0
  final CodeActionTriggerKind? triggerKind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['diagnostics'] = diagnostics.map((item) => item.toJson()).toList();
    if (only != null) {
      result['only'] = only?.map((item) => item.toJson()).toList();
    }
    if (triggerKind != null) {
      result['triggerKind'] = triggerKind?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('diagnostics');
      try {
        if (!obj.containsKey('diagnostics')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final diagnostics = obj['diagnostics'];
        if (diagnostics == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (diagnostics is! List<Object?> ||
            diagnostics.any((item) => !Diagnostic.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('only');
      try {
        final only = obj['only'];
        if (only != null &&
            (only is! List<Object?> ||
                only.any((item) => !CodeActionKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<CodeActionKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerKind');
      try {
        final triggerKind = obj['triggerKind'];
        if (triggerKind != null &&
            !CodeActionTriggerKind.canParse(triggerKind, reporter)) {
          reporter.reportError('must be of type CodeActionTriggerKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeActionContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionContext &&
        other.runtimeType == CodeActionContext &&
        listEqual(diagnostics, other.diagnostics,
            (Diagnostic a, Diagnostic b) => a == b) &&
        listEqual(
            only, other.only, (CodeActionKind a, CodeActionKind b) => a == b) &&
        triggerKind == other.triggerKind;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(diagnostics),
        lspHashCode(only),
        triggerKind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CodeActionDisabled implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionDisabled.canParse,
    CodeActionDisabled.fromJson,
  );

  CodeActionDisabled({
    required this.reason,
  });
  static CodeActionDisabled fromJson(Map<String, Object?> json) {
    final reasonJson = json['reason'];
    final reason = reasonJson as String;
    return CodeActionDisabled(
      reason: reason,
    );
  }

  /// Human readable description of why the code action is currently disabled.
  ///
  /// This is displayed in the code actions UI.
  final String reason;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('reason');
      try {
        if (!obj.containsKey('reason')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final reason = obj['reason'];
        if (reason == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (reason is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeActionDisabled');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionDisabled &&
        other.runtimeType == CodeActionDisabled &&
        reason == other.reason;
  }

  @override
  int get hashCode => reason.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A set of predefined code action kinds
class CodeActionKind implements ToJsonable {
  const CodeActionKind(this._value);
  const CodeActionKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// Empty kind.
  static const Empty = CodeActionKind('');

  /// Base kind for quickfix actions: 'quickfix'
  static const QuickFix = CodeActionKind('quickfix');

  /// Base kind for refactoring actions: 'refactor'
  static const Refactor = CodeActionKind('refactor');

  /// Base kind for refactoring extraction actions: 'refactor.extract'
  ///
  /// Example extract actions:
  ///
  /// - Extract method
  /// - Extract function
  /// - Extract variable
  /// - Extract interface from class
  /// - ...
  static const RefactorExtract = CodeActionKind('refactor.extract');

  /// Base kind for refactoring inline actions: 'refactor.inline'
  ///
  /// Example inline actions:
  ///
  /// - Inline function
  /// - Inline variable
  /// - Inline constant
  /// - ...
  static const RefactorInline = CodeActionKind('refactor.inline');

  /// Base kind for refactoring rewrite actions: 'refactor.rewrite'
  ///
  /// Example rewrite actions:
  ///
  /// - Convert JavaScript function to class
  /// - Add or remove parameter
  /// - Encapsulate field
  /// - Make method static
  /// - Move method to base class
  /// - ...
  static const RefactorRewrite = CodeActionKind('refactor.rewrite');

  /// Base kind for source actions: `source`
  ///
  /// Source code actions apply to the entire file.
  static const Source = CodeActionKind('source');

  /// Base kind for auto-fix source actions: `source.fixAll`.
  ///
  /// Fix all actions automatically fix errors that have a clear fix that do not
  /// require user input. They should not suppress errors or perform unsafe
  /// fixes such as generating new types or classes.
  ///
  /// @since 3.15.0
  static const SourceFixAll = CodeActionKind('source.fixAll');

  /// Base kind for an organize imports source action: `source.organizeImports`
  static const SourceOrganizeImports = CodeActionKind('source.organizeImports');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is CodeActionKind && other._value == _value;
}

class CodeActionLiteralSupportCodeActionKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionLiteralSupportCodeActionKind.canParse,
    CodeActionLiteralSupportCodeActionKind.fromJson,
  );

  CodeActionLiteralSupportCodeActionKind({
    required this.valueSet,
  });
  static CodeActionLiteralSupportCodeActionKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => CodeActionKind.fromJson(item as String))
        .toList();
    return CodeActionLiteralSupportCodeActionKind(
      valueSet: valueSet,
    );
  }

  /// The code action kind values the client supports. When this property exists
  /// the client also guarantees that it will handle values outside its set
  /// gracefully and falls back to a default value when unknown.
  final List<CodeActionKind> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final valueSet = obj['valueSet'];
        if (valueSet == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (valueSet is! List<Object?> ||
            valueSet.any((item) => !CodeActionKind.canParse(item, reporter))) {
          reporter.reportError('must be of type List<CodeActionKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type CodeActionLiteralSupportCodeActionKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionLiteralSupportCodeActionKind &&
        other.runtimeType == CodeActionLiteralSupportCodeActionKind &&
        listEqual(valueSet, other.valueSet,
            (CodeActionKind a, CodeActionKind b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a CodeActionRequest.
class CodeActionOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionOptions.canParse,
    CodeActionOptions.fromJson,
  );

  CodeActionOptions({
    this.codeActionKinds,
    this.resolveProvider,
    this.workDoneProgress,
  });
  static CodeActionOptions fromJson(Map<String, Object?> json) {
    if (CodeActionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionRegistrationOptions.fromJson(json);
    }
    final codeActionKindsJson = json['codeActionKinds'];
    final codeActionKinds = (codeActionKindsJson as List<Object?>?)
        ?.map((item) => CodeActionKind.fromJson(item as String))
        .toList();
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CodeActionOptions(
      codeActionKinds: codeActionKinds,
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// CodeActionKinds that this server may return.
  ///
  /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or
  /// the server may list out every specific kind they provide.
  final List<CodeActionKind>? codeActionKinds;

  /// The server provides support to resolve additional information for a code
  /// action.
  ///
  /// @since 3.16.0
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (codeActionKinds != null) {
      result['codeActionKinds'] =
          codeActionKinds?.map((item) => item.toJson()).toList();
    }
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('codeActionKinds');
      try {
        final codeActionKinds = obj['codeActionKinds'];
        if (codeActionKinds != null &&
            (codeActionKinds is! List<Object?> ||
                codeActionKinds
                    .any((item) => !CodeActionKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<CodeActionKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeActionOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionOptions &&
        other.runtimeType == CodeActionOptions &&
        listEqual(codeActionKinds, other.codeActionKinds,
            (CodeActionKind a, CodeActionKind b) => a == b) &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(codeActionKinds),
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a CodeActionRequest.
class CodeActionParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionParams.canParse,
    CodeActionParams.fromJson,
  );

  CodeActionParams({
    required this.context,
    this.partialResultToken,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static CodeActionParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context =
        CodeActionContext.fromJson(contextJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return CodeActionParams(
      context: context,
      partialResultToken: partialResultToken,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// Context carrying additional information.
  final CodeActionContext context;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The range for which the command was invoked.
  final Range range;

  /// The document in which the command was invoked.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['context'] = context.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('context');
      try {
        if (!obj.containsKey('context')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final context = obj['context'];
        if (context == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!CodeActionContext.canParse(context, reporter)) {
          reporter.reportError('must be of type CodeActionContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeActionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionParams &&
        other.runtimeType == CodeActionParams &&
        context == other.context &&
        partialResultToken == other.partialResultToken &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        context,
        partialResultToken,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a CodeActionRequest.
class CodeActionRegistrationOptions
    implements CodeActionOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionRegistrationOptions.canParse,
    CodeActionRegistrationOptions.fromJson,
  );

  CodeActionRegistrationOptions({
    this.codeActionKinds,
    this.documentSelector,
    this.resolveProvider,
    this.workDoneProgress,
  });
  static CodeActionRegistrationOptions fromJson(Map<String, Object?> json) {
    final codeActionKindsJson = json['codeActionKinds'];
    final codeActionKinds = (codeActionKindsJson as List<Object?>?)
        ?.map((item) => CodeActionKind.fromJson(item as String))
        .toList();
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CodeActionRegistrationOptions(
      codeActionKinds: codeActionKinds,
      documentSelector: documentSelector,
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// CodeActionKinds that this server may return.
  ///
  /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or
  /// the server may list out every specific kind they provide.
  @override
  final List<CodeActionKind>? codeActionKinds;

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The server provides support to resolve additional information for a code
  /// action.
  ///
  /// @since 3.16.0
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (codeActionKinds != null) {
      result['codeActionKinds'] =
          codeActionKinds?.map((item) => item.toJson()).toList();
    }
    result['documentSelector'] = documentSelector;
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('codeActionKinds');
      try {
        final codeActionKinds = obj['codeActionKinds'];
        if (codeActionKinds != null &&
            (codeActionKinds is! List<Object?> ||
                codeActionKinds
                    .any((item) => !CodeActionKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<CodeActionKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeActionRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionRegistrationOptions &&
        other.runtimeType == CodeActionRegistrationOptions &&
        listEqual(codeActionKinds, other.codeActionKinds,
            (CodeActionKind a, CodeActionKind b) => a == b) &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(codeActionKinds),
        lspHashCode(documentSelector),
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The reason why code actions were requested.
///
/// @since 3.17.0
class CodeActionTriggerKind implements ToJsonable {
  const CodeActionTriggerKind(this._value);
  const CodeActionTriggerKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Code actions were requested automatically.
  ///
  /// This typically happens when current selection in a file changes, but can
  /// also be triggered when file content changes.
  static const Automatic = CodeActionTriggerKind(2);

  /// Code actions were explicitly requested by the user or by an extension.
  static const Invoked = CodeActionTriggerKind(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is CodeActionTriggerKind && other._value == _value;
}

/// Structure to capture a description for an error code.
///
/// @since 3.16.0
class CodeDescription implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeDescription.canParse,
    CodeDescription.fromJson,
  );

  CodeDescription({
    required this.href,
  });
  static CodeDescription fromJson(Map<String, Object?> json) {
    final hrefJson = json['href'];
    final href = hrefJson as String;
    return CodeDescription(
      href: href,
    );
  }

  /// An URI to open with more information about the diagnostic error.
  final String href;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('href');
      try {
        if (!obj.containsKey('href')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final href = obj['href'];
        if (href == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (href is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeDescription');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeDescription &&
        other.runtimeType == CodeDescription &&
        href == other.href;
  }

  @override
  int get hashCode => href.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A code lens represents a command that should be shown along with source
/// text, like the number of references, a way to run tests, etc.
///
/// A code lens is _unresolved_ when no command is associated to it. For
/// performance reasons the creation of a code lens and resolving should be done
/// in two stages.
class CodeLens implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLens.canParse,
    CodeLens.fromJson,
  );

  CodeLens({
    this.command,
    this.data,
    required this.range,
  });
  static CodeLens fromJson(Map<String, Object?> json) {
    final commandJson = json['command'];
    final command = commandJson != null
        ? Command.fromJson(commandJson as Map<String, Object?>)
        : null;
    final dataJson = json['data'];
    final data = dataJson;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return CodeLens(
      command: command,
      data: data,
      range: range,
    );
  }

  /// The command this code lens represents.
  final Command? command;

  /// A data entry field that is preserved on a code lens item between a
  /// CodeLensRequest and a CodeLensResolveRequest
  final Object? data;

  /// The range in which this code lens is valid. Should only span a single
  /// line.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (command != null) {
      result['command'] = command?.toJson();
    }
    if (data != null) {
      result['data'] = data;
    }
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('command');
      try {
        final command = obj['command'];
        if (command != null && !Command.canParse(command, reporter)) {
          reporter.reportError('must be of type Command');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeLens');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeLens &&
        other.runtimeType == CodeLens &&
        command == other.command &&
        data == other.data &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        command,
        data,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The client capabilities  of a CodeLensRequest.
class CodeLensClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensClientCapabilities.canParse,
    CodeLensClientCapabilities.fromJson,
  );

  CodeLensClientCapabilities({
    this.dynamicRegistration,
  });
  static CodeLensClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return CodeLensClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether code lens supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeLensClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeLensClientCapabilities &&
        other.runtimeType == CodeLensClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Code Lens provider options of a CodeLensRequest.
class CodeLensOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensOptions.canParse,
    CodeLensOptions.fromJson,
  );

  CodeLensOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static CodeLensOptions fromJson(Map<String, Object?> json) {
    if (CodeLensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensRegistrationOptions.fromJson(json);
    }
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CodeLensOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Code lens has a resolve provider as well.
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeLensOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeLensOptions &&
        other.runtimeType == CodeLensOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a CodeLensRequest.
class CodeLensParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensParams.canParse,
    CodeLensParams.fromJson,
  );

  CodeLensParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static CodeLensParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return CodeLensParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The document to request code lens for.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeLensParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeLensParams &&
        other.runtimeType == CodeLensParams &&
        partialResultToken == other.partialResultToken &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a CodeLensRequest.
class CodeLensRegistrationOptions
    implements CodeLensOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensRegistrationOptions.canParse,
    CodeLensRegistrationOptions.fromJson,
  );

  CodeLensRegistrationOptions({
    this.documentSelector,
    this.resolveProvider,
    this.workDoneProgress,
  });
  static CodeLensRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CodeLensRegistrationOptions(
      documentSelector: documentSelector,
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// Code lens has a resolve provider as well.
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeLensRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeLensRegistrationOptions &&
        other.runtimeType == CodeLensRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class CodeLensWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensWorkspaceClientCapabilities.canParse,
    CodeLensWorkspaceClientCapabilities.fromJson,
  );

  CodeLensWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static CodeLensWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return CodeLensWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// code lenses currently shown. It should be used with absolute care and is
  /// useful for situation where a server for example detect a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('refreshSupport');
      try {
        final refreshSupport = obj['refreshSupport'];
        if (refreshSupport != null && refreshSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type CodeLensWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeLensWorkspaceClientCapabilities &&
        other.runtimeType == CodeLensWorkspaceClientCapabilities &&
        refreshSupport == other.refreshSupport;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a color in RGBA space.
class Color implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Color.canParse,
    Color.fromJson,
  );

  Color({
    required this.alpha,
    required this.blue,
    required this.green,
    required this.red,
  });
  static Color fromJson(Map<String, Object?> json) {
    final alphaJson = json['alpha'];
    final alpha = alphaJson as num;
    final blueJson = json['blue'];
    final blue = blueJson as num;
    final greenJson = json['green'];
    final green = greenJson as num;
    final redJson = json['red'];
    final red = redJson as num;
    return Color(
      alpha: alpha,
      blue: blue,
      green: green,
      red: red,
    );
  }

  /// The alpha component of this color in the range [0-1].
  final num alpha;

  /// The blue component of this color in the range [0-1].
  final num blue;

  /// The green component of this color in the range [0-1].
  final num green;

  /// The red component of this color in the range [0-1].
  final num red;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['alpha'] = alpha;
    result['blue'] = blue;
    result['green'] = green;
    result['red'] = red;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('alpha');
      try {
        if (!obj.containsKey('alpha')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final alpha = obj['alpha'];
        if (alpha == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (alpha is! num) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('blue');
      try {
        if (!obj.containsKey('blue')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final blue = obj['blue'];
        if (blue == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (blue is! num) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('green');
      try {
        if (!obj.containsKey('green')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final green = obj['green'];
        if (green == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (green is! num) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('red');
      try {
        if (!obj.containsKey('red')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final red = obj['red'];
        if (red == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (red is! num) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Color');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Color &&
        other.runtimeType == Color &&
        alpha == other.alpha &&
        blue == other.blue &&
        green == other.green &&
        red == other.red;
  }

  @override
  int get hashCode => Object.hash(
        alpha,
        blue,
        green,
        red,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a color range from a document.
class ColorInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ColorInformation.canParse,
    ColorInformation.fromJson,
  );

  ColorInformation({
    required this.color,
    required this.range,
  });
  static ColorInformation fromJson(Map<String, Object?> json) {
    final colorJson = json['color'];
    final color = Color.fromJson(colorJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return ColorInformation(
      color: color,
      range: range,
    );
  }

  /// The actual color value for this color range.
  final Color color;

  /// The range in the document where this color appears.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['color'] = color.toJson();
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('color');
      try {
        if (!obj.containsKey('color')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final color = obj['color'];
        if (color == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Color.canParse(color, reporter)) {
          reporter.reportError('must be of type Color');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ColorInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ColorInformation &&
        other.runtimeType == ColorInformation &&
        color == other.color &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        color,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ColorPresentation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ColorPresentation.canParse,
    ColorPresentation.fromJson,
  );

  ColorPresentation({
    this.additionalTextEdits,
    required this.label,
    this.textEdit,
  });
  static ColorPresentation fromJson(Map<String, Object?> json) {
    final additionalTextEditsJson = json['additionalTextEdits'];
    final additionalTextEdits = (additionalTextEditsJson as List<Object?>?)
        ?.map((item) => TextEdit.fromJson(item as Map<String, Object?>))
        .toList();
    final labelJson = json['label'];
    final label = labelJson as String;
    final textEditJson = json['textEdit'];
    final textEdit = textEditJson != null
        ? TextEdit.fromJson(textEditJson as Map<String, Object?>)
        : null;
    return ColorPresentation(
      additionalTextEdits: additionalTextEdits,
      label: label,
      textEdit: textEdit,
    );
  }

  /// An optional array of additional text edits that are applied when selecting
  /// this color presentation. Edits must not overlap with the main edit nor
  /// with themselves.
  final List<TextEdit>? additionalTextEdits;

  /// The label of this color presentation. It will be shown on the color picker
  /// header. By default this is also the text that is inserted when selecting
  /// this color presentation.
  final String label;

  /// An edit which is applied to a document when selecting this presentation
  /// for the color.  When `falsy` the label is used.
  final TextEdit? textEdit;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (additionalTextEdits != null) {
      result['additionalTextEdits'] =
          additionalTextEdits?.map((item) => item.toJson()).toList();
    }
    result['label'] = label;
    if (textEdit != null) {
      result['textEdit'] = textEdit?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('additionalTextEdits');
      try {
        final additionalTextEdits = obj['additionalTextEdits'];
        if (additionalTextEdits != null &&
            (additionalTextEdits is! List<Object?> ||
                additionalTextEdits
                    .any((item) => !TextEdit.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<TextEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final label = obj['label'];
        if (label == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textEdit');
      try {
        final textEdit = obj['textEdit'];
        if (textEdit != null && !TextEdit.canParse(textEdit, reporter)) {
          reporter.reportError('must be of type TextEdit');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ColorPresentation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ColorPresentation &&
        other.runtimeType == ColorPresentation &&
        listEqual(additionalTextEdits, other.additionalTextEdits,
            (TextEdit a, TextEdit b) => a == b) &&
        label == other.label &&
        textEdit == other.textEdit;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(additionalTextEdits),
        label,
        textEdit,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a ColorPresentationRequest.
class ColorPresentationParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ColorPresentationParams.canParse,
    ColorPresentationParams.fromJson,
  );

  ColorPresentationParams({
    required this.color,
    this.partialResultToken,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static ColorPresentationParams fromJson(Map<String, Object?> json) {
    final colorJson = json['color'];
    final color = Color.fromJson(colorJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return ColorPresentationParams(
      color: color,
      partialResultToken: partialResultToken,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The color to request presentations for.
  final Color color;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The range where the color would be inserted. Serves as a context.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['color'] = color.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('color');
      try {
        if (!obj.containsKey('color')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final color = obj['color'];
        if (color == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Color.canParse(color, reporter)) {
          reporter.reportError('must be of type Color');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ColorPresentationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ColorPresentationParams &&
        other.runtimeType == ColorPresentationParams &&
        color == other.color &&
        partialResultToken == other.partialResultToken &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        color,
        partialResultToken,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a reference to a command. Provides a title which will be used to
/// represent a command in the UI and, optionally,
/// an array of arguments which will be passed to the command handler function
/// when invoked.
class Command implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Command.canParse,
    Command.fromJson,
  );

  Command({
    this.arguments,
    required this.command,
    required this.title,
  });
  static Command fromJson(Map<String, Object?> json) {
    final argumentsJson = json['arguments'];
    final arguments =
        (argumentsJson as List<Object?>?)?.map((item) => item).toList();
    final commandJson = json['command'];
    final command = commandJson as String;
    final titleJson = json['title'];
    final title = titleJson as String;
    return Command(
      arguments: arguments,
      command: command,
      title: title,
    );
  }

  /// Arguments that the command handler should be invoked with.
  final List<Object?>? arguments;

  /// The identifier of the actual command handler.
  final String command;

  /// Title of the command, like `save`.
  final String title;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (arguments != null) {
      result['arguments'] = arguments;
    }
    result['command'] = command;
    result['title'] = title;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('arguments');
      try {
        final arguments = obj['arguments'];
        if (arguments != null &&
            (arguments is! List<Object?> || arguments.any((item) => false))) {
          reporter.reportError('must be of type List<Object?>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('command');
      try {
        if (!obj.containsKey('command')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final command = obj['command'];
        if (command == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (command is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('title');
      try {
        if (!obj.containsKey('title')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final title = obj['title'];
        if (title == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (title is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Command');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Command &&
        other.runtimeType == Command &&
        listEqual(
            arguments, other.arguments, (Object? a, Object? b) => a == b) &&
        command == other.command &&
        title == other.title;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(arguments),
        command,
        title,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Completion client capabilities
class CompletionClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionClientCapabilities.canParse,
    CompletionClientCapabilities.fromJson,
  );

  CompletionClientCapabilities({
    this.completionItem,
    this.completionItemKind,
    this.completionList,
    this.contextSupport,
    this.dynamicRegistration,
    this.insertTextMode,
  });
  static CompletionClientCapabilities fromJson(Map<String, Object?> json) {
    final completionItemJson = json['completionItem'];
    final completionItem = completionItemJson != null
        ? CompletionClientCapabilitiesCompletionItem.fromJson(
            completionItemJson as Map<String, Object?>)
        : null;
    final completionItemKindJson = json['completionItemKind'];
    final completionItemKind = completionItemKindJson != null
        ? CompletionClientCapabilitiesCompletionItemKind.fromJson(
            completionItemKindJson as Map<String, Object?>)
        : null;
    final completionListJson = json['completionList'];
    final completionList = completionListJson != null
        ? CompletionClientCapabilitiesCompletionList.fromJson(
            completionListJson as Map<String, Object?>)
        : null;
    final contextSupportJson = json['contextSupport'];
    final contextSupport = contextSupportJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final insertTextModeJson = json['insertTextMode'];
    final insertTextMode = insertTextModeJson != null
        ? InsertTextMode.fromJson(insertTextModeJson as int)
        : null;
    return CompletionClientCapabilities(
      completionItem: completionItem,
      completionItemKind: completionItemKind,
      completionList: completionList,
      contextSupport: contextSupport,
      dynamicRegistration: dynamicRegistration,
      insertTextMode: insertTextMode,
    );
  }

  /// The client supports the following `CompletionItem` specific capabilities.
  final CompletionClientCapabilitiesCompletionItem? completionItem;
  final CompletionClientCapabilitiesCompletionItemKind? completionItemKind;

  /// The client supports the following `CompletionList` specific capabilities.
  ///
  /// @since 3.17.0
  final CompletionClientCapabilitiesCompletionList? completionList;

  /// The client supports to send additional context information for a
  /// `textDocument/completion` request.
  final bool? contextSupport;

  /// Whether completion supports dynamic registration.
  final bool? dynamicRegistration;

  /// Defines how the client handles whitespace and indentation when accepting a
  /// completion item that uses multi line text in either `insertText` or
  /// `textEdit`.
  ///
  /// @since 3.17.0
  final InsertTextMode? insertTextMode;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (completionItem != null) {
      result['completionItem'] = completionItem?.toJson();
    }
    if (completionItemKind != null) {
      result['completionItemKind'] = completionItemKind?.toJson();
    }
    if (completionList != null) {
      result['completionList'] = completionList?.toJson();
    }
    if (contextSupport != null) {
      result['contextSupport'] = contextSupport;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (insertTextMode != null) {
      result['insertTextMode'] = insertTextMode?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('completionItem');
      try {
        final completionItem = obj['completionItem'];
        if (completionItem != null &&
            !CompletionClientCapabilitiesCompletionItem.canParse(
                completionItem, reporter)) {
          reporter.reportError(
              'must be of type CompletionClientCapabilitiesCompletionItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completionItemKind');
      try {
        final completionItemKind = obj['completionItemKind'];
        if (completionItemKind != null &&
            !CompletionClientCapabilitiesCompletionItemKind.canParse(
                completionItemKind, reporter)) {
          reporter.reportError(
              'must be of type CompletionClientCapabilitiesCompletionItemKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completionList');
      try {
        final completionList = obj['completionList'];
        if (completionList != null &&
            !CompletionClientCapabilitiesCompletionList.canParse(
                completionList, reporter)) {
          reporter.reportError(
              'must be of type CompletionClientCapabilitiesCompletionList');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('contextSupport');
      try {
        final contextSupport = obj['contextSupport'];
        if (contextSupport != null && contextSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertTextMode');
      try {
        final insertTextMode = obj['insertTextMode'];
        if (insertTextMode != null &&
            !InsertTextMode.canParse(insertTextMode, reporter)) {
          reporter.reportError('must be of type InsertTextMode');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionClientCapabilities &&
        other.runtimeType == CompletionClientCapabilities &&
        completionItem == other.completionItem &&
        completionItemKind == other.completionItemKind &&
        completionList == other.completionList &&
        contextSupport == other.contextSupport &&
        dynamicRegistration == other.dynamicRegistration &&
        insertTextMode == other.insertTextMode;
  }

  @override
  int get hashCode => Object.hash(
        completionItem,
        completionItemKind,
        completionList,
        contextSupport,
        dynamicRegistration,
        insertTextMode,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CompletionClientCapabilitiesCompletionItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionClientCapabilitiesCompletionItem.canParse,
    CompletionClientCapabilitiesCompletionItem.fromJson,
  );

  CompletionClientCapabilitiesCompletionItem({
    this.commitCharactersSupport,
    this.deprecatedSupport,
    this.documentationFormat,
    this.insertReplaceSupport,
    this.insertTextModeSupport,
    this.labelDetailsSupport,
    this.preselectSupport,
    this.resolveSupport,
    this.snippetSupport,
    this.tagSupport,
  });
  static CompletionClientCapabilitiesCompletionItem fromJson(
      Map<String, Object?> json) {
    final commitCharactersSupportJson = json['commitCharactersSupport'];
    final commitCharactersSupport = commitCharactersSupportJson as bool?;
    final deprecatedSupportJson = json['deprecatedSupport'];
    final deprecatedSupport = deprecatedSupportJson as bool?;
    final documentationFormatJson = json['documentationFormat'];
    final documentationFormat = (documentationFormatJson as List<Object?>?)
        ?.map((item) => MarkupKind.fromJson(item as String))
        .toList();
    final insertReplaceSupportJson = json['insertReplaceSupport'];
    final insertReplaceSupport = insertReplaceSupportJson as bool?;
    final insertTextModeSupportJson = json['insertTextModeSupport'];
    final insertTextModeSupport = insertTextModeSupportJson != null
        ? CompletionItemInsertTextModeSupport.fromJson(
            insertTextModeSupportJson as Map<String, Object?>)
        : null;
    final labelDetailsSupportJson = json['labelDetailsSupport'];
    final labelDetailsSupport = labelDetailsSupportJson as bool?;
    final preselectSupportJson = json['preselectSupport'];
    final preselectSupport = preselectSupportJson as bool?;
    final resolveSupportJson = json['resolveSupport'];
    final resolveSupport = resolveSupportJson != null
        ? CompletionItemResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    final snippetSupportJson = json['snippetSupport'];
    final snippetSupport = snippetSupportJson as bool?;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? CompletionItemTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    return CompletionClientCapabilitiesCompletionItem(
      commitCharactersSupport: commitCharactersSupport,
      deprecatedSupport: deprecatedSupport,
      documentationFormat: documentationFormat,
      insertReplaceSupport: insertReplaceSupport,
      insertTextModeSupport: insertTextModeSupport,
      labelDetailsSupport: labelDetailsSupport,
      preselectSupport: preselectSupport,
      resolveSupport: resolveSupport,
      snippetSupport: snippetSupport,
      tagSupport: tagSupport,
    );
  }

  /// Client supports commit characters on a completion item.
  final bool? commitCharactersSupport;

  /// Client supports the deprecated property on a completion item.
  final bool? deprecatedSupport;

  /// Client supports the following content formats for the documentation
  /// property. The order describes the preferred format of the client.
  final List<MarkupKind>? documentationFormat;

  /// Client support insert replace edit to control different behavior if a
  /// completion item is inserted in the text or should replace text.
  ///
  /// @since 3.16.0
  final bool? insertReplaceSupport;

  /// The client supports the `insertTextMode` property on a completion item to
  /// override the whitespace handling mode as defined by the client (see
  /// `insertTextMode`).
  ///
  /// @since 3.16.0
  final CompletionItemInsertTextModeSupport? insertTextModeSupport;

  /// The client has support for completion item label details (see also
  /// `CompletionItemLabelDetails`).
  ///
  /// @since 3.17.0
  final bool? labelDetailsSupport;

  /// Client supports the preselect property on a completion item.
  final bool? preselectSupport;

  /// Indicates which properties a client can resolve lazily on a completion
  /// item. Before version 3.16.0 only the predefined properties `documentation`
  /// and `details` could be resolved lazily.
  ///
  /// @since 3.16.0
  final CompletionItemResolveSupport? resolveSupport;

  /// Client supports snippets as insert text.
  ///
  /// A snippet can define tab stops and placeholders with `$1`, `$2` and
  /// `${3:foo}`. `$0` defines the final tab stop, it defaults to the end of the
  /// snippet. Placeholders with equal identifiers are linked,
  /// that is typing in one will update others too.
  final bool? snippetSupport;

  /// Client supports the tag property on a completion item. Clients supporting
  /// tags have to handle unknown tags gracefully. Clients especially need to
  /// preserve unknown tags when sending a completion item back to the server in
  /// a resolve call.
  ///
  /// @since 3.15.0
  final CompletionItemTagSupport? tagSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (commitCharactersSupport != null) {
      result['commitCharactersSupport'] = commitCharactersSupport;
    }
    if (deprecatedSupport != null) {
      result['deprecatedSupport'] = deprecatedSupport;
    }
    if (documentationFormat != null) {
      result['documentationFormat'] =
          documentationFormat?.map((item) => item.toJson()).toList();
    }
    if (insertReplaceSupport != null) {
      result['insertReplaceSupport'] = insertReplaceSupport;
    }
    if (insertTextModeSupport != null) {
      result['insertTextModeSupport'] = insertTextModeSupport?.toJson();
    }
    if (labelDetailsSupport != null) {
      result['labelDetailsSupport'] = labelDetailsSupport;
    }
    if (preselectSupport != null) {
      result['preselectSupport'] = preselectSupport;
    }
    if (resolveSupport != null) {
      result['resolveSupport'] = resolveSupport?.toJson();
    }
    if (snippetSupport != null) {
      result['snippetSupport'] = snippetSupport;
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('commitCharactersSupport');
      try {
        final commitCharactersSupport = obj['commitCharactersSupport'];
        if (commitCharactersSupport != null &&
            commitCharactersSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deprecatedSupport');
      try {
        final deprecatedSupport = obj['deprecatedSupport'];
        if (deprecatedSupport != null && deprecatedSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentationFormat');
      try {
        final documentationFormat = obj['documentationFormat'];
        if (documentationFormat != null &&
            (documentationFormat is! List<Object?> ||
                documentationFormat
                    .any((item) => !MarkupKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<MarkupKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertReplaceSupport');
      try {
        final insertReplaceSupport = obj['insertReplaceSupport'];
        if (insertReplaceSupport != null && insertReplaceSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertTextModeSupport');
      try {
        final insertTextModeSupport = obj['insertTextModeSupport'];
        if (insertTextModeSupport != null &&
            !CompletionItemInsertTextModeSupport.canParse(
                insertTextModeSupport, reporter)) {
          reporter.reportError(
              'must be of type CompletionItemInsertTextModeSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('labelDetailsSupport');
      try {
        final labelDetailsSupport = obj['labelDetailsSupport'];
        if (labelDetailsSupport != null && labelDetailsSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('preselectSupport');
      try {
        final preselectSupport = obj['preselectSupport'];
        if (preselectSupport != null && preselectSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveSupport');
      try {
        final resolveSupport = obj['resolveSupport'];
        if (resolveSupport != null &&
            !CompletionItemResolveSupport.canParse(resolveSupport, reporter)) {
          reporter.reportError('must be of type CompletionItemResolveSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('snippetSupport');
      try {
        final snippetSupport = obj['snippetSupport'];
        if (snippetSupport != null && snippetSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        final tagSupport = obj['tagSupport'];
        if (tagSupport != null &&
            !CompletionItemTagSupport.canParse(tagSupport, reporter)) {
          reporter.reportError('must be of type CompletionItemTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type CompletionClientCapabilitiesCompletionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionClientCapabilitiesCompletionItem &&
        other.runtimeType == CompletionClientCapabilitiesCompletionItem &&
        commitCharactersSupport == other.commitCharactersSupport &&
        deprecatedSupport == other.deprecatedSupport &&
        listEqual(documentationFormat, other.documentationFormat,
            (MarkupKind a, MarkupKind b) => a == b) &&
        insertReplaceSupport == other.insertReplaceSupport &&
        insertTextModeSupport == other.insertTextModeSupport &&
        labelDetailsSupport == other.labelDetailsSupport &&
        preselectSupport == other.preselectSupport &&
        resolveSupport == other.resolveSupport &&
        snippetSupport == other.snippetSupport &&
        tagSupport == other.tagSupport;
  }

  @override
  int get hashCode => Object.hash(
        commitCharactersSupport,
        deprecatedSupport,
        lspHashCode(documentationFormat),
        insertReplaceSupport,
        insertTextModeSupport,
        labelDetailsSupport,
        preselectSupport,
        resolveSupport,
        snippetSupport,
        tagSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CompletionClientCapabilitiesCompletionItemKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionClientCapabilitiesCompletionItemKind.canParse,
    CompletionClientCapabilitiesCompletionItemKind.fromJson,
  );

  CompletionClientCapabilitiesCompletionItemKind({
    this.valueSet,
  });
  static CompletionClientCapabilitiesCompletionItemKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => CompletionItemKind.fromJson(item as int))
        .toList();
    return CompletionClientCapabilitiesCompletionItemKind(
      valueSet: valueSet,
    );
  }

  /// The completion item kind values the client supports. When this property
  /// exists the client also guarantees that it will handle values outside its
  /// set gracefully and falls back to a default value when unknown.
  ///
  /// If this property is not present the client only supports the completion
  /// items kinds from `Text` to `Reference` as defined in the initial version
  /// of the protocol.
  final List<CompletionItemKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        final valueSet = obj['valueSet'];
        if (valueSet != null &&
            (valueSet is! List<Object?> ||
                valueSet.any(
                    (item) => !CompletionItemKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<CompletionItemKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type CompletionClientCapabilitiesCompletionItemKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionClientCapabilitiesCompletionItemKind &&
        other.runtimeType == CompletionClientCapabilitiesCompletionItemKind &&
        listEqual(valueSet, other.valueSet,
            (CompletionItemKind a, CompletionItemKind b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CompletionClientCapabilitiesCompletionList implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionClientCapabilitiesCompletionList.canParse,
    CompletionClientCapabilitiesCompletionList.fromJson,
  );

  CompletionClientCapabilitiesCompletionList({
    this.itemDefaults,
  });
  static CompletionClientCapabilitiesCompletionList fromJson(
      Map<String, Object?> json) {
    final itemDefaultsJson = json['itemDefaults'];
    final itemDefaults = (itemDefaultsJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    return CompletionClientCapabilitiesCompletionList(
      itemDefaults: itemDefaults,
    );
  }

  /// The client supports the following itemDefaults on a completion list.
  ///
  /// The value lists the supported property names of the
  /// `CompletionList.itemDefaults` object. If omitted no properties are
  /// supported.
  ///
  /// @since 3.17.0
  final List<String>? itemDefaults;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (itemDefaults != null) {
      result['itemDefaults'] = itemDefaults;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('itemDefaults');
      try {
        final itemDefaults = obj['itemDefaults'];
        if (itemDefaults != null &&
            (itemDefaults is! List<Object?> ||
                itemDefaults.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type CompletionClientCapabilitiesCompletionList');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionClientCapabilitiesCompletionList &&
        other.runtimeType == CompletionClientCapabilitiesCompletionList &&
        listEqual(
            itemDefaults, other.itemDefaults, (String a, String b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(itemDefaults);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Contains additional information about the context in which a completion
/// request is triggered.
class CompletionContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionContext.canParse,
    CompletionContext.fromJson,
  );

  CompletionContext({
    this.triggerCharacter,
    required this.triggerKind,
  });
  static CompletionContext fromJson(Map<String, Object?> json) {
    final triggerCharacterJson = json['triggerCharacter'];
    final triggerCharacter = triggerCharacterJson as String?;
    final triggerKindJson = json['triggerKind'];
    final triggerKind = CompletionTriggerKind.fromJson(triggerKindJson as int);
    return CompletionContext(
      triggerCharacter: triggerCharacter,
      triggerKind: triggerKind,
    );
  }

  /// The trigger character (a single character) that has trigger code complete.
  /// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
  final String? triggerCharacter;

  /// How the completion was triggered.
  final CompletionTriggerKind triggerKind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (triggerCharacter != null) {
      result['triggerCharacter'] = triggerCharacter;
    }
    result['triggerKind'] = triggerKind.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('triggerCharacter');
      try {
        final triggerCharacter = obj['triggerCharacter'];
        if (triggerCharacter != null && triggerCharacter is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerKind');
      try {
        if (!obj.containsKey('triggerKind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final triggerKind = obj['triggerKind'];
        if (triggerKind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!CompletionTriggerKind.canParse(triggerKind, reporter)) {
          reporter.reportError('must be of type CompletionTriggerKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionContext &&
        other.runtimeType == CompletionContext &&
        triggerCharacter == other.triggerCharacter &&
        triggerKind == other.triggerKind;
  }

  @override
  int get hashCode => Object.hash(
        triggerCharacter,
        triggerKind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A completion item represents a text snippet that is proposed to complete
/// text that is being typed.
class CompletionItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionItem.canParse,
    CompletionItem.fromJson,
  );

  CompletionItem({
    this.additionalTextEdits,
    this.command,
    this.commitCharacters,
    this.data,
    this.deprecated,
    this.detail,
    this.documentation,
    this.filterText,
    this.insertText,
    this.insertTextFormat,
    this.insertTextMode,
    this.kind,
    required this.label,
    this.labelDetails,
    this.preselect,
    this.sortText,
    this.tags,
    this.textEdit,
    this.textEditText,
  });
  static CompletionItem fromJson(Map<String, Object?> json) {
    final additionalTextEditsJson = json['additionalTextEdits'];
    final additionalTextEdits = (additionalTextEditsJson as List<Object?>?)
        ?.map((item) => TextEdit.fromJson(item as Map<String, Object?>))
        .toList();
    final commandJson = json['command'];
    final command = commandJson != null
        ? Command.fromJson(commandJson as Map<String, Object?>)
        : null;
    final commitCharactersJson = json['commitCharacters'];
    final commitCharacters = (commitCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final dataJson = json['data'];
    final data = dataJson != null
        ? CompletionItemResolutionInfo.fromJson(
            dataJson as Map<String, Object?>)
        : null;
    final deprecatedJson = json['deprecated'];
    final deprecated = deprecatedJson as bool?;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final documentationJson = json['documentation'];
    final documentation = documentationJson == null
        ? null
        : (MarkupContent.canParse(documentationJson, nullLspJsonReporter)
            ? Either2<MarkupContent, String>.t1(MarkupContent.fromJson(
                documentationJson as Map<String, Object?>))
            : (documentationJson is String
                ? Either2<MarkupContent, String>.t2(documentationJson)
                : (throw '''$documentationJson was not one of (MarkupContent, String)''')));
    final filterTextJson = json['filterText'];
    final filterText = filterTextJson as String?;
    final insertTextJson = json['insertText'];
    final insertText = insertTextJson as String?;
    final insertTextFormatJson = json['insertTextFormat'];
    final insertTextFormat = insertTextFormatJson != null
        ? InsertTextFormat.fromJson(insertTextFormatJson as int)
        : null;
    final insertTextModeJson = json['insertTextMode'];
    final insertTextMode = insertTextModeJson != null
        ? InsertTextMode.fromJson(insertTextModeJson as int)
        : null;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? CompletionItemKind.fromJson(kindJson as int) : null;
    final labelJson = json['label'];
    final label = labelJson as String;
    final labelDetailsJson = json['labelDetails'];
    final labelDetails = labelDetailsJson != null
        ? CompletionItemLabelDetails.fromJson(
            labelDetailsJson as Map<String, Object?>)
        : null;
    final preselectJson = json['preselect'];
    final preselect = preselectJson as bool?;
    final sortTextJson = json['sortText'];
    final sortText = sortTextJson as String?;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => CompletionItemTag.fromJson(item as int))
        .toList();
    final textEditJson = json['textEdit'];
    final textEdit = textEditJson == null
        ? null
        : (InsertReplaceEdit.canParse(textEditJson, nullLspJsonReporter)
            ? Either2<InsertReplaceEdit, TextEdit>.t1(
                InsertReplaceEdit.fromJson(
                    textEditJson as Map<String, Object?>))
            : (TextEdit.canParse(textEditJson, nullLspJsonReporter)
                ? Either2<InsertReplaceEdit, TextEdit>.t2(
                    TextEdit.fromJson(textEditJson as Map<String, Object?>))
                : (throw '''$textEditJson was not one of (InsertReplaceEdit, TextEdit)''')));
    final textEditTextJson = json['textEditText'];
    final textEditText = textEditTextJson as String?;
    return CompletionItem(
      additionalTextEdits: additionalTextEdits,
      command: command,
      commitCharacters: commitCharacters,
      data: data,
      deprecated: deprecated,
      detail: detail,
      documentation: documentation,
      filterText: filterText,
      insertText: insertText,
      insertTextFormat: insertTextFormat,
      insertTextMode: insertTextMode,
      kind: kind,
      label: label,
      labelDetails: labelDetails,
      preselect: preselect,
      sortText: sortText,
      tags: tags,
      textEdit: textEdit,
      textEditText: textEditText,
    );
  }

  /// An optional array of additional text edits that are applied when selecting
  /// this completion. Edits must not overlap (including the same insert
  /// position) with the main edit nor with themselves.
  ///
  /// Additional text edits should be used to change text unrelated to the
  /// current cursor position (for example adding an import statement at the top
  /// of the file if the completion item will insert an unqualified type).
  final List<TextEdit>? additionalTextEdits;

  /// An optional command that is executed *after* inserting this completion.
  /// *Note* that additional modifications to the current document should be
  /// described with the additionalTextEdits-property.
  final Command? command;

  /// An optional set of characters that when pressed while this completion is
  /// active will accept it first and then type that character. *Note* that all
  /// commit characters should have `length=1` and that superfluous characters
  /// will be ignored.
  final List<String>? commitCharacters;

  /// A data entry field that is preserved on a completion item between a
  /// CompletionRequest and a CompletionResolveRequest.
  final CompletionItemResolutionInfo? data;

  /// Indicates if this item is deprecated.
  /// @deprecated Use `tags` instead.
  final bool? deprecated;

  /// A human-readable string with additional information about this item, like
  /// type or symbol information.
  final String? detail;

  /// A human-readable string that represents a doc-comment.
  final Either2<MarkupContent, String>? documentation;

  /// A string that should be used when filtering a set of completion items.
  /// When `falsy` the label is used.
  final String? filterText;

  /// A string that should be inserted into a document when selecting this
  /// completion. When `falsy` the label is used.
  ///
  /// The `insertText` is subject to interpretation by the client side. Some
  /// tools might not take the string literally. For example VS Code when code
  /// complete is requested in this example `con<cursor position>` and a
  /// completion item with an `insertText` of `console` is provided it will only
  /// insert `sole`. Therefore it is recommended to use `textEdit` instead since
  /// it avoids additional client side interpretation.
  final String? insertText;

  /// The format of the insert text. The format applies to both the `insertText`
  /// property and the `newText` property of a provided `textEdit`. If omitted
  /// defaults to `InsertTextFormat.PlainText`.
  ///
  /// Please note that the insertTextFormat doesn't apply to
  /// `additionalTextEdits`.
  final InsertTextFormat? insertTextFormat;

  /// How whitespace and indentation is handled during completion item
  /// insertion. If not provided the clients default value depends on the
  /// `textDocument.completion.insertTextMode` client capability.
  ///
  /// @since 3.16.0
  final InsertTextMode? insertTextMode;

  /// The kind of this completion item. Based of the kind an icon is chosen by
  /// the editor.
  final CompletionItemKind? kind;

  /// The label of this completion item.
  ///
  /// The label property is also by default the text that is inserted when
  /// selecting this completion.
  ///
  /// If label details are provided the label itself should be an unqualified
  /// name of the completion item.
  final String label;

  /// Additional details for the label
  ///
  /// @since 3.17.0
  final CompletionItemLabelDetails? labelDetails;

  /// Select this item when showing.
  ///
  /// *Note* that only one completion item can be selected and that the tool /
  /// client decides which item that is. The rule is that the *first*
  /// item of those that match best is selected.
  final bool? preselect;

  /// A string that should be used when comparing this item with other items.
  /// When `falsy` the label is used.
  final String? sortText;

  /// Tags for this completion item.
  ///
  /// @since 3.15.0
  final List<CompletionItemTag>? tags;

  /// An edit which is applied to a document when selecting this completion.
  /// When an edit is provided the value of insertText is ignored.
  ///
  /// Most editors support two different operations when accepting a completion
  /// item. One is to insert a completion text and the other is to replace an
  /// existing text with a completion text. Since this can usually not be
  /// predetermined by a server it can report both ranges. Clients need to
  /// signal support for `InsertReplaceEdits` via the
  /// `textDocument.completion.insertReplaceSupport` client capability property.
  ///
  /// *Note 1:* The text edit's range as well as both ranges from an insert
  /// replace edit must be a [single line] and they must contain the position at
  /// which completion has been requested.
  /// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range
  /// must be a prefix of the edit's replace range, that means it must be
  /// contained and starting at the same position.
  ///
  /// @since 3.16.0 additional type `InsertReplaceEdit`
  final Either2<InsertReplaceEdit, TextEdit>? textEdit;

  /// The edit text used if the completion item is part of a CompletionList and
  /// CompletionList defines an item default for the text edit range.
  ///
  /// Clients will only honor this property if they opt into completion list
  /// item defaults using the capability `completionList.itemDefaults`.
  ///
  /// If not provided and a list's default range is provided the label property
  /// is used as a text.
  ///
  /// @since 3.17.0
  final String? textEditText;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (additionalTextEdits != null) {
      result['additionalTextEdits'] =
          additionalTextEdits?.map((item) => item.toJson()).toList();
    }
    if (command != null) {
      result['command'] = command?.toJson();
    }
    if (commitCharacters != null) {
      result['commitCharacters'] = commitCharacters;
    }
    if (data != null) {
      result['data'] = data?.toJson();
    }
    if (deprecated != null) {
      result['deprecated'] = deprecated;
    }
    if (detail != null) {
      result['detail'] = detail;
    }
    if (documentation != null) {
      result['documentation'] = documentation;
    }
    if (filterText != null) {
      result['filterText'] = filterText;
    }
    if (insertText != null) {
      result['insertText'] = insertText;
    }
    if (insertTextFormat != null) {
      result['insertTextFormat'] = insertTextFormat?.toJson();
    }
    if (insertTextMode != null) {
      result['insertTextMode'] = insertTextMode?.toJson();
    }
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['label'] = label;
    if (labelDetails != null) {
      result['labelDetails'] = labelDetails?.toJson();
    }
    if (preselect != null) {
      result['preselect'] = preselect;
    }
    if (sortText != null) {
      result['sortText'] = sortText;
    }
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    if (textEdit != null) {
      result['textEdit'] = textEdit;
    }
    if (textEditText != null) {
      result['textEditText'] = textEditText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('additionalTextEdits');
      try {
        final additionalTextEdits = obj['additionalTextEdits'];
        if (additionalTextEdits != null &&
            (additionalTextEdits is! List<Object?> ||
                additionalTextEdits
                    .any((item) => !TextEdit.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<TextEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('command');
      try {
        final command = obj['command'];
        if (command != null && !Command.canParse(command, reporter)) {
          reporter.reportError('must be of type Command');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('commitCharacters');
      try {
        final commitCharacters = obj['commitCharacters'];
        if (commitCharacters != null &&
            (commitCharacters is! List<Object?> ||
                commitCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('data');
      try {
        final data = obj['data'];
        if (data != null &&
            !CompletionItemResolutionInfo.canParse(data, reporter)) {
          reporter.reportError('must be of type CompletionItemResolutionInfo');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deprecated');
      try {
        final deprecated = obj['deprecated'];
        if (deprecated != null && deprecated is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('detail');
      try {
        final detail = obj['detail'];
        if (detail != null && detail is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentation');
      try {
        final documentation = obj['documentation'];
        if (documentation != null &&
            !MarkupContent.canParse(documentation, reporter) &&
            documentation is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('filterText');
      try {
        final filterText = obj['filterText'];
        if (filterText != null && filterText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertText');
      try {
        final insertText = obj['insertText'];
        if (insertText != null && insertText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertTextFormat');
      try {
        final insertTextFormat = obj['insertTextFormat'];
        if (insertTextFormat != null &&
            !InsertTextFormat.canParse(insertTextFormat, reporter)) {
          reporter.reportError('must be of type InsertTextFormat');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertTextMode');
      try {
        final insertTextMode = obj['insertTextMode'];
        if (insertTextMode != null &&
            !InsertTextMode.canParse(insertTextMode, reporter)) {
          reporter.reportError('must be of type InsertTextMode');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !CompletionItemKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type CompletionItemKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final label = obj['label'];
        if (label == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('labelDetails');
      try {
        final labelDetails = obj['labelDetails'];
        if (labelDetails != null &&
            !CompletionItemLabelDetails.canParse(labelDetails, reporter)) {
          reporter.reportError('must be of type CompletionItemLabelDetails');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('preselect');
      try {
        final preselect = obj['preselect'];
        if (preselect != null && preselect is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('sortText');
      try {
        final sortText = obj['sortText'];
        if (sortText != null && sortText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any(
                    (item) => !CompletionItemTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<CompletionItemTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textEdit');
      try {
        final textEdit = obj['textEdit'];
        if (textEdit != null &&
            !InsertReplaceEdit.canParse(textEdit, reporter) &&
            !TextEdit.canParse(textEdit, reporter)) {
          reporter.reportError(
              'must be of type Either2<InsertReplaceEdit, TextEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textEditText');
      try {
        final textEditText = obj['textEditText'];
        if (textEditText != null && textEditText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionItem &&
        other.runtimeType == CompletionItem &&
        listEqual(additionalTextEdits, other.additionalTextEdits,
            (TextEdit a, TextEdit b) => a == b) &&
        command == other.command &&
        listEqual(commitCharacters, other.commitCharacters,
            (String a, String b) => a == b) &&
        data == other.data &&
        deprecated == other.deprecated &&
        detail == other.detail &&
        documentation == other.documentation &&
        filterText == other.filterText &&
        insertText == other.insertText &&
        insertTextFormat == other.insertTextFormat &&
        insertTextMode == other.insertTextMode &&
        kind == other.kind &&
        label == other.label &&
        labelDetails == other.labelDetails &&
        preselect == other.preselect &&
        sortText == other.sortText &&
        listEqual(tags, other.tags,
            (CompletionItemTag a, CompletionItemTag b) => a == b) &&
        textEdit == other.textEdit &&
        textEditText == other.textEditText;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(additionalTextEdits),
        command,
        lspHashCode(commitCharacters),
        data,
        deprecated,
        detail,
        documentation,
        filterText,
        insertText,
        insertTextFormat,
        insertTextMode,
        kind,
        label,
        labelDetails,
        preselect,
        sortText,
        lspHashCode(tags),
        textEdit,
        textEditText,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CompletionItemEditRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionItemEditRange.canParse,
    CompletionItemEditRange.fromJson,
  );

  CompletionItemEditRange({
    required this.insert,
    required this.replace,
  });
  static CompletionItemEditRange fromJson(Map<String, Object?> json) {
    final insertJson = json['insert'];
    final insert = Range.fromJson(insertJson as Map<String, Object?>);
    final replaceJson = json['replace'];
    final replace = Range.fromJson(replaceJson as Map<String, Object?>);
    return CompletionItemEditRange(
      insert: insert,
      replace: replace,
    );
  }

  final Range insert;
  final Range replace;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['insert'] = insert.toJson();
    result['replace'] = replace.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('insert');
      try {
        if (!obj.containsKey('insert')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final insert = obj['insert'];
        if (insert == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(insert, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('replace');
      try {
        if (!obj.containsKey('replace')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final replace = obj['replace'];
        if (replace == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(replace, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionItemEditRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionItemEditRange &&
        other.runtimeType == CompletionItemEditRange &&
        insert == other.insert &&
        replace == other.replace;
  }

  @override
  int get hashCode => Object.hash(
        insert,
        replace,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CompletionItemInsertTextModeSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionItemInsertTextModeSupport.canParse,
    CompletionItemInsertTextModeSupport.fromJson,
  );

  CompletionItemInsertTextModeSupport({
    required this.valueSet,
  });
  static CompletionItemInsertTextModeSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => InsertTextMode.fromJson(item as int))
        .toList();
    return CompletionItemInsertTextModeSupport(
      valueSet: valueSet,
    );
  }

  final List<InsertTextMode> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final valueSet = obj['valueSet'];
        if (valueSet == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (valueSet is! List<Object?> ||
            valueSet.any((item) => !InsertTextMode.canParse(item, reporter))) {
          reporter.reportError('must be of type List<InsertTextMode>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type CompletionItemInsertTextModeSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionItemInsertTextModeSupport &&
        other.runtimeType == CompletionItemInsertTextModeSupport &&
        listEqual(valueSet, other.valueSet,
            (InsertTextMode a, InsertTextMode b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The kind of a completion entry.
class CompletionItemKind implements ToJsonable {
  const CompletionItemKind(this._value);
  const CompletionItemKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  static const Class = CompletionItemKind(7);
  static const Color = CompletionItemKind(16);
  static const Constant = CompletionItemKind(21);
  static const Constructor = CompletionItemKind(4);
  static const Enum = CompletionItemKind(13);
  static const EnumMember = CompletionItemKind(20);
  static const Event = CompletionItemKind(23);
  static const Field = CompletionItemKind(5);
  static const File = CompletionItemKind(17);
  static const Folder = CompletionItemKind(19);
  static const Function = CompletionItemKind(3);
  static const Interface = CompletionItemKind(8);
  static const Keyword = CompletionItemKind(14);
  static const Method = CompletionItemKind(2);
  static const Module = CompletionItemKind(9);
  static const Operator = CompletionItemKind(24);
  static const Property = CompletionItemKind(10);
  static const Reference = CompletionItemKind(18);
  static const Snippet = CompletionItemKind(15);
  static const Struct = CompletionItemKind(22);
  static const Text = CompletionItemKind(1);
  static const TypeParameter = CompletionItemKind(25);
  static const Unit = CompletionItemKind(11);
  static const Value = CompletionItemKind(12);
  static const Variable = CompletionItemKind(6);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is CompletionItemKind && other._value == _value;
}

/// Additional details for a completion item label.
///
/// @since 3.17.0
class CompletionItemLabelDetails implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionItemLabelDetails.canParse,
    CompletionItemLabelDetails.fromJson,
  );

  CompletionItemLabelDetails({
    this.description,
    this.detail,
  });
  static CompletionItemLabelDetails fromJson(Map<String, Object?> json) {
    final descriptionJson = json['description'];
    final description = descriptionJson as String?;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    return CompletionItemLabelDetails(
      description: description,
      detail: detail,
    );
  }

  /// An optional string which is rendered less prominently after {@link
  /// CompletionItem.detail}. Should be used for fully qualified names and file
  /// paths.
  final String? description;

  /// An optional string which is rendered less prominently directly after
  /// {@link CompletionItem.label label},
  /// without any spacing. Should be used for function signatures and type
  /// annotations.
  final String? detail;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (description != null) {
      result['description'] = description;
    }
    if (detail != null) {
      result['detail'] = detail;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('description');
      try {
        final description = obj['description'];
        if (description != null && description is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('detail');
      try {
        final detail = obj['detail'];
        if (detail != null && detail is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionItemLabelDetails');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionItemLabelDetails &&
        other.runtimeType == CompletionItemLabelDetails &&
        description == other.description &&
        detail == other.detail;
  }

  @override
  int get hashCode => Object.hash(
        description,
        detail,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CompletionItemResolveSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionItemResolveSupport.canParse,
    CompletionItemResolveSupport.fromJson,
  );

  CompletionItemResolveSupport({
    required this.properties,
  });
  static CompletionItemResolveSupport fromJson(Map<String, Object?> json) {
    final propertiesJson = json['properties'];
    final properties = (propertiesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return CompletionItemResolveSupport(
      properties: properties,
    );
  }

  /// The properties that a client can resolve lazily.
  final List<String> properties;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('properties');
      try {
        if (!obj.containsKey('properties')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final properties = obj['properties'];
        if (properties == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (properties is! List<Object?> ||
            properties.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionItemResolveSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionItemResolveSupport &&
        other.runtimeType == CompletionItemResolveSupport &&
        listEqual(properties, other.properties, (String a, String b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(properties);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Completion item tags are extra annotations that tweak the rendering of a
/// completion item.
///
/// @since 3.15.0
class CompletionItemTag implements ToJsonable {
  const CompletionItemTag(this._value);
  const CompletionItemTag.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Render a completion as obsolete, usually using a strike-out.
  static const Deprecated = CompletionItemTag(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is CompletionItemTag && other._value == _value;
}

class CompletionItemTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionItemTagSupport.canParse,
    CompletionItemTagSupport.fromJson,
  );

  CompletionItemTagSupport({
    required this.valueSet,
  });
  static CompletionItemTagSupport fromJson(Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => CompletionItemTag.fromJson(item as int))
        .toList();
    return CompletionItemTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<CompletionItemTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final valueSet = obj['valueSet'];
        if (valueSet == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (valueSet is! List<Object?> ||
            valueSet
                .any((item) => !CompletionItemTag.canParse(item, reporter))) {
          reporter.reportError('must be of type List<CompletionItemTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionItemTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionItemTagSupport &&
        other.runtimeType == CompletionItemTagSupport &&
        listEqual(valueSet, other.valueSet,
            (CompletionItemTag a, CompletionItemTag b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a collection of completion items to be presented in the editor.
class CompletionList implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionList.canParse,
    CompletionList.fromJson,
  );

  CompletionList({
    required this.isIncomplete,
    this.itemDefaults,
    required this.items,
  });
  static CompletionList fromJson(Map<String, Object?> json) {
    final isIncompleteJson = json['isIncomplete'];
    final isIncomplete = isIncompleteJson as bool;
    final itemDefaultsJson = json['itemDefaults'];
    final itemDefaults = itemDefaultsJson != null
        ? CompletionListItemDefaults.fromJson(
            itemDefaultsJson as Map<String, Object?>)
        : null;
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => CompletionItem.fromJson(item as Map<String, Object?>))
        .toList();
    return CompletionList(
      isIncomplete: isIncomplete,
      itemDefaults: itemDefaults,
      items: items,
    );
  }

  /// This list it not complete. Further typing results in recomputing this
  /// list.
  ///
  /// Recomputed lists have all their items replaced (not appended) in the
  /// incomplete completion sessions.
  final bool isIncomplete;

  /// In many cases the items of an actual completion result share the same
  /// value for properties like `commitCharacters` or the range of a text edit.
  /// A completion list can therefore define item defaults which will be used if
  /// a completion item itself doesn't specify the value.
  ///
  /// If a completion list specifies a default value and a completion item also
  /// specifies a corresponding value the one from the item is used.
  ///
  /// Servers are only allowed to return default values if the client signals
  /// support for this via the `completionList.itemDefaults` capability.
  ///
  /// @since 3.17.0
  final CompletionListItemDefaults? itemDefaults;

  /// The completion items.
  final List<CompletionItem> items;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['isIncomplete'] = isIncomplete;
    if (itemDefaults != null) {
      result['itemDefaults'] = itemDefaults?.toJson();
    }
    result['items'] = items.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('isIncomplete');
      try {
        if (!obj.containsKey('isIncomplete')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final isIncomplete = obj['isIncomplete'];
        if (isIncomplete == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (isIncomplete is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('itemDefaults');
      try {
        final itemDefaults = obj['itemDefaults'];
        if (itemDefaults != null &&
            !CompletionListItemDefaults.canParse(itemDefaults, reporter)) {
          reporter.reportError('must be of type CompletionListItemDefaults');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) => !CompletionItem.canParse(item, reporter))) {
          reporter.reportError('must be of type List<CompletionItem>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionList');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionList &&
        other.runtimeType == CompletionList &&
        isIncomplete == other.isIncomplete &&
        itemDefaults == other.itemDefaults &&
        listEqual(
            items, other.items, (CompletionItem a, CompletionItem b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        isIncomplete,
        itemDefaults,
        lspHashCode(items),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CompletionListItemDefaults implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionListItemDefaults.canParse,
    CompletionListItemDefaults.fromJson,
  );

  CompletionListItemDefaults({
    this.commitCharacters,
    this.data,
    this.editRange,
    this.insertTextFormat,
    this.insertTextMode,
  });
  static CompletionListItemDefaults fromJson(Map<String, Object?> json) {
    final commitCharactersJson = json['commitCharacters'];
    final commitCharacters = (commitCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final dataJson = json['data'];
    final data = dataJson;
    final editRangeJson = json['editRange'];
    final editRange = editRangeJson == null
        ? null
        : (CompletionItemEditRange.canParse(editRangeJson, nullLspJsonReporter)
            ? Either2<CompletionItemEditRange, Range>.t1(
                CompletionItemEditRange.fromJson(
                    editRangeJson as Map<String, Object?>))
            : (Range.canParse(editRangeJson, nullLspJsonReporter)
                ? Either2<CompletionItemEditRange, Range>.t2(
                    Range.fromJson(editRangeJson as Map<String, Object?>))
                : (throw '''$editRangeJson was not one of (CompletionItemEditRange, Range)''')));
    final insertTextFormatJson = json['insertTextFormat'];
    final insertTextFormat = insertTextFormatJson != null
        ? InsertTextFormat.fromJson(insertTextFormatJson as int)
        : null;
    final insertTextModeJson = json['insertTextMode'];
    final insertTextMode = insertTextModeJson != null
        ? InsertTextMode.fromJson(insertTextModeJson as int)
        : null;
    return CompletionListItemDefaults(
      commitCharacters: commitCharacters,
      data: data,
      editRange: editRange,
      insertTextFormat: insertTextFormat,
      insertTextMode: insertTextMode,
    );
  }

  /// A default commit character set.
  ///
  /// @since 3.17.0
  final List<String>? commitCharacters;

  /// A default data value.
  ///
  /// @since 3.17.0
  final Object? data;

  /// A default edit range.
  ///
  /// @since 3.17.0
  final Either2<CompletionItemEditRange, Range>? editRange;

  /// A default insert text format.
  ///
  /// @since 3.17.0
  final InsertTextFormat? insertTextFormat;

  /// A default insert text mode.
  ///
  /// @since 3.17.0
  final InsertTextMode? insertTextMode;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (commitCharacters != null) {
      result['commitCharacters'] = commitCharacters;
    }
    if (data != null) {
      result['data'] = data;
    }
    if (editRange != null) {
      result['editRange'] = editRange;
    }
    if (insertTextFormat != null) {
      result['insertTextFormat'] = insertTextFormat?.toJson();
    }
    if (insertTextMode != null) {
      result['insertTextMode'] = insertTextMode?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('commitCharacters');
      try {
        final commitCharacters = obj['commitCharacters'];
        if (commitCharacters != null &&
            (commitCharacters is! List<Object?> ||
                commitCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('editRange');
      try {
        final editRange = obj['editRange'];
        if (editRange != null &&
            !CompletionItemEditRange.canParse(editRange, reporter) &&
            !Range.canParse(editRange, reporter)) {
          reporter.reportError(
              'must be of type Either2<CompletionItemEditRange, Range>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertTextFormat');
      try {
        final insertTextFormat = obj['insertTextFormat'];
        if (insertTextFormat != null &&
            !InsertTextFormat.canParse(insertTextFormat, reporter)) {
          reporter.reportError('must be of type InsertTextFormat');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertTextMode');
      try {
        final insertTextMode = obj['insertTextMode'];
        if (insertTextMode != null &&
            !InsertTextMode.canParse(insertTextMode, reporter)) {
          reporter.reportError('must be of type InsertTextMode');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionListItemDefaults');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionListItemDefaults &&
        other.runtimeType == CompletionListItemDefaults &&
        listEqual(commitCharacters, other.commitCharacters,
            (String a, String b) => a == b) &&
        data == other.data &&
        editRange == other.editRange &&
        insertTextFormat == other.insertTextFormat &&
        insertTextMode == other.insertTextMode;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(commitCharacters),
        data,
        editRange,
        insertTextFormat,
        insertTextMode,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Completion options.
class CompletionOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionOptions.canParse,
    CompletionOptions.fromJson,
  );

  CompletionOptions({
    this.allCommitCharacters,
    this.completionItem,
    this.resolveProvider,
    this.triggerCharacters,
    this.workDoneProgress,
  });
  static CompletionOptions fromJson(Map<String, Object?> json) {
    if (CompletionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionRegistrationOptions.fromJson(json);
    }
    final allCommitCharactersJson = json['allCommitCharacters'];
    final allCommitCharacters = (allCommitCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final completionItemJson = json['completionItem'];
    final completionItem = completionItemJson != null
        ? CompletionOptionsCompletionItem.fromJson(
            completionItemJson as Map<String, Object?>)
        : null;
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CompletionOptions(
      allCommitCharacters: allCommitCharacters,
      completionItem: completionItem,
      resolveProvider: resolveProvider,
      triggerCharacters: triggerCharacters,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The list of all possible characters that commit a completion. This field
  /// can be used if clients don't support individual commit characters per
  /// completion item. See
  /// `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`
  ///
  /// If a server provides both `allCommitCharacters` and commit characters on
  /// an individual completion item the ones on the completion item win.
  ///
  /// @since 3.2.0
  final List<String>? allCommitCharacters;

  /// The server supports the following `CompletionItem` specific capabilities.
  ///
  /// @since 3.17.0
  final CompletionOptionsCompletionItem? completionItem;

  /// The server provides support to resolve additional information for a
  /// completion item.
  final bool? resolveProvider;

  /// Most tools trigger completion request automatically without explicitly
  /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they
  /// do so when the user starts to type an identifier. For example if the user
  /// types `c` in a JavaScript file code complete will automatically pop up
  /// present `console` besides others as a completion item. Characters that
  /// make up identifiers don't need to be listed here.
  ///
  /// If code complete should automatically be trigger on characters not being
  /// valid inside an identifier (for example `.` in JavaScript) list them in
  /// `triggerCharacters`.
  final List<String>? triggerCharacters;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (allCommitCharacters != null) {
      result['allCommitCharacters'] = allCommitCharacters;
    }
    if (completionItem != null) {
      result['completionItem'] = completionItem?.toJson();
    }
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (triggerCharacters != null) {
      result['triggerCharacters'] = triggerCharacters;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('allCommitCharacters');
      try {
        final allCommitCharacters = obj['allCommitCharacters'];
        if (allCommitCharacters != null &&
            (allCommitCharacters is! List<Object?> ||
                allCommitCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completionItem');
      try {
        final completionItem = obj['completionItem'];
        if (completionItem != null &&
            !CompletionOptionsCompletionItem.canParse(
                completionItem, reporter)) {
          reporter
              .reportError('must be of type CompletionOptionsCompletionItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacters');
      try {
        final triggerCharacters = obj['triggerCharacters'];
        if (triggerCharacters != null &&
            (triggerCharacters is! List<Object?> ||
                triggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionOptions &&
        other.runtimeType == CompletionOptions &&
        listEqual(allCommitCharacters, other.allCommitCharacters,
            (String a, String b) => a == b) &&
        completionItem == other.completionItem &&
        resolveProvider == other.resolveProvider &&
        listEqual(triggerCharacters, other.triggerCharacters,
            (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(allCommitCharacters),
        completionItem,
        resolveProvider,
        lspHashCode(triggerCharacters),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class CompletionOptionsCompletionItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionOptionsCompletionItem.canParse,
    CompletionOptionsCompletionItem.fromJson,
  );

  CompletionOptionsCompletionItem({
    this.labelDetailsSupport,
  });
  static CompletionOptionsCompletionItem fromJson(Map<String, Object?> json) {
    final labelDetailsSupportJson = json['labelDetailsSupport'];
    final labelDetailsSupport = labelDetailsSupportJson as bool?;
    return CompletionOptionsCompletionItem(
      labelDetailsSupport: labelDetailsSupport,
    );
  }

  /// The server has support for completion item label details (see also
  /// `CompletionItemLabelDetails`) when receiving a completion item in a
  /// resolve call.
  ///
  /// @since 3.17.0
  final bool? labelDetailsSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (labelDetailsSupport != null) {
      result['labelDetailsSupport'] = labelDetailsSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('labelDetailsSupport');
      try {
        final labelDetailsSupport = obj['labelDetailsSupport'];
        if (labelDetailsSupport != null && labelDetailsSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionOptionsCompletionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionOptionsCompletionItem &&
        other.runtimeType == CompletionOptionsCompletionItem &&
        labelDetailsSupport == other.labelDetailsSupport;
  }

  @override
  int get hashCode => labelDetailsSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Completion parameters
class CompletionParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionParams.canParse,
    CompletionParams.fromJson,
  );

  CompletionParams({
    this.context,
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static CompletionParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context = contextJson != null
        ? CompletionContext.fromJson(contextJson as Map<String, Object?>)
        : null;
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return CompletionParams(
      context: context,
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The completion context. This is only available it the client specifies to
  /// send this using the client capability
  /// `textDocument.completion.contextSupport === true`
  final CompletionContext? context;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (context != null) {
      result['context'] = context?.toJson();
    }
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('context');
      try {
        final context = obj['context'];
        if (context != null && !CompletionContext.canParse(context, reporter)) {
          reporter.reportError('must be of type CompletionContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionParams &&
        other.runtimeType == CompletionParams &&
        context == other.context &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        context,
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a CompletionRequest.
class CompletionRegistrationOptions
    implements CompletionOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionRegistrationOptions.canParse,
    CompletionRegistrationOptions.fromJson,
  );

  CompletionRegistrationOptions({
    this.allCommitCharacters,
    this.completionItem,
    this.documentSelector,
    this.resolveProvider,
    this.triggerCharacters,
    this.workDoneProgress,
  });
  static CompletionRegistrationOptions fromJson(Map<String, Object?> json) {
    final allCommitCharactersJson = json['allCommitCharacters'];
    final allCommitCharacters = (allCommitCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final completionItemJson = json['completionItem'];
    final completionItem = completionItemJson != null
        ? CompletionOptionsCompletionItem.fromJson(
            completionItemJson as Map<String, Object?>)
        : null;
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CompletionRegistrationOptions(
      allCommitCharacters: allCommitCharacters,
      completionItem: completionItem,
      documentSelector: documentSelector,
      resolveProvider: resolveProvider,
      triggerCharacters: triggerCharacters,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The list of all possible characters that commit a completion. This field
  /// can be used if clients don't support individual commit characters per
  /// completion item. See
  /// `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`
  ///
  /// If a server provides both `allCommitCharacters` and commit characters on
  /// an individual completion item the ones on the completion item win.
  ///
  /// @since 3.2.0
  @override
  final List<String>? allCommitCharacters;

  /// The server supports the following `CompletionItem` specific capabilities.
  ///
  /// @since 3.17.0
  @override
  final CompletionOptionsCompletionItem? completionItem;

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The server provides support to resolve additional information for a
  /// completion item.
  @override
  final bool? resolveProvider;

  /// Most tools trigger completion request automatically without explicitly
  /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they
  /// do so when the user starts to type an identifier. For example if the user
  /// types `c` in a JavaScript file code complete will automatically pop up
  /// present `console` besides others as a completion item. Characters that
  /// make up identifiers don't need to be listed here.
  ///
  /// If code complete should automatically be trigger on characters not being
  /// valid inside an identifier (for example `.` in JavaScript) list them in
  /// `triggerCharacters`.
  @override
  final List<String>? triggerCharacters;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (allCommitCharacters != null) {
      result['allCommitCharacters'] = allCommitCharacters;
    }
    if (completionItem != null) {
      result['completionItem'] = completionItem?.toJson();
    }
    result['documentSelector'] = documentSelector;
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (triggerCharacters != null) {
      result['triggerCharacters'] = triggerCharacters;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('allCommitCharacters');
      try {
        final allCommitCharacters = obj['allCommitCharacters'];
        if (allCommitCharacters != null &&
            (allCommitCharacters is! List<Object?> ||
                allCommitCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completionItem');
      try {
        final completionItem = obj['completionItem'];
        if (completionItem != null &&
            !CompletionOptionsCompletionItem.canParse(
                completionItem, reporter)) {
          reporter
              .reportError('must be of type CompletionOptionsCompletionItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacters');
      try {
        final triggerCharacters = obj['triggerCharacters'];
        if (triggerCharacters != null &&
            (triggerCharacters is! List<Object?> ||
                triggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CompletionRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CompletionRegistrationOptions &&
        other.runtimeType == CompletionRegistrationOptions &&
        listEqual(allCommitCharacters, other.allCommitCharacters,
            (String a, String b) => a == b) &&
        completionItem == other.completionItem &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        resolveProvider == other.resolveProvider &&
        listEqual(triggerCharacters, other.triggerCharacters,
            (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(allCommitCharacters),
        completionItem,
        lspHashCode(documentSelector),
        resolveProvider,
        lspHashCode(triggerCharacters),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// How a completion was triggered
class CompletionTriggerKind implements ToJsonable {
  const CompletionTriggerKind._(this._value);
  const CompletionTriggerKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 1:
      case 2:
      case 3:
        return true;
    }
    return false;
  }

  /// Completion was triggered by typing an identifier (24x7 code complete),
  /// manual invocation (e.g Ctrl+Space) or via API.
  static const Invoked = CompletionTriggerKind._(1);

  /// Completion was triggered by a trigger character specified by the
  /// `triggerCharacters` properties of the `CompletionRegistrationOptions`.
  static const TriggerCharacter = CompletionTriggerKind._(2);

  /// Completion was re-triggered as current completion list is incomplete
  static const TriggerForIncompleteCompletions = CompletionTriggerKind._(3);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is CompletionTriggerKind && other._value == _value;
}

class ConfigurationItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ConfigurationItem.canParse,
    ConfigurationItem.fromJson,
  );

  ConfigurationItem({
    this.scopeUri,
    this.section,
  });
  static ConfigurationItem fromJson(Map<String, Object?> json) {
    final scopeUriJson = json['scopeUri'];
    final scopeUri = scopeUriJson as String?;
    final sectionJson = json['section'];
    final section = sectionJson as String?;
    return ConfigurationItem(
      scopeUri: scopeUri,
      section: section,
    );
  }

  /// The scope to get the configuration section for.
  final String? scopeUri;

  /// The configuration section asked for.
  final String? section;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (scopeUri != null) {
      result['scopeUri'] = scopeUri;
    }
    if (section != null) {
      result['section'] = section;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('scopeUri');
      try {
        final scopeUri = obj['scopeUri'];
        if (scopeUri != null && scopeUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('section');
      try {
        final section = obj['section'];
        if (section != null && section is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ConfigurationItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ConfigurationItem &&
        other.runtimeType == ConfigurationItem &&
        scopeUri == other.scopeUri &&
        section == other.section;
  }

  @override
  int get hashCode => Object.hash(
        scopeUri,
        section,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a configuration request.
class ConfigurationParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ConfigurationParams.canParse,
    ConfigurationParams.fromJson,
  );

  ConfigurationParams({
    required this.items,
  });
  static ConfigurationParams fromJson(Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => ConfigurationItem.fromJson(item as Map<String, Object?>))
        .toList();
    return ConfigurationParams(
      items: items,
    );
  }

  final List<ConfigurationItem> items;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) => !ConfigurationItem.canParse(item, reporter))) {
          reporter.reportError('must be of type List<ConfigurationItem>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ConfigurationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ConfigurationParams &&
        other.runtimeType == ConfigurationParams &&
        listEqual(items, other.items,
            (ConfigurationItem a, ConfigurationItem b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(items);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Create file operation.
class CreateFile implements ResourceOperation, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CreateFile.canParse,
    CreateFile.fromJson,
  );

  CreateFile({
    this.annotationId,
    this.kind = 'create',
    this.options,
    required this.uri,
  }) {
    if (kind != 'create') {
      throw 'kind may only be the literal \'create\'';
    }
  }
  static CreateFile fromJson(Map<String, Object?> json) {
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? CreateFileOptions.fromJson(optionsJson as Map<String, Object?>)
        : null;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return CreateFile(
      annotationId: annotationId,
      kind: kind,
      options: options,
      uri: uri,
    );
  }

  /// An optional annotation identifier describing the operation.
  ///
  /// @since 3.16.0
  @override
  final String? annotationId;

  /// A create
  @override
  final String kind;

  /// Additional options
  final CreateFileOptions? options;

  /// The resource to create.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (annotationId != null) {
      result['annotationId'] = annotationId;
    }
    result['kind'] = kind;
    if (options != null) {
      result['options'] = options?.toJson();
    }
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('annotationId');
      try {
        final annotationId = obj['annotationId'];
        if (annotationId != null && annotationId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'create') {
          reporter.reportError('must be the literal \'create\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        final options = obj['options'];
        if (options != null && !CreateFileOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type CreateFileOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CreateFile');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CreateFile &&
        other.runtimeType == CreateFile &&
        annotationId == other.annotationId &&
        kind == other.kind &&
        options == other.options &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        annotationId,
        kind,
        options,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Options to create a file.
class CreateFileOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CreateFileOptions.canParse,
    CreateFileOptions.fromJson,
  );

  CreateFileOptions({
    this.ignoreIfExists,
    this.overwrite,
  });
  static CreateFileOptions fromJson(Map<String, Object?> json) {
    final ignoreIfExistsJson = json['ignoreIfExists'];
    final ignoreIfExists = ignoreIfExistsJson as bool?;
    final overwriteJson = json['overwrite'];
    final overwrite = overwriteJson as bool?;
    return CreateFileOptions(
      ignoreIfExists: ignoreIfExists,
      overwrite: overwrite,
    );
  }

  /// Ignore if exists.
  final bool? ignoreIfExists;

  /// Overwrite existing file. Overwrite wins over `ignoreIfExists`
  final bool? overwrite;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (ignoreIfExists != null) {
      result['ignoreIfExists'] = ignoreIfExists;
    }
    if (overwrite != null) {
      result['overwrite'] = overwrite;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ignoreIfExists');
      try {
        final ignoreIfExists = obj['ignoreIfExists'];
        if (ignoreIfExists != null && ignoreIfExists is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('overwrite');
      try {
        final overwrite = obj['overwrite'];
        if (overwrite != null && overwrite is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CreateFileOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CreateFileOptions &&
        other.runtimeType == CreateFileOptions &&
        ignoreIfExists == other.ignoreIfExists &&
        overwrite == other.overwrite;
  }

  @override
  int get hashCode => Object.hash(
        ignoreIfExists,
        overwrite,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters sent in notifications/requests for user-initiated creation of
/// files.
///
/// @since 3.16.0
class CreateFilesParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CreateFilesParams.canParse,
    CreateFilesParams.fromJson,
  );

  CreateFilesParams({
    required this.files,
  });
  static CreateFilesParams fromJson(Map<String, Object?> json) {
    final filesJson = json['files'];
    final files = (filesJson as List<Object?>)
        .map((item) => FileCreate.fromJson(item as Map<String, Object?>))
        .toList();
    return CreateFilesParams(
      files: files,
    );
  }

  /// An array of all files/folders created in this operation.
  final List<FileCreate> files;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('files');
      try {
        if (!obj.containsKey('files')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final files = obj['files'];
        if (files == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (files is! List<Object?> ||
            files.any((item) => !FileCreate.canParse(item, reporter))) {
          reporter.reportError('must be of type List<FileCreate>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CreateFilesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CreateFilesParams &&
        other.runtimeType == CreateFilesParams &&
        listEqual(files, other.files, (FileCreate a, FileCreate b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(files);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.14.0
class DeclarationClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DeclarationClientCapabilities.canParse,
    DeclarationClientCapabilities.fromJson,
  );

  DeclarationClientCapabilities({
    this.dynamicRegistration,
    this.linkSupport,
  });
  static DeclarationClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final linkSupportJson = json['linkSupport'];
    final linkSupport = linkSupportJson as bool?;
    return DeclarationClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      linkSupport: linkSupport,
    );
  }

  /// Whether declaration supports dynamic registration. If this is set to
  /// `true` the client supports the new `DeclarationRegistrationOptions` return
  /// value for the corresponding server capability as well.
  final bool? dynamicRegistration;

  /// The client supports additional metadata in the form of declaration links.
  final bool? linkSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (linkSupport != null) {
      result['linkSupport'] = linkSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        final linkSupport = obj['linkSupport'];
        if (linkSupport != null && linkSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DeclarationClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DeclarationClientCapabilities &&
        other.runtimeType == DeclarationClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        linkSupport == other.linkSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        linkSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DeclarationOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DeclarationOptions.canParse,
    DeclarationOptions.fromJson,
  );

  DeclarationOptions({
    this.workDoneProgress,
  });
  static DeclarationOptions fromJson(Map<String, Object?> json) {
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DeclarationOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DeclarationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DeclarationOptions &&
        other.runtimeType == DeclarationOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DeclarationParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DeclarationParams.canParse,
    DeclarationParams.fromJson,
  );

  DeclarationParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static DeclarationParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DeclarationParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DeclarationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DeclarationParams &&
        other.runtimeType == DeclarationParams &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DeclarationRegistrationOptions
    implements
        DeclarationOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DeclarationRegistrationOptions.canParse,
    DeclarationRegistrationOptions.fromJson,
  );

  DeclarationRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static DeclarationRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DeclarationRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DeclarationRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DeclarationRegistrationOptions &&
        other.runtimeType == DeclarationRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client Capabilities for a DefinitionRequest.
class DefinitionClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DefinitionClientCapabilities.canParse,
    DefinitionClientCapabilities.fromJson,
  );

  DefinitionClientCapabilities({
    this.dynamicRegistration,
    this.linkSupport,
  });
  static DefinitionClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final linkSupportJson = json['linkSupport'];
    final linkSupport = linkSupportJson as bool?;
    return DefinitionClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      linkSupport: linkSupport,
    );
  }

  /// Whether definition supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports additional metadata in the form of definition links.
  ///
  /// @since 3.14.0
  final bool? linkSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (linkSupport != null) {
      result['linkSupport'] = linkSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        final linkSupport = obj['linkSupport'];
        if (linkSupport != null && linkSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DefinitionClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DefinitionClientCapabilities &&
        other.runtimeType == DefinitionClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        linkSupport == other.linkSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        linkSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Server Capabilities for a DefinitionRequest.
class DefinitionOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DefinitionOptions.canParse,
    DefinitionOptions.fromJson,
  );

  DefinitionOptions({
    this.workDoneProgress,
  });
  static DefinitionOptions fromJson(Map<String, Object?> json) {
    if (DefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DefinitionOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DefinitionOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DefinitionOptions &&
        other.runtimeType == DefinitionOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a DefinitionRequest.
class DefinitionParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DefinitionParams.canParse,
    DefinitionParams.fromJson,
  );

  DefinitionParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static DefinitionParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DefinitionParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DefinitionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DefinitionParams &&
        other.runtimeType == DefinitionParams &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DefinitionRequest.
class DefinitionRegistrationOptions
    implements DefinitionOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DefinitionRegistrationOptions.canParse,
    DefinitionRegistrationOptions.fromJson,
  );

  DefinitionRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static DefinitionRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DefinitionRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DefinitionRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DefinitionRegistrationOptions &&
        other.runtimeType == DefinitionRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Delete file operation
class DeleteFile implements ResourceOperation, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DeleteFile.canParse,
    DeleteFile.fromJson,
  );

  DeleteFile({
    this.annotationId,
    this.kind = 'delete',
    this.options,
    required this.uri,
  }) {
    if (kind != 'delete') {
      throw 'kind may only be the literal \'delete\'';
    }
  }
  static DeleteFile fromJson(Map<String, Object?> json) {
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? DeleteFileOptions.fromJson(optionsJson as Map<String, Object?>)
        : null;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return DeleteFile(
      annotationId: annotationId,
      kind: kind,
      options: options,
      uri: uri,
    );
  }

  /// An optional annotation identifier describing the operation.
  ///
  /// @since 3.16.0
  @override
  final String? annotationId;

  /// A delete
  @override
  final String kind;

  /// Delete options.
  final DeleteFileOptions? options;

  /// The file to delete.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (annotationId != null) {
      result['annotationId'] = annotationId;
    }
    result['kind'] = kind;
    if (options != null) {
      result['options'] = options?.toJson();
    }
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('annotationId');
      try {
        final annotationId = obj['annotationId'];
        if (annotationId != null && annotationId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'delete') {
          reporter.reportError('must be the literal \'delete\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        final options = obj['options'];
        if (options != null && !DeleteFileOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type DeleteFileOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DeleteFile');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DeleteFile &&
        other.runtimeType == DeleteFile &&
        annotationId == other.annotationId &&
        kind == other.kind &&
        options == other.options &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        annotationId,
        kind,
        options,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Delete file options
class DeleteFileOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DeleteFileOptions.canParse,
    DeleteFileOptions.fromJson,
  );

  DeleteFileOptions({
    this.ignoreIfNotExists,
    this.recursive,
  });
  static DeleteFileOptions fromJson(Map<String, Object?> json) {
    final ignoreIfNotExistsJson = json['ignoreIfNotExists'];
    final ignoreIfNotExists = ignoreIfNotExistsJson as bool?;
    final recursiveJson = json['recursive'];
    final recursive = recursiveJson as bool?;
    return DeleteFileOptions(
      ignoreIfNotExists: ignoreIfNotExists,
      recursive: recursive,
    );
  }

  /// Ignore the operation if the file doesn't exist.
  final bool? ignoreIfNotExists;

  /// Delete the content recursively if a folder is denoted.
  final bool? recursive;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (ignoreIfNotExists != null) {
      result['ignoreIfNotExists'] = ignoreIfNotExists;
    }
    if (recursive != null) {
      result['recursive'] = recursive;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ignoreIfNotExists');
      try {
        final ignoreIfNotExists = obj['ignoreIfNotExists'];
        if (ignoreIfNotExists != null && ignoreIfNotExists is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('recursive');
      try {
        final recursive = obj['recursive'];
        if (recursive != null && recursive is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DeleteFileOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DeleteFileOptions &&
        other.runtimeType == DeleteFileOptions &&
        ignoreIfNotExists == other.ignoreIfNotExists &&
        recursive == other.recursive;
  }

  @override
  int get hashCode => Object.hash(
        ignoreIfNotExists,
        recursive,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters sent in notifications/requests for user-initiated deletes of
/// files.
///
/// @since 3.16.0
class DeleteFilesParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DeleteFilesParams.canParse,
    DeleteFilesParams.fromJson,
  );

  DeleteFilesParams({
    required this.files,
  });
  static DeleteFilesParams fromJson(Map<String, Object?> json) {
    final filesJson = json['files'];
    final files = (filesJson as List<Object?>)
        .map((item) => FileDelete.fromJson(item as Map<String, Object?>))
        .toList();
    return DeleteFilesParams(
      files: files,
    );
  }

  /// An array of all files/folders deleted in this operation.
  final List<FileDelete> files;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('files');
      try {
        if (!obj.containsKey('files')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final files = obj['files'];
        if (files == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (files is! List<Object?> ||
            files.any((item) => !FileDelete.canParse(item, reporter))) {
          reporter.reportError('must be of type List<FileDelete>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DeleteFilesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DeleteFilesParams &&
        other.runtimeType == DeleteFilesParams &&
        listEqual(files, other.files, (FileDelete a, FileDelete b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(files);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a diagnostic, such as a compiler error or warning. Diagnostic
/// objects are only valid in the scope of a resource.
class Diagnostic implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Diagnostic.canParse,
    Diagnostic.fromJson,
  );

  Diagnostic({
    this.code,
    this.codeDescription,
    this.data,
    required this.message,
    required this.range,
    this.relatedInformation,
    this.severity,
    this.source,
    this.tags,
  });
  static Diagnostic fromJson(Map<String, Object?> json) {
    final codeJson = json['code'];
    final code = codeJson as String?;
    final codeDescriptionJson = json['codeDescription'];
    final codeDescription = codeDescriptionJson != null
        ? CodeDescription.fromJson(codeDescriptionJson as Map<String, Object?>)
        : null;
    final dataJson = json['data'];
    final data = dataJson;
    final messageJson = json['message'];
    final message = messageJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final relatedInformationJson = json['relatedInformation'];
    final relatedInformation = (relatedInformationJson as List<Object?>?)
        ?.map((item) =>
            DiagnosticRelatedInformation.fromJson(item as Map<String, Object?>))
        .toList();
    final severityJson = json['severity'];
    final severity = severityJson != null
        ? DiagnosticSeverity.fromJson(severityJson as int)
        : null;
    final sourceJson = json['source'];
    final source = sourceJson as String?;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => DiagnosticTag.fromJson(item as int))
        .toList();
    return Diagnostic(
      code: code,
      codeDescription: codeDescription,
      data: data,
      message: message,
      range: range,
      relatedInformation: relatedInformation,
      severity: severity,
      source: source,
      tags: tags,
    );
  }

  /// The diagnostic's code, which usually appear in the user interface.
  final String? code;

  /// An optional property to describe the error code. Requires the code field
  /// (above) to be present/not null.
  ///
  /// @since 3.16.0
  final CodeDescription? codeDescription;

  /// A data entry field that is preserved between a
  /// `textDocument/publishDiagnostics` notification and
  /// `textDocument/codeAction` request.
  ///
  /// @since 3.16.0
  final Object? data;

  /// The diagnostic's message. It usually appears in the user interface
  final String message;

  /// The range at which the message applies
  final Range range;

  /// An array of related diagnostic information, e.g. when symbol-names within
  /// a scope collide all definitions can be marked via this property.
  final List<DiagnosticRelatedInformation>? relatedInformation;

  /// The diagnostic's severity. Can be omitted. If omitted it is up to the
  /// client to interpret diagnostics as error, warning, info or hint.
  final DiagnosticSeverity? severity;

  /// A human-readable string describing the source of this diagnostic, e.g.
  /// 'typescript' or 'super lint'. It usually appears in the user interface.
  final String? source;

  /// Additional metadata about the diagnostic.
  ///
  /// @since 3.15.0
  final List<DiagnosticTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (code != null) {
      result['code'] = code;
    }
    if (codeDescription != null) {
      result['codeDescription'] = codeDescription?.toJson();
    }
    if (data != null) {
      result['data'] = data;
    }
    result['message'] = message;
    result['range'] = range.toJson();
    if (relatedInformation != null) {
      result['relatedInformation'] =
          relatedInformation?.map((item) => item.toJson()).toList();
    }
    if (severity != null) {
      result['severity'] = severity?.toJson();
    }
    if (source != null) {
      result['source'] = source;
    }
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('code');
      try {
        final code = obj['code'];
        if (code != null && code is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeDescription');
      try {
        final codeDescription = obj['codeDescription'];
        if (codeDescription != null &&
            !CodeDescription.canParse(codeDescription, reporter)) {
          reporter.reportError('must be of type CodeDescription');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('relatedInformation');
      try {
        final relatedInformation = obj['relatedInformation'];
        if (relatedInformation != null &&
            (relatedInformation is! List<Object?> ||
                relatedInformation.any((item) =>
                    !DiagnosticRelatedInformation.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<DiagnosticRelatedInformation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('severity');
      try {
        final severity = obj['severity'];
        if (severity != null &&
            !DiagnosticSeverity.canParse(severity, reporter)) {
          reporter.reportError('must be of type DiagnosticSeverity');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('source');
      try {
        final source = obj['source'];
        if (source != null && source is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !DiagnosticTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<DiagnosticTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Diagnostic');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Diagnostic &&
        other.runtimeType == Diagnostic &&
        code == other.code &&
        codeDescription == other.codeDescription &&
        data == other.data &&
        message == other.message &&
        range == other.range &&
        listEqual(
            relatedInformation,
            other.relatedInformation,
            (DiagnosticRelatedInformation a, DiagnosticRelatedInformation b) =>
                a == b) &&
        severity == other.severity &&
        source == other.source &&
        listEqual(
            tags, other.tags, (DiagnosticTag a, DiagnosticTag b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        code,
        codeDescription,
        data,
        message,
        range,
        lspHashCode(relatedInformation),
        severity,
        source,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to diagnostic pull requests.
///
/// @since 3.17.0
class DiagnosticClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DiagnosticClientCapabilities.canParse,
    DiagnosticClientCapabilities.fromJson,
  );

  DiagnosticClientCapabilities({
    this.dynamicRegistration,
    this.relatedDocumentSupport,
  });
  static DiagnosticClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final relatedDocumentSupportJson = json['relatedDocumentSupport'];
    final relatedDocumentSupport = relatedDocumentSupportJson as bool?;
    return DiagnosticClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      relatedDocumentSupport: relatedDocumentSupport,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  /// Whether the clients supports related documents for document diagnostic
  /// pulls.
  final bool? relatedDocumentSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (relatedDocumentSupport != null) {
      result['relatedDocumentSupport'] = relatedDocumentSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('relatedDocumentSupport');
      try {
        final relatedDocumentSupport = obj['relatedDocumentSupport'];
        if (relatedDocumentSupport != null && relatedDocumentSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DiagnosticClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DiagnosticClientCapabilities &&
        other.runtimeType == DiagnosticClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        relatedDocumentSupport == other.relatedDocumentSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        relatedDocumentSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Diagnostic options.
///
/// @since 3.17.0
class DiagnosticOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DiagnosticOptions.canParse,
    DiagnosticOptions.fromJson,
  );

  DiagnosticOptions({
    this.identifier,
    required this.interFileDependencies,
    this.workDoneProgress,
    required this.workspaceDiagnostics,
  });
  static DiagnosticOptions fromJson(Map<String, Object?> json) {
    if (DiagnosticRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticRegistrationOptions.fromJson(json);
    }
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String?;
    final interFileDependenciesJson = json['interFileDependencies'];
    final interFileDependencies = interFileDependenciesJson as bool;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final workspaceDiagnosticsJson = json['workspaceDiagnostics'];
    final workspaceDiagnostics = workspaceDiagnosticsJson as bool;
    return DiagnosticOptions(
      identifier: identifier,
      interFileDependencies: interFileDependencies,
      workDoneProgress: workDoneProgress,
      workspaceDiagnostics: workspaceDiagnostics,
    );
  }

  /// An optional identifier under which the diagnostics are managed by the
  /// client.
  final String? identifier;

  /// Whether the language has inter file dependencies meaning that editing code
  /// in one file can result in a different diagnostic set in another file.
  /// Inter file dependencies are common for most programming languages and
  /// typically uncommon for linters.
  final bool interFileDependencies;
  @override
  final bool? workDoneProgress;

  /// The server provides support for workspace diagnostics as well.
  final bool workspaceDiagnostics;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (identifier != null) {
      result['identifier'] = identifier;
    }
    result['interFileDependencies'] = interFileDependencies;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    result['workspaceDiagnostics'] = workspaceDiagnostics;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('identifier');
      try {
        final identifier = obj['identifier'];
        if (identifier != null && identifier is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('interFileDependencies');
      try {
        if (!obj.containsKey('interFileDependencies')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final interFileDependencies = obj['interFileDependencies'];
        if (interFileDependencies == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (interFileDependencies is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceDiagnostics');
      try {
        if (!obj.containsKey('workspaceDiagnostics')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final workspaceDiagnostics = obj['workspaceDiagnostics'];
        if (workspaceDiagnostics == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (workspaceDiagnostics is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DiagnosticOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DiagnosticOptions &&
        other.runtimeType == DiagnosticOptions &&
        identifier == other.identifier &&
        interFileDependencies == other.interFileDependencies &&
        workDoneProgress == other.workDoneProgress &&
        workspaceDiagnostics == other.workspaceDiagnostics;
  }

  @override
  int get hashCode => Object.hash(
        identifier,
        interFileDependencies,
        workDoneProgress,
        workspaceDiagnostics,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Diagnostic registration options.
///
/// @since 3.17.0
class DiagnosticRegistrationOptions
    implements
        DiagnosticOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DiagnosticRegistrationOptions.canParse,
    DiagnosticRegistrationOptions.fromJson,
  );

  DiagnosticRegistrationOptions({
    this.documentSelector,
    this.id,
    this.identifier,
    required this.interFileDependencies,
    this.workDoneProgress,
    required this.workspaceDiagnostics,
  });
  static DiagnosticRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String?;
    final interFileDependenciesJson = json['interFileDependencies'];
    final interFileDependencies = interFileDependenciesJson as bool;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final workspaceDiagnosticsJson = json['workspaceDiagnostics'];
    final workspaceDiagnostics = workspaceDiagnosticsJson as bool;
    return DiagnosticRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      identifier: identifier,
      interFileDependencies: interFileDependencies,
      workDoneProgress: workDoneProgress,
      workspaceDiagnostics: workspaceDiagnostics,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// An optional identifier under which the diagnostics are managed by the
  /// client.
  @override
  final String? identifier;

  /// Whether the language has inter file dependencies meaning that editing code
  /// in one file can result in a different diagnostic set in another file.
  /// Inter file dependencies are common for most programming languages and
  /// typically uncommon for linters.
  @override
  final bool interFileDependencies;
  @override
  final bool? workDoneProgress;

  /// The server provides support for workspace diagnostics as well.
  @override
  final bool workspaceDiagnostics;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (identifier != null) {
      result['identifier'] = identifier;
    }
    result['interFileDependencies'] = interFileDependencies;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    result['workspaceDiagnostics'] = workspaceDiagnostics;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('identifier');
      try {
        final identifier = obj['identifier'];
        if (identifier != null && identifier is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('interFileDependencies');
      try {
        if (!obj.containsKey('interFileDependencies')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final interFileDependencies = obj['interFileDependencies'];
        if (interFileDependencies == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (interFileDependencies is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceDiagnostics');
      try {
        if (!obj.containsKey('workspaceDiagnostics')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final workspaceDiagnostics = obj['workspaceDiagnostics'];
        if (workspaceDiagnostics == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (workspaceDiagnostics is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DiagnosticRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DiagnosticRegistrationOptions &&
        other.runtimeType == DiagnosticRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        identifier == other.identifier &&
        interFileDependencies == other.interFileDependencies &&
        workDoneProgress == other.workDoneProgress &&
        workspaceDiagnostics == other.workspaceDiagnostics;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        identifier,
        interFileDependencies,
        workDoneProgress,
        workspaceDiagnostics,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a related message and source code location for a diagnostic. This
/// should be used to point to code locations that cause or related to a
/// diagnostics, e.g when duplicating a symbol in a scope.
class DiagnosticRelatedInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DiagnosticRelatedInformation.canParse,
    DiagnosticRelatedInformation.fromJson,
  );

  DiagnosticRelatedInformation({
    required this.location,
    required this.message,
  });
  static DiagnosticRelatedInformation fromJson(Map<String, Object?> json) {
    final locationJson = json['location'];
    final location = Location.fromJson(locationJson as Map<String, Object?>);
    final messageJson = json['message'];
    final message = messageJson as String;
    return DiagnosticRelatedInformation(
      location: location,
      message: message,
    );
  }

  /// The location of this related diagnostic information.
  final Location location;

  /// The message of this related diagnostic information.
  final String message;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['location'] = location.toJson();
    result['message'] = message;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('location');
      try {
        if (!obj.containsKey('location')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final location = obj['location'];
        if (location == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Location.canParse(location, reporter)) {
          reporter.reportError('must be of type Location');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DiagnosticRelatedInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DiagnosticRelatedInformation &&
        other.runtimeType == DiagnosticRelatedInformation &&
        location == other.location &&
        message == other.message;
  }

  @override
  int get hashCode => Object.hash(
        location,
        message,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Cancellation data returned from a diagnostic request.
///
/// @since 3.17.0
class DiagnosticServerCancellationData implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DiagnosticServerCancellationData.canParse,
    DiagnosticServerCancellationData.fromJson,
  );

  DiagnosticServerCancellationData({
    required this.retriggerRequest,
  });
  static DiagnosticServerCancellationData fromJson(Map<String, Object?> json) {
    final retriggerRequestJson = json['retriggerRequest'];
    final retriggerRequest = retriggerRequestJson as bool;
    return DiagnosticServerCancellationData(
      retriggerRequest: retriggerRequest,
    );
  }

  final bool retriggerRequest;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('retriggerRequest');
      try {
        if (!obj.containsKey('retriggerRequest')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final retriggerRequest = obj['retriggerRequest'];
        if (retriggerRequest == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (retriggerRequest is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DiagnosticServerCancellationData');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DiagnosticServerCancellationData &&
        other.runtimeType == DiagnosticServerCancellationData &&
        retriggerRequest == other.retriggerRequest;
  }

  @override
  int get hashCode => retriggerRequest.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The diagnostic's severity.
class DiagnosticSeverity implements ToJsonable {
  const DiagnosticSeverity(this._value);
  const DiagnosticSeverity.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Reports an error.
  static const Error = DiagnosticSeverity(1);

  /// Reports a hint.
  static const Hint = DiagnosticSeverity(4);

  /// Reports an information.
  static const Information = DiagnosticSeverity(3);

  /// Reports a warning.
  static const Warning = DiagnosticSeverity(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is DiagnosticSeverity && other._value == _value;
}

/// The diagnostic tags.
///
/// @since 3.15.0
class DiagnosticTag implements ToJsonable {
  const DiagnosticTag(this._value);
  const DiagnosticTag.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Deprecated or obsolete code.
  ///
  /// Clients are allowed to rendered diagnostics with this tag strike through.
  static const Deprecated = DiagnosticTag(2);

  /// Unused or unnecessary code.
  ///
  /// Clients are allowed to render diagnostics with this tag faded out instead
  /// of having an error squiggle.
  static const Unnecessary = DiagnosticTag(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is DiagnosticTag && other._value == _value;
}

/// Workspace client capabilities specific to diagnostic pull requests.
///
/// @since 3.17.0
class DiagnosticWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DiagnosticWorkspaceClientCapabilities.canParse,
    DiagnosticWorkspaceClientCapabilities.fromJson,
  );

  DiagnosticWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static DiagnosticWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return DiagnosticWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// pulled diagnostics currently shown. It should be used with absolute care
  /// and is useful for situation where a server for example detects a project
  /// wide change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('refreshSupport');
      try {
        final refreshSupport = obj['refreshSupport'];
        if (refreshSupport != null && refreshSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DiagnosticWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DiagnosticWorkspaceClientCapabilities &&
        other.runtimeType == DiagnosticWorkspaceClientCapabilities &&
        refreshSupport == other.refreshSupport;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DidChangeConfigurationClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeConfigurationClientCapabilities.canParse,
    DidChangeConfigurationClientCapabilities.fromJson,
  );

  DidChangeConfigurationClientCapabilities({
    this.dynamicRegistration,
  });
  static DidChangeConfigurationClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DidChangeConfigurationClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Did change configuration notification supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DidChangeConfigurationClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidChangeConfigurationClientCapabilities &&
        other.runtimeType == DidChangeConfigurationClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a change configuration notification.
class DidChangeConfigurationParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeConfigurationParams.canParse,
    DidChangeConfigurationParams.fromJson,
  );

  DidChangeConfigurationParams({
    this.settings,
  });
  static DidChangeConfigurationParams fromJson(Map<String, Object?> json) {
    final settingsJson = json['settings'];
    final settings = settingsJson;
    return DidChangeConfigurationParams(
      settings: settings,
    );
  }

  /// The actual changed settings
  final Object? settings;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError('must be of type DidChangeConfigurationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidChangeConfigurationParams &&
        other.runtimeType == DidChangeConfigurationParams &&
        settings == other.settings;
  }

  @override
  int get hashCode => settings.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The params sent in a change notebook document notification.
///
/// @since 3.17.0
class DidChangeNotebookDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeNotebookDocumentParams.canParse,
    DidChangeNotebookDocumentParams.fromJson,
  );

  DidChangeNotebookDocumentParams({
    required this.change,
    required this.notebookDocument,
  });
  static DidChangeNotebookDocumentParams fromJson(Map<String, Object?> json) {
    final changeJson = json['change'];
    final change = NotebookDocumentChangeEvent.fromJson(
        changeJson as Map<String, Object?>);
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument = VersionedNotebookDocumentIdentifier.fromJson(
        notebookDocumentJson as Map<String, Object?>);
    return DidChangeNotebookDocumentParams(
      change: change,
      notebookDocument: notebookDocument,
    );
  }

  /// The actual changes to the notebook document.
  ///
  /// The changes describe single state changes to the notebook document. So if
  /// there are two changes c1 (at array index 0) and c2 (at array index 1) for
  /// a notebook in state S then c1 moves the notebook from S to S' and c2 from
  /// S' to S''. So c1 is computed on the state S and c2 is computed on the
  /// state S'.
  ///
  /// To mirror the content of a notebook using change events use the following
  /// approach:
  /// - start with the same initial content
  /// - apply the 'notebookDocument/didChange' notifications in the order you
  /// receive them.
  /// - apply the `NotebookChangeEvent`s in a single notification in the order
  ///   you receive them.
  final NotebookDocumentChangeEvent change;

  /// The notebook document that did change. The version number points to the
  /// version after all provided changes have been applied. If only the text
  /// document content of a cell changes the notebook version doesn't
  /// necessarily have to change.
  final VersionedNotebookDocumentIdentifier notebookDocument;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('change');
      try {
        if (!obj.containsKey('change')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final change = obj['change'];
        if (change == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocumentChangeEvent.canParse(change, reporter)) {
          reporter.reportError('must be of type NotebookDocumentChangeEvent');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookDocument');
      try {
        if (!obj.containsKey('notebookDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookDocument = obj['notebookDocument'];
        if (notebookDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!VersionedNotebookDocumentIdentifier.canParse(
            notebookDocument, reporter)) {
          reporter.reportError(
              'must be of type VersionedNotebookDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidChangeNotebookDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidChangeNotebookDocumentParams &&
        other.runtimeType == DidChangeNotebookDocumentParams &&
        change == other.change &&
        notebookDocument == other.notebookDocument;
  }

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

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The change text document notification's parameters.
class DidChangeTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeTextDocumentParams.canParse,
    DidChangeTextDocumentParams.fromJson,
  );

  DidChangeTextDocumentParams({
    required this.contentChanges,
    required this.textDocument,
  });
  static DidChangeTextDocumentParams fromJson(Map<String, Object?> json) {
    final contentChangesJson = json['contentChanges'];
    final contentChanges = (contentChangesJson as List<Object?>)
        .map((item) => TextDocumentContentChangeEvent1.canParse(
                item, nullLspJsonReporter)
            ? Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>.t1(
                TextDocumentContentChangeEvent1.fromJson(
                    item as Map<String, Object?>))
            : (TextDocumentContentChangeEvent2.canParse(item, nullLspJsonReporter)
                ? Either2<TextDocumentContentChangeEvent1,
                        TextDocumentContentChangeEvent2>.t2(
                    TextDocumentContentChangeEvent2.fromJson(item as Map<String, Object?>))
                : (throw '''$item was not one of (TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2)''')))
        .toList();
    final textDocumentJson = json['textDocument'];
    final textDocument = VersionedTextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return DidChangeTextDocumentParams(
      contentChanges: contentChanges,
      textDocument: textDocument,
    );
  }

  /// The actual content changes. The content changes describe single state
  /// changes to the document. So if there are two content changes c1 (at array
  /// index 0) and c2 (at array index 1) for a document in state S then c1 moves
  /// the document from S to S' and c2 from S' to S''. So c1 is computed on the
  /// state S and c2 is computed on the state S'.
  ///
  /// To mirror the content of a document using change events use the following
  /// approach:
  /// - start with the same initial content
  /// - apply the 'textDocument/didChange' notifications in the order you
  /// receive them.
  /// - apply the `TextDocumentContentChangeEvent`s in a single notification in
  /// the order
  ///   you receive them.
  final List<
      Either2<TextDocumentContentChangeEvent1,
          TextDocumentContentChangeEvent2>> contentChanges;

  /// The document that did change. The version number points to the version
  /// after all provided content changes have been applied.
  final VersionedTextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['contentChanges'] = contentChanges;
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('contentChanges');
      try {
        if (!obj.containsKey('contentChanges')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final contentChanges = obj['contentChanges'];
        if (contentChanges == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (contentChanges is! List<Object?> ||
            contentChanges.any((item) =>
                !TextDocumentContentChangeEvent1.canParse(item, reporter) &&
                !TextDocumentContentChangeEvent2.canParse(item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!VersionedTextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter
              .reportError('must be of type VersionedTextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidChangeTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidChangeTextDocumentParams &&
        other.runtimeType == DidChangeTextDocumentParams &&
        listEqual(
            contentChanges,
            other.contentChanges,
            (Either2<TextDocumentContentChangeEvent1,
                            TextDocumentContentChangeEvent2>
                        a,
                    Either2<TextDocumentContentChangeEvent1,
                            TextDocumentContentChangeEvent2>
                        b) =>
                a == b) &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(contentChanges),
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DidChangeWatchedFilesClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeWatchedFilesClientCapabilities.canParse,
    DidChangeWatchedFilesClientCapabilities.fromJson,
  );

  DidChangeWatchedFilesClientCapabilities({
    this.dynamicRegistration,
    this.relativePatternSupport,
  });
  static DidChangeWatchedFilesClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final relativePatternSupportJson = json['relativePatternSupport'];
    final relativePatternSupport = relativePatternSupportJson as bool?;
    return DidChangeWatchedFilesClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      relativePatternSupport: relativePatternSupport,
    );
  }

  /// Did change watched files notification supports dynamic registration.
  /// Please note that the current protocol doesn't support static configuration
  /// for file changes from the server side.
  final bool? dynamicRegistration;

  /// Whether the client has support for {@link  RelativePattern relative
  /// pattern}
  /// or not.
  ///
  /// @since 3.17.0
  final bool? relativePatternSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (relativePatternSupport != null) {
      result['relativePatternSupport'] = relativePatternSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('relativePatternSupport');
      try {
        final relativePatternSupport = obj['relativePatternSupport'];
        if (relativePatternSupport != null && relativePatternSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DidChangeWatchedFilesClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidChangeWatchedFilesClientCapabilities &&
        other.runtimeType == DidChangeWatchedFilesClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        relativePatternSupport == other.relativePatternSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        relativePatternSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The watched files change notification's parameters.
class DidChangeWatchedFilesParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeWatchedFilesParams.canParse,
    DidChangeWatchedFilesParams.fromJson,
  );

  DidChangeWatchedFilesParams({
    required this.changes,
  });
  static DidChangeWatchedFilesParams fromJson(Map<String, Object?> json) {
    final changesJson = json['changes'];
    final changes = (changesJson as List<Object?>)
        .map((item) => FileEvent.fromJson(item as Map<String, Object?>))
        .toList();
    return DidChangeWatchedFilesParams(
      changes: changes,
    );
  }

  /// The actual file events.
  final List<FileEvent> changes;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['changes'] = changes.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('changes');
      try {
        if (!obj.containsKey('changes')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final changes = obj['changes'];
        if (changes == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (changes is! List<Object?> ||
            changes.any((item) => !FileEvent.canParse(item, reporter))) {
          reporter.reportError('must be of type List<FileEvent>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidChangeWatchedFilesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidChangeWatchedFilesParams &&
        other.runtimeType == DidChangeWatchedFilesParams &&
        listEqual(changes, other.changes, (FileEvent a, FileEvent b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(changes);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Describe options to be used when registered for text document change events.
class DidChangeWatchedFilesRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeWatchedFilesRegistrationOptions.canParse,
    DidChangeWatchedFilesRegistrationOptions.fromJson,
  );

  DidChangeWatchedFilesRegistrationOptions({
    required this.watchers,
  });
  static DidChangeWatchedFilesRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final watchersJson = json['watchers'];
    final watchers = (watchersJson as List<Object?>)
        .map((item) => FileSystemWatcher.fromJson(item as Map<String, Object?>))
        .toList();
    return DidChangeWatchedFilesRegistrationOptions(
      watchers: watchers,
    );
  }

  /// The watchers to register.
  final List<FileSystemWatcher> watchers;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['watchers'] = watchers.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('watchers');
      try {
        if (!obj.containsKey('watchers')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final watchers = obj['watchers'];
        if (watchers == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (watchers is! List<Object?> ||
            watchers
                .any((item) => !FileSystemWatcher.canParse(item, reporter))) {
          reporter.reportError('must be of type List<FileSystemWatcher>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DidChangeWatchedFilesRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidChangeWatchedFilesRegistrationOptions &&
        other.runtimeType == DidChangeWatchedFilesRegistrationOptions &&
        listEqual(watchers, other.watchers,
            (FileSystemWatcher a, FileSystemWatcher b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(watchers);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a `workspace/didChangeWorkspaceFolders` notification.
class DidChangeWorkspaceFoldersParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeWorkspaceFoldersParams.canParse,
    DidChangeWorkspaceFoldersParams.fromJson,
  );

  DidChangeWorkspaceFoldersParams({
    required this.event,
  });
  static DidChangeWorkspaceFoldersParams fromJson(Map<String, Object?> json) {
    final eventJson = json['event'];
    final event =
        WorkspaceFoldersChangeEvent.fromJson(eventJson as Map<String, Object?>);
    return DidChangeWorkspaceFoldersParams(
      event: event,
    );
  }

  /// The actual workspace folder change event.
  final WorkspaceFoldersChangeEvent event;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('event');
      try {
        if (!obj.containsKey('event')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final event = obj['event'];
        if (event == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!WorkspaceFoldersChangeEvent.canParse(event, reporter)) {
          reporter.reportError('must be of type WorkspaceFoldersChangeEvent');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidChangeWorkspaceFoldersParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidChangeWorkspaceFoldersParams &&
        other.runtimeType == DidChangeWorkspaceFoldersParams &&
        event == other.event;
  }

  @override
  int get hashCode => event.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The params sent in a close notebook document notification.
///
/// @since 3.17.0
class DidCloseNotebookDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidCloseNotebookDocumentParams.canParse,
    DidCloseNotebookDocumentParams.fromJson,
  );

  DidCloseNotebookDocumentParams({
    required this.cellTextDocuments,
    required this.notebookDocument,
  });
  static DidCloseNotebookDocumentParams fromJson(Map<String, Object?> json) {
    final cellTextDocumentsJson = json['cellTextDocuments'];
    final cellTextDocuments = (cellTextDocumentsJson as List<Object?>)
        .map((item) =>
            TextDocumentIdentifier.fromJson(item as Map<String, Object?>))
        .toList();
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument = NotebookDocumentIdentifier.fromJson(
        notebookDocumentJson as Map<String, Object?>);
    return DidCloseNotebookDocumentParams(
      cellTextDocuments: cellTextDocuments,
      notebookDocument: notebookDocument,
    );
  }

  /// The text documents that represent the content of a notebook cell that got
  /// closed.
  final List<TextDocumentIdentifier> cellTextDocuments;

  /// The notebook document that got closed.
  final NotebookDocumentIdentifier notebookDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cellTextDocuments'] =
        cellTextDocuments.map((item) => item.toJson()).toList();
    result['notebookDocument'] = notebookDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cellTextDocuments');
      try {
        if (!obj.containsKey('cellTextDocuments')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final cellTextDocuments = obj['cellTextDocuments'];
        if (cellTextDocuments == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (cellTextDocuments is! List<Object?> ||
            cellTextDocuments.any(
                (item) => !TextDocumentIdentifier.canParse(item, reporter))) {
          reporter.reportError('must be of type List<TextDocumentIdentifier>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookDocument');
      try {
        if (!obj.containsKey('notebookDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookDocument = obj['notebookDocument'];
        if (notebookDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocumentIdentifier.canParse(notebookDocument, reporter)) {
          reporter.reportError('must be of type NotebookDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidCloseNotebookDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidCloseNotebookDocumentParams &&
        other.runtimeType == DidCloseNotebookDocumentParams &&
        listEqual(cellTextDocuments, other.cellTextDocuments,
            (TextDocumentIdentifier a, TextDocumentIdentifier b) => a == b) &&
        notebookDocument == other.notebookDocument;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cellTextDocuments),
        notebookDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters sent in a close text document notification
class DidCloseTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidCloseTextDocumentParams.canParse,
    DidCloseTextDocumentParams.fromJson,
  );

  DidCloseTextDocumentParams({
    required this.textDocument,
  });
  static DidCloseTextDocumentParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return DidCloseTextDocumentParams(
      textDocument: textDocument,
    );
  }

  /// The document that was closed.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidCloseTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidCloseTextDocumentParams &&
        other.runtimeType == DidCloseTextDocumentParams &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => textDocument.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The params sent in an open notebook document notification.
///
/// @since 3.17.0
class DidOpenNotebookDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidOpenNotebookDocumentParams.canParse,
    DidOpenNotebookDocumentParams.fromJson,
  );

  DidOpenNotebookDocumentParams({
    required this.cellTextDocuments,
    required this.notebookDocument,
  });
  static DidOpenNotebookDocumentParams fromJson(Map<String, Object?> json) {
    final cellTextDocumentsJson = json['cellTextDocuments'];
    final cellTextDocuments = (cellTextDocumentsJson as List<Object?>)
        .map((item) => TextDocumentItem.fromJson(item as Map<String, Object?>))
        .toList();
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument =
        NotebookDocument.fromJson(notebookDocumentJson as Map<String, Object?>);
    return DidOpenNotebookDocumentParams(
      cellTextDocuments: cellTextDocuments,
      notebookDocument: notebookDocument,
    );
  }

  /// The text documents that represent the content of a notebook cell.
  final List<TextDocumentItem> cellTextDocuments;

  /// The notebook document that got opened.
  final NotebookDocument notebookDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cellTextDocuments'] =
        cellTextDocuments.map((item) => item.toJson()).toList();
    result['notebookDocument'] = notebookDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cellTextDocuments');
      try {
        if (!obj.containsKey('cellTextDocuments')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final cellTextDocuments = obj['cellTextDocuments'];
        if (cellTextDocuments == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (cellTextDocuments is! List<Object?> ||
            cellTextDocuments
                .any((item) => !TextDocumentItem.canParse(item, reporter))) {
          reporter.reportError('must be of type List<TextDocumentItem>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookDocument');
      try {
        if (!obj.containsKey('notebookDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookDocument = obj['notebookDocument'];
        if (notebookDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocument.canParse(notebookDocument, reporter)) {
          reporter.reportError('must be of type NotebookDocument');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidOpenNotebookDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidOpenNotebookDocumentParams &&
        other.runtimeType == DidOpenNotebookDocumentParams &&
        listEqual(cellTextDocuments, other.cellTextDocuments,
            (TextDocumentItem a, TextDocumentItem b) => a == b) &&
        notebookDocument == other.notebookDocument;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cellTextDocuments),
        notebookDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters sent in an open text document notification
class DidOpenTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidOpenTextDocumentParams.canParse,
    DidOpenTextDocumentParams.fromJson,
  );

  DidOpenTextDocumentParams({
    required this.textDocument,
  });
  static DidOpenTextDocumentParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument =
        TextDocumentItem.fromJson(textDocumentJson as Map<String, Object?>);
    return DidOpenTextDocumentParams(
      textDocument: textDocument,
    );
  }

  /// The document that was opened.
  final TextDocumentItem textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentItem.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidOpenTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidOpenTextDocumentParams &&
        other.runtimeType == DidOpenTextDocumentParams &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => textDocument.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The params sent in a save notebook document notification.
///
/// @since 3.17.0
class DidSaveNotebookDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidSaveNotebookDocumentParams.canParse,
    DidSaveNotebookDocumentParams.fromJson,
  );

  DidSaveNotebookDocumentParams({
    required this.notebookDocument,
  });
  static DidSaveNotebookDocumentParams fromJson(Map<String, Object?> json) {
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument = NotebookDocumentIdentifier.fromJson(
        notebookDocumentJson as Map<String, Object?>);
    return DidSaveNotebookDocumentParams(
      notebookDocument: notebookDocument,
    );
  }

  /// The notebook document that got saved.
  final NotebookDocumentIdentifier notebookDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['notebookDocument'] = notebookDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookDocument');
      try {
        if (!obj.containsKey('notebookDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookDocument = obj['notebookDocument'];
        if (notebookDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocumentIdentifier.canParse(notebookDocument, reporter)) {
          reporter.reportError('must be of type NotebookDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidSaveNotebookDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidSaveNotebookDocumentParams &&
        other.runtimeType == DidSaveNotebookDocumentParams &&
        notebookDocument == other.notebookDocument;
  }

  @override
  int get hashCode => notebookDocument.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters sent in a save text document notification
class DidSaveTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidSaveTextDocumentParams.canParse,
    DidSaveTextDocumentParams.fromJson,
  );

  DidSaveTextDocumentParams({
    this.text,
    required this.textDocument,
  });
  static DidSaveTextDocumentParams fromJson(Map<String, Object?> json) {
    final textJson = json['text'];
    final text = textJson as String?;
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return DidSaveTextDocumentParams(
      text: text,
      textDocument: textDocument,
    );
  }

  /// Optional the content when saved. Depends on the includeText value when the
  /// save notification was requested.
  final String? text;

  /// The document that was saved.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (text != null) {
      result['text'] = text;
    }
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('text');
      try {
        final text = obj['text'];
        if (text != null && text is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DidSaveTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidSaveTextDocumentParams &&
        other.runtimeType == DidSaveTextDocumentParams &&
        text == other.text &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        text,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentColorClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentColorClientCapabilities.canParse,
    DocumentColorClientCapabilities.fromJson,
  );

  DocumentColorClientCapabilities({
    this.dynamicRegistration,
  });
  static DocumentColorClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DocumentColorClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `DocumentColorRegistrationOptions`
  /// return value for the corresponding server capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentColorClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentColorClientCapabilities &&
        other.runtimeType == DocumentColorClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentColorOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentColorOptions.canParse,
    DocumentColorOptions.fromJson,
  );

  DocumentColorOptions({
    this.workDoneProgress,
  });
  static DocumentColorOptions fromJson(Map<String, Object?> json) {
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentColorOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentColorOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentColorOptions &&
        other.runtimeType == DocumentColorOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a DocumentColorRequest.
class DocumentColorParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentColorParams.canParse,
    DocumentColorParams.fromJson,
  );

  DocumentColorParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentColorParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentColorParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentColorParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentColorParams &&
        other.runtimeType == DocumentColorParams &&
        partialResultToken == other.partialResultToken &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentColorRegistrationOptions
    implements
        DocumentColorOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentColorRegistrationOptions.canParse,
    DocumentColorRegistrationOptions.fromJson,
  );

  DocumentColorRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static DocumentColorRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentColorRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentColorRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentColorRegistrationOptions &&
        other.runtimeType == DocumentColorRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters of the document diagnostic request.
///
/// @since 3.17.0
class DocumentDiagnosticParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentDiagnosticParams.canParse,
    DocumentDiagnosticParams.fromJson,
  );

  DocumentDiagnosticParams({
    this.identifier,
    this.partialResultToken,
    this.previousResultId,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentDiagnosticParams fromJson(Map<String, Object?> json) {
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String?;
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final previousResultIdJson = json['previousResultId'];
    final previousResultId = previousResultIdJson as String?;
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentDiagnosticParams(
      identifier: identifier,
      partialResultToken: partialResultToken,
      previousResultId: previousResultId,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The additional identifier  provided during registration.
  final String? identifier;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The result id of a previous response if provided.
  final String? previousResultId;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (identifier != null) {
      result['identifier'] = identifier;
    }
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    if (previousResultId != null) {
      result['previousResultId'] = previousResultId;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('identifier');
      try {
        final identifier = obj['identifier'];
        if (identifier != null && identifier is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('previousResultId');
      try {
        final previousResultId = obj['previousResultId'];
        if (previousResultId != null && previousResultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentDiagnosticParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentDiagnosticParams &&
        other.runtimeType == DocumentDiagnosticParams &&
        identifier == other.identifier &&
        partialResultToken == other.partialResultToken &&
        previousResultId == other.previousResultId &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        identifier,
        partialResultToken,
        previousResultId,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A partial result for a document diagnostic report.
///
/// @since 3.17.0
class DocumentDiagnosticReportPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentDiagnosticReportPartialResult.canParse,
    DocumentDiagnosticReportPartialResult.fromJson,
  );

  DocumentDiagnosticReportPartialResult({
    required this.relatedDocuments,
  });
  static DocumentDiagnosticReportPartialResult fromJson(
      Map<String, Object?> json) {
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>).map(
        (key, value) => MapEntry(
            key as String,
            FullDocumentDiagnosticReport.canParse(value, nullLspJsonReporter)
                ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t1(
                    FullDocumentDiagnosticReport.fromJson(
                        value as Map<String, Object?>))
                : (UnchangedDocumentDiagnosticReport.canParse(
                        value, nullLspJsonReporter)
                    ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t2(
                        UnchangedDocumentDiagnosticReport.fromJson(
                            value as Map<String, Object?>))
                    : (throw '''$value was not one of (FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport)'''))));
    return DocumentDiagnosticReportPartialResult(
      relatedDocuments: relatedDocuments,
    );
  }

  final Map<
      String,
      Either2<FullDocumentDiagnosticReport,
          UnchangedDocumentDiagnosticReport>> relatedDocuments;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('relatedDocuments');
      try {
        if (!obj.containsKey('relatedDocuments')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final relatedDocuments = obj['relatedDocuments'];
        if (relatedDocuments == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (relatedDocuments is! Map ||
            (relatedDocuments.keys.any((item) =>
                item is! String ||
                relatedDocuments.values.any((item) =>
                    !FullDocumentDiagnosticReport.canParse(item, reporter) &&
                    !UnchangedDocumentDiagnosticReport.canParse(
                        item, reporter))))) {
          reporter.reportError(
              'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentDiagnosticReportPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentDiagnosticReportPartialResult &&
        other.runtimeType == DocumentDiagnosticReportPartialResult &&
        mapEqual(
            relatedDocuments,
            other.relatedDocuments,
            (Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        a,
                    Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        b) =>
                a == b);
  }

  @override
  int get hashCode => lspHashCode(relatedDocuments);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities of a DocumentFormattingRequest.
class DocumentFormattingClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingClientCapabilities.canParse,
    DocumentFormattingClientCapabilities.fromJson,
  );

  DocumentFormattingClientCapabilities({
    this.dynamicRegistration,
  });
  static DocumentFormattingClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DocumentFormattingClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether formatting supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentFormattingClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentFormattingClientCapabilities &&
        other.runtimeType == DocumentFormattingClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a DocumentFormattingRequest.
class DocumentFormattingOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingOptions.canParse,
    DocumentFormattingOptions.fromJson,
  );

  DocumentFormattingOptions({
    this.workDoneProgress,
  });
  static DocumentFormattingOptions fromJson(Map<String, Object?> json) {
    if (DocumentFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentFormattingRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentFormattingOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentFormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentFormattingOptions &&
        other.runtimeType == DocumentFormattingOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a DocumentFormattingRequest.
class DocumentFormattingParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingParams.canParse,
    DocumentFormattingParams.fromJson,
  );

  DocumentFormattingParams({
    required this.options,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentFormattingParams fromJson(Map<String, Object?> json) {
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentFormattingParams(
      options: options,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The format options.
  final FormattingOptions options;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['options'] = options.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('options');
      try {
        if (!obj.containsKey('options')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final options = obj['options'];
        if (options == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!FormattingOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type FormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentFormattingParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentFormattingParams &&
        other.runtimeType == DocumentFormattingParams &&
        options == other.options &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        options,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DocumentFormattingRequest.
class DocumentFormattingRegistrationOptions
    implements
        DocumentFormattingOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingRegistrationOptions.canParse,
    DocumentFormattingRegistrationOptions.fromJson,
  );

  DocumentFormattingRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static DocumentFormattingRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentFormattingRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentFormattingRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentFormattingRegistrationOptions &&
        other.runtimeType == DocumentFormattingRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A document highlight is a range inside a text document which deserves
/// special attention. Usually a document highlight is visualized by changing
/// the background color of its range.
class DocumentHighlight implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlight.canParse,
    DocumentHighlight.fromJson,
  );

  DocumentHighlight({
    this.kind,
    required this.range,
  });
  static DocumentHighlight fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson != null
        ? DocumentHighlightKind.fromJson(kindJson as int)
        : null;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return DocumentHighlight(
      kind: kind,
      range: range,
    );
  }

  /// The highlight kind, default is text.
  final DocumentHighlightKind? kind;

  /// The range this highlight applies to.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !DocumentHighlightKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type DocumentHighlightKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentHighlight');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentHighlight &&
        other.runtimeType == DocumentHighlight &&
        kind == other.kind &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client Capabilities for a DocumentHighlightRequest.
class DocumentHighlightClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightClientCapabilities.canParse,
    DocumentHighlightClientCapabilities.fromJson,
  );

  DocumentHighlightClientCapabilities({
    this.dynamicRegistration,
  });
  static DocumentHighlightClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DocumentHighlightClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether document highlight supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentHighlightClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentHighlightClientCapabilities &&
        other.runtimeType == DocumentHighlightClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A document highlight kind.
class DocumentHighlightKind implements ToJsonable {
  const DocumentHighlightKind(this._value);
  const DocumentHighlightKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Read-access of a symbol, like reading a variable.
  static const Read = DocumentHighlightKind(2);

  /// A textual occurrence.
  static const Text = DocumentHighlightKind(1);

  /// Write-access of a symbol, like writing to a variable.
  static const Write = DocumentHighlightKind(3);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is DocumentHighlightKind && other._value == _value;
}

/// Provider options for a DocumentHighlightRequest.
class DocumentHighlightOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightOptions.canParse,
    DocumentHighlightOptions.fromJson,
  );

  DocumentHighlightOptions({
    this.workDoneProgress,
  });
  static DocumentHighlightOptions fromJson(Map<String, Object?> json) {
    if (DocumentHighlightRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentHighlightRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentHighlightOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentHighlightOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentHighlightOptions &&
        other.runtimeType == DocumentHighlightOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a DocumentHighlightRequest.
class DocumentHighlightParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightParams.canParse,
    DocumentHighlightParams.fromJson,
  );

  DocumentHighlightParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentHighlightParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentHighlightParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentHighlightParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentHighlightParams &&
        other.runtimeType == DocumentHighlightParams &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DocumentHighlightRequest.
class DocumentHighlightRegistrationOptions
    implements
        DocumentHighlightOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightRegistrationOptions.canParse,
    DocumentHighlightRegistrationOptions.fromJson,
  );

  DocumentHighlightRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static DocumentHighlightRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentHighlightRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentHighlightRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentHighlightRegistrationOptions &&
        other.runtimeType == DocumentHighlightRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A document link is a range in a text document that links to an internal or
/// external resource, like another text document or a web site.
class DocumentLink implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLink.canParse,
    DocumentLink.fromJson,
  );

  DocumentLink({
    this.data,
    required this.range,
    this.target,
    this.tooltip,
  });
  static DocumentLink fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final targetJson = json['target'];
    final target = targetJson as String?;
    final tooltipJson = json['tooltip'];
    final tooltip = tooltipJson as String?;
    return DocumentLink(
      data: data,
      range: range,
      target: target,
      tooltip: tooltip,
    );
  }

  /// A data entry field that is preserved on a document link between a
  /// DocumentLinkRequest and a DocumentLinkResolveRequest.
  final Object? data;

  /// The range this link applies to.
  final Range range;

  /// The uri this link points to. If missing a resolve request is sent later.
  final String? target;

  /// The tooltip text when you hover over this link.
  ///
  /// If a tooltip is provided, is will be displayed in a string that includes
  /// instructions on how to trigger the link, such as `{0} (ctrl + click)`. The
  /// specific instructions vary depending on OS,
  /// user settings, and localization.
  ///
  /// @since 3.15.0
  final String? tooltip;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    result['range'] = range.toJson();
    if (target != null) {
      result['target'] = target;
    }
    if (tooltip != null) {
      result['tooltip'] = tooltip;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('target');
      try {
        final target = obj['target'];
        if (target != null && target is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tooltip');
      try {
        final tooltip = obj['tooltip'];
        if (tooltip != null && tooltip is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLink');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentLink &&
        other.runtimeType == DocumentLink &&
        data == other.data &&
        range == other.range &&
        target == other.target &&
        tooltip == other.tooltip;
  }

  @override
  int get hashCode => Object.hash(
        data,
        range,
        target,
        tooltip,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The client capabilities of a DocumentLinkRequest.
class DocumentLinkClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkClientCapabilities.canParse,
    DocumentLinkClientCapabilities.fromJson,
  );

  DocumentLinkClientCapabilities({
    this.dynamicRegistration,
    this.tooltipSupport,
  });
  static DocumentLinkClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final tooltipSupportJson = json['tooltipSupport'];
    final tooltipSupport = tooltipSupportJson as bool?;
    return DocumentLinkClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      tooltipSupport: tooltipSupport,
    );
  }

  /// Whether document link supports dynamic registration.
  final bool? dynamicRegistration;

  /// Whether the client supports the `tooltip` property on `DocumentLink`.
  ///
  /// @since 3.15.0
  final bool? tooltipSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (tooltipSupport != null) {
      result['tooltipSupport'] = tooltipSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tooltipSupport');
      try {
        final tooltipSupport = obj['tooltipSupport'];
        if (tooltipSupport != null && tooltipSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLinkClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentLinkClientCapabilities &&
        other.runtimeType == DocumentLinkClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        tooltipSupport == other.tooltipSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        tooltipSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a DocumentLinkRequest.
class DocumentLinkOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkOptions.canParse,
    DocumentLinkOptions.fromJson,
  );

  DocumentLinkOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static DocumentLinkOptions fromJson(Map<String, Object?> json) {
    if (DocumentLinkRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkRegistrationOptions.fromJson(json);
    }
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentLinkOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Document links have a resolve provider as well.
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLinkOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentLinkOptions &&
        other.runtimeType == DocumentLinkOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a DocumentLinkRequest.
class DocumentLinkParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkParams.canParse,
    DocumentLinkParams.fromJson,
  );

  DocumentLinkParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentLinkParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentLinkParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The document to provide document links for.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLinkParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentLinkParams &&
        other.runtimeType == DocumentLinkParams &&
        partialResultToken == other.partialResultToken &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DocumentLinkRequest.
class DocumentLinkRegistrationOptions
    implements
        DocumentLinkOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkRegistrationOptions.canParse,
    DocumentLinkRegistrationOptions.fromJson,
  );

  DocumentLinkRegistrationOptions({
    this.documentSelector,
    this.resolveProvider,
    this.workDoneProgress,
  });
  static DocumentLinkRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentLinkRegistrationOptions(
      documentSelector: documentSelector,
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// Document links have a resolve provider as well.
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLinkRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentLinkRegistrationOptions &&
        other.runtimeType == DocumentLinkRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities of a DocumentOnTypeFormattingRequest.
class DocumentOnTypeFormattingClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingClientCapabilities.canParse,
    DocumentOnTypeFormattingClientCapabilities.fromJson,
  );

  DocumentOnTypeFormattingClientCapabilities({
    this.dynamicRegistration,
  });
  static DocumentOnTypeFormattingClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DocumentOnTypeFormattingClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether on type formatting supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentOnTypeFormattingClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentOnTypeFormattingClientCapabilities &&
        other.runtimeType == DocumentOnTypeFormattingClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a DocumentOnTypeFormattingRequest.
class DocumentOnTypeFormattingOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingOptions.canParse,
    DocumentOnTypeFormattingOptions.fromJson,
  );

  DocumentOnTypeFormattingOptions({
    required this.firstTriggerCharacter,
    this.moreTriggerCharacter,
  });
  static DocumentOnTypeFormattingOptions fromJson(Map<String, Object?> json) {
    if (DocumentOnTypeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingRegistrationOptions.fromJson(json);
    }
    final firstTriggerCharacterJson = json['firstTriggerCharacter'];
    final firstTriggerCharacter = firstTriggerCharacterJson as String;
    final moreTriggerCharacterJson = json['moreTriggerCharacter'];
    final moreTriggerCharacter = (moreTriggerCharacterJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    return DocumentOnTypeFormattingOptions(
      firstTriggerCharacter: firstTriggerCharacter,
      moreTriggerCharacter: moreTriggerCharacter,
    );
  }

  /// A character on which formatting should be triggered, like `{`.
  final String firstTriggerCharacter;

  /// More trigger characters.
  final List<String>? moreTriggerCharacter;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['firstTriggerCharacter'] = firstTriggerCharacter;
    if (moreTriggerCharacter != null) {
      result['moreTriggerCharacter'] = moreTriggerCharacter;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('firstTriggerCharacter');
      try {
        if (!obj.containsKey('firstTriggerCharacter')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final firstTriggerCharacter = obj['firstTriggerCharacter'];
        if (firstTriggerCharacter == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (firstTriggerCharacter is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('moreTriggerCharacter');
      try {
        final moreTriggerCharacter = obj['moreTriggerCharacter'];
        if (moreTriggerCharacter != null &&
            (moreTriggerCharacter is! List<Object?> ||
                moreTriggerCharacter.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentOnTypeFormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentOnTypeFormattingOptions &&
        other.runtimeType == DocumentOnTypeFormattingOptions &&
        firstTriggerCharacter == other.firstTriggerCharacter &&
        listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
            (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        firstTriggerCharacter,
        lspHashCode(moreTriggerCharacter),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a DocumentOnTypeFormattingRequest.
class DocumentOnTypeFormattingParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingParams.canParse,
    DocumentOnTypeFormattingParams.fromJson,
  );

  DocumentOnTypeFormattingParams({
    required this.ch,
    required this.options,
    required this.position,
    required this.textDocument,
  });
  static DocumentOnTypeFormattingParams fromJson(Map<String, Object?> json) {
    final chJson = json['ch'];
    final ch = chJson as String;
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return DocumentOnTypeFormattingParams(
      ch: ch,
      options: options,
      position: position,
      textDocument: textDocument,
    );
  }

  /// The character that has been typed that triggered the formatting on type
  /// request. That is not necessarily the last character that got inserted into
  /// the document since the client could auto insert characters as well (e.g.
  /// like automatic brace completion).
  final String ch;

  /// The formatting options.
  final FormattingOptions options;

  /// The position around which the on type formatting should happen. This is
  /// not necessarily the exact position where the character denoted by the
  /// property `ch` got typed.
  final Position position;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['ch'] = ch;
    result['options'] = options.toJson();
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ch');
      try {
        if (!obj.containsKey('ch')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final ch = obj['ch'];
        if (ch == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (ch is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        if (!obj.containsKey('options')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final options = obj['options'];
        if (options == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!FormattingOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type FormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentOnTypeFormattingParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentOnTypeFormattingParams &&
        other.runtimeType == DocumentOnTypeFormattingParams &&
        ch == other.ch &&
        options == other.options &&
        position == other.position &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        ch,
        options,
        position,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DocumentOnTypeFormattingRequest.
class DocumentOnTypeFormattingRegistrationOptions
    implements
        DocumentOnTypeFormattingOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingRegistrationOptions.canParse,
    DocumentOnTypeFormattingRegistrationOptions.fromJson,
  );

  DocumentOnTypeFormattingRegistrationOptions({
    this.documentSelector,
    required this.firstTriggerCharacter,
    this.moreTriggerCharacter,
  });
  static DocumentOnTypeFormattingRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final firstTriggerCharacterJson = json['firstTriggerCharacter'];
    final firstTriggerCharacter = firstTriggerCharacterJson as String;
    final moreTriggerCharacterJson = json['moreTriggerCharacter'];
    final moreTriggerCharacter = (moreTriggerCharacterJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    return DocumentOnTypeFormattingRegistrationOptions(
      documentSelector: documentSelector,
      firstTriggerCharacter: firstTriggerCharacter,
      moreTriggerCharacter: moreTriggerCharacter,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// A character on which formatting should be triggered, like `{`.
  @override
  final String firstTriggerCharacter;

  /// More trigger characters.
  @override
  final List<String>? moreTriggerCharacter;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    result['firstTriggerCharacter'] = firstTriggerCharacter;
    if (moreTriggerCharacter != null) {
      result['moreTriggerCharacter'] = moreTriggerCharacter;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('firstTriggerCharacter');
      try {
        if (!obj.containsKey('firstTriggerCharacter')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final firstTriggerCharacter = obj['firstTriggerCharacter'];
        if (firstTriggerCharacter == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (firstTriggerCharacter is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('moreTriggerCharacter');
      try {
        final moreTriggerCharacter = obj['moreTriggerCharacter'];
        if (moreTriggerCharacter != null &&
            (moreTriggerCharacter is! List<Object?> ||
                moreTriggerCharacter.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentOnTypeFormattingRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentOnTypeFormattingRegistrationOptions &&
        other.runtimeType == DocumentOnTypeFormattingRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        firstTriggerCharacter == other.firstTriggerCharacter &&
        listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
            (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        firstTriggerCharacter,
        lspHashCode(moreTriggerCharacter),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities of a DocumentRangeFormattingRequest.
class DocumentRangeFormattingClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingClientCapabilities.canParse,
    DocumentRangeFormattingClientCapabilities.fromJson,
  );

  DocumentRangeFormattingClientCapabilities({
    this.dynamicRegistration,
  });
  static DocumentRangeFormattingClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DocumentRangeFormattingClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether range formatting supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentRangeFormattingClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentRangeFormattingClientCapabilities &&
        other.runtimeType == DocumentRangeFormattingClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a DocumentRangeFormattingRequest.
class DocumentRangeFormattingOptions
    implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingOptions.canParse,
    DocumentRangeFormattingOptions.fromJson,
  );

  DocumentRangeFormattingOptions({
    this.workDoneProgress,
  });
  static DocumentRangeFormattingOptions fromJson(Map<String, Object?> json) {
    if (DocumentRangeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentRangeFormattingRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentRangeFormattingOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentRangeFormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentRangeFormattingOptions &&
        other.runtimeType == DocumentRangeFormattingOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a DocumentRangeFormattingRequest.
class DocumentRangeFormattingParams
    implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingParams.canParse,
    DocumentRangeFormattingParams.fromJson,
  );

  DocumentRangeFormattingParams({
    required this.options,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentRangeFormattingParams fromJson(Map<String, Object?> json) {
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentRangeFormattingParams(
      options: options,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The format options
  final FormattingOptions options;

  /// The range to format
  final Range range;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['options'] = options.toJson();
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('options');
      try {
        if (!obj.containsKey('options')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final options = obj['options'];
        if (options == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!FormattingOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type FormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentRangeFormattingParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentRangeFormattingParams &&
        other.runtimeType == DocumentRangeFormattingParams &&
        options == other.options &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        options,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DocumentRangeFormattingRequest.
class DocumentRangeFormattingRegistrationOptions
    implements
        DocumentRangeFormattingOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingRegistrationOptions.canParse,
    DocumentRangeFormattingRegistrationOptions.fromJson,
  );

  DocumentRangeFormattingRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static DocumentRangeFormattingRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentRangeFormattingRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentRangeFormattingRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentRangeFormattingRegistrationOptions &&
        other.runtimeType == DocumentRangeFormattingRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents programming constructs like variables, classes, interfaces etc.
/// that appear in a document. Document symbols can be hierarchical and they
/// have two ranges: one that encloses its definition and one that points to its
/// most interesting range, e.g. the range of an identifier.
class DocumentSymbol implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbol.canParse,
    DocumentSymbol.fromJson,
  );

  DocumentSymbol({
    this.children,
    this.deprecated,
    this.detail,
    required this.kind,
    required this.name,
    required this.range,
    required this.selectionRange,
    this.tags,
  });
  static DocumentSymbol fromJson(Map<String, Object?> json) {
    final childrenJson = json['children'];
    final children = (childrenJson as List<Object?>?)
        ?.map((item) => DocumentSymbol.fromJson(item as Map<String, Object?>))
        .toList();
    final deprecatedJson = json['deprecated'];
    final deprecated = deprecatedJson as bool?;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final nameJson = json['name'];
    final name = nameJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final selectionRangeJson = json['selectionRange'];
    final selectionRange =
        Range.fromJson(selectionRangeJson as Map<String, Object?>);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return DocumentSymbol(
      children: children,
      deprecated: deprecated,
      detail: detail,
      kind: kind,
      name: name,
      range: range,
      selectionRange: selectionRange,
      tags: tags,
    );
  }

  /// Children of this symbol, e.g. properties of a class.
  final List<DocumentSymbol>? children;

  /// Indicates if this symbol is deprecated.
  ///
  /// @deprecated Use tags instead
  final bool? deprecated;

  /// More detail for this symbol, e.g the signature of a function.
  final String? detail;

  /// The kind of this symbol.
  final SymbolKind kind;

  /// The name of this symbol. Will be displayed in the user interface and
  /// therefore must not be an empty string or a string only consisting of white
  /// spaces.
  final String name;

  /// The range enclosing this symbol not including leading/trailing whitespace
  /// but everything else like comments. This information is typically used to
  /// determine if the clients cursor is inside the symbol to reveal in the
  /// symbol in the UI.
  final Range range;

  /// The range that should be selected and revealed when this symbol is being
  /// picked, e.g the name of a function. Must be contained by the `range`.
  final Range selectionRange;

  /// Tags for this document symbol.
  ///
  /// @since 3.16.0
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (children != null) {
      result['children'] = children?.map((item) => item.toJson()).toList();
    }
    if (deprecated != null) {
      result['deprecated'] = deprecated;
    }
    if (detail != null) {
      result['detail'] = detail;
    }
    result['kind'] = kind.toJson();
    result['name'] = name;
    result['range'] = range.toJson();
    result['selectionRange'] = selectionRange.toJson();
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('children');
      try {
        final children = obj['children'];
        if (children != null &&
            (children is! List<Object?> ||
                children
                    .any((item) => !DocumentSymbol.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<DocumentSymbol>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deprecated');
      try {
        final deprecated = obj['deprecated'];
        if (deprecated != null && deprecated is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('detail');
      try {
        final detail = obj['detail'];
        if (detail != null && detail is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRange');
      try {
        if (!obj.containsKey('selectionRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final selectionRange = obj['selectionRange'];
        if (selectionRange == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(selectionRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbol');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbol &&
        other.runtimeType == DocumentSymbol &&
        listEqual(children, other.children,
            (DocumentSymbol a, DocumentSymbol b) => a == b) &&
        deprecated == other.deprecated &&
        detail == other.detail &&
        kind == other.kind &&
        name == other.name &&
        range == other.range &&
        selectionRange == other.selectionRange &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(children),
        deprecated,
        detail,
        kind,
        name,
        range,
        selectionRange,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client Capabilities for a DocumentSymbolRequest.
class DocumentSymbolClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolClientCapabilities.canParse,
    DocumentSymbolClientCapabilities.fromJson,
  );

  DocumentSymbolClientCapabilities({
    this.dynamicRegistration,
    this.hierarchicalDocumentSymbolSupport,
    this.labelSupport,
    this.symbolKind,
    this.tagSupport,
  });
  static DocumentSymbolClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final hierarchicalDocumentSymbolSupportJson =
        json['hierarchicalDocumentSymbolSupport'];
    final hierarchicalDocumentSymbolSupport =
        hierarchicalDocumentSymbolSupportJson as bool?;
    final labelSupportJson = json['labelSupport'];
    final labelSupport = labelSupportJson as bool?;
    final symbolKindJson = json['symbolKind'];
    final symbolKind = symbolKindJson != null
        ? DocumentSymbolClientCapabilitiesSymbolKind.fromJson(
            symbolKindJson as Map<String, Object?>)
        : null;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? DocumentSymbolClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    return DocumentSymbolClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      hierarchicalDocumentSymbolSupport: hierarchicalDocumentSymbolSupport,
      labelSupport: labelSupport,
      symbolKind: symbolKind,
      tagSupport: tagSupport,
    );
  }

  /// Whether document symbol supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports hierarchical document symbols.
  final bool? hierarchicalDocumentSymbolSupport;

  /// The client supports an additional label presented in the UI when
  /// registering a document symbol provider.
  ///
  /// @since 3.16.0
  final bool? labelSupport;

  /// Specific capabilities for the `SymbolKind` in the
  /// `textDocument/documentSymbol` request.
  final DocumentSymbolClientCapabilitiesSymbolKind? symbolKind;

  /// The client supports tags on `SymbolInformation`. Tags are supported on
  /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///
  /// @since 3.16.0
  final DocumentSymbolClientCapabilitiesTagSupport? tagSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (hierarchicalDocumentSymbolSupport != null) {
      result['hierarchicalDocumentSymbolSupport'] =
          hierarchicalDocumentSymbolSupport;
    }
    if (labelSupport != null) {
      result['labelSupport'] = labelSupport;
    }
    if (symbolKind != null) {
      result['symbolKind'] = symbolKind?.toJson();
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('hierarchicalDocumentSymbolSupport');
      try {
        final hierarchicalDocumentSymbolSupport =
            obj['hierarchicalDocumentSymbolSupport'];
        if (hierarchicalDocumentSymbolSupport != null &&
            hierarchicalDocumentSymbolSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('labelSupport');
      try {
        final labelSupport = obj['labelSupport'];
        if (labelSupport != null && labelSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('symbolKind');
      try {
        final symbolKind = obj['symbolKind'];
        if (symbolKind != null &&
            !DocumentSymbolClientCapabilitiesSymbolKind.canParse(
                symbolKind, reporter)) {
          reporter.reportError(
              'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        final tagSupport = obj['tagSupport'];
        if (tagSupport != null &&
            !DocumentSymbolClientCapabilitiesTagSupport.canParse(
                tagSupport, reporter)) {
          reporter.reportError(
              'must be of type DocumentSymbolClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolClientCapabilities &&
        other.runtimeType == DocumentSymbolClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        hierarchicalDocumentSymbolSupport ==
            other.hierarchicalDocumentSymbolSupport &&
        labelSupport == other.labelSupport &&
        symbolKind == other.symbolKind &&
        tagSupport == other.tagSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        hierarchicalDocumentSymbolSupport,
        labelSupport,
        symbolKind,
        tagSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentSymbolClientCapabilitiesSymbolKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolClientCapabilitiesSymbolKind.canParse,
    DocumentSymbolClientCapabilitiesSymbolKind.fromJson,
  );

  DocumentSymbolClientCapabilitiesSymbolKind({
    this.valueSet,
  });
  static DocumentSymbolClientCapabilitiesSymbolKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => SymbolKind.fromJson(item as int))
        .toList();
    return DocumentSymbolClientCapabilitiesSymbolKind(
      valueSet: valueSet,
    );
  }

  /// The symbol kind values the client supports. When this property exists the
  /// client also guarantees that it will handle values outside its set
  /// gracefully and falls back to a default value when unknown.
  ///
  /// If this property is not present the client only supports the symbol kinds
  /// from `File` to `Array` as defined in the initial version of the protocol.
  final List<SymbolKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        final valueSet = obj['valueSet'];
        if (valueSet != null &&
            (valueSet is! List<Object?> ||
                valueSet.any((item) => !SymbolKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolClientCapabilitiesSymbolKind &&
        other.runtimeType == DocumentSymbolClientCapabilitiesSymbolKind &&
        listEqual(
            valueSet, other.valueSet, (SymbolKind a, SymbolKind b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentSymbolClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolClientCapabilitiesTagSupport.canParse,
    DocumentSymbolClientCapabilitiesTagSupport.fromJson,
  );

  DocumentSymbolClientCapabilitiesTagSupport({
    required this.valueSet,
  });
  static DocumentSymbolClientCapabilitiesTagSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return DocumentSymbolClientCapabilitiesTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<SymbolTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final valueSet = obj['valueSet'];
        if (valueSet == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (valueSet is! List<Object?> ||
            valueSet.any((item) => !SymbolTag.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentSymbolClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolClientCapabilitiesTagSupport &&
        other.runtimeType == DocumentSymbolClientCapabilitiesTagSupport &&
        listEqual(
            valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a DocumentSymbolRequest.
class DocumentSymbolOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolOptions.canParse,
    DocumentSymbolOptions.fromJson,
  );

  DocumentSymbolOptions({
    this.label,
    this.workDoneProgress,
  });
  static DocumentSymbolOptions fromJson(Map<String, Object?> json) {
    if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolRegistrationOptions.fromJson(json);
    }
    final labelJson = json['label'];
    final label = labelJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentSymbolOptions(
      label: label,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A human-readable string that is shown when multiple outlines trees are
  /// shown for the same document.
  ///
  /// @since 3.16.0
  final String? label;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (label != null) {
      result['label'] = label;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('label');
      try {
        final label = obj['label'];
        if (label != null && label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolOptions &&
        other.runtimeType == DocumentSymbolOptions &&
        label == other.label &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        label,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a DocumentSymbolRequest.
class DocumentSymbolParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolParams.canParse,
    DocumentSymbolParams.fromJson,
  );

  DocumentSymbolParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentSymbolParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentSymbolParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolParams &&
        other.runtimeType == DocumentSymbolParams &&
        partialResultToken == other.partialResultToken &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DocumentSymbolRequest.
class DocumentSymbolRegistrationOptions
    implements
        DocumentSymbolOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolRegistrationOptions.canParse,
    DocumentSymbolRegistrationOptions.fromJson,
  );

  DocumentSymbolRegistrationOptions({
    this.documentSelector,
    this.label,
    this.workDoneProgress,
  });
  static DocumentSymbolRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final labelJson = json['label'];
    final label = labelJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentSymbolRegistrationOptions(
      documentSelector: documentSelector,
      label: label,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// A human-readable string that is shown when multiple outlines trees are
  /// shown for the same document.
  ///
  /// @since 3.16.0
  @override
  final String? label;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (label != null) {
      result['label'] = label;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        final label = obj['label'];
        if (label != null && label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolRegistrationOptions &&
        other.runtimeType == DocumentSymbolRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        label == other.label &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        label,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Predefined error codes.
class ErrorCodes implements ToJsonable {
  const ErrorCodes(this._value);
  const ErrorCodes.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// The server detected that the content of a document got modified outside
  /// normal conditions. A server should NOT send this error code if it detects
  /// a content change in it unprocessed messages. The result even computed on
  /// an older state might still be useful for the client.
  ///
  /// If a client decides that a result is not of any use anymore the client
  /// should cancel the request.
  static const ContentModified = ErrorCodes(-32801);
  static const InternalError = ErrorCodes(-32603);
  static const InvalidParams = ErrorCodes(-32602);
  static const InvalidRequest = ErrorCodes(-32600);

  /// This is the end range of JSON RPC reserved error codes. It doesn't denote
  /// a real error code.
  ///
  /// @since 3.16.0
  static const jsonrpcReservedErrorRangeEnd = ErrorCodes(-32000);

  /// This is the start range of JSON RPC reserved error codes. It doesn't
  /// denote a real error code. No application error codes should be defined
  /// between the start and end range. For backwards compatibility the
  /// `ServerNotInitialized` and the `UnknownErrorCode` are left in the range.
  ///
  /// @since 3.16.0
  static const jsonrpcReservedErrorRangeStart = ErrorCodes(-32099);

  /// This is the end range of LSP reserved error codes. It doesn't denote a
  /// real error code.
  ///
  /// @since 3.16.0
  static const lspReservedErrorRangeEnd = ErrorCodes(-32800);

  /// This is the start range of LSP reserved error codes. It doesn't denote a
  /// real error code.
  ///
  /// @since 3.16.0
  static const lspReservedErrorRangeStart = ErrorCodes(-32899);
  static const MethodNotFound = ErrorCodes(-32601);
  static const ParseError = ErrorCodes(-32700);

  /// The client has canceled a request and a server as detected the cancel.
  static const RequestCancelled = ErrorCodes(-32800);

  /// A request failed but it was syntactically correct, e.g the method name was
  /// known and the parameters were valid. The error message should contain
  /// human readable information about why the request failed.
  ///
  /// @since 3.17.0
  static const RequestFailed = ErrorCodes(-32803);

  /// The server cancelled the request. This error code should only be used for
  /// requests that explicitly support being server cancellable.
  ///
  /// @since 3.17.0
  static const ServerCancelled = ErrorCodes(-32802);

  /// Error code indicating that a server received a notification or request
  /// before the server has received the `initialize` request.
  static const ServerNotInitialized = ErrorCodes(-32002);
  static const UnknownErrorCode = ErrorCodes(-32001);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is ErrorCodes && other._value == _value;
}

/// The client capabilities of a ExecuteCommandRequest.
class ExecuteCommandClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandClientCapabilities.canParse,
    ExecuteCommandClientCapabilities.fromJson,
  );

  ExecuteCommandClientCapabilities({
    this.dynamicRegistration,
  });
  static ExecuteCommandClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return ExecuteCommandClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Execute command supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecuteCommandClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecuteCommandClientCapabilities &&
        other.runtimeType == ExecuteCommandClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The server capabilities of a ExecuteCommandRequest.
class ExecuteCommandOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandOptions.canParse,
    ExecuteCommandOptions.fromJson,
  );

  ExecuteCommandOptions({
    required this.commands,
    this.workDoneProgress,
  });
  static ExecuteCommandOptions fromJson(Map<String, Object?> json) {
    if (ExecuteCommandRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandRegistrationOptions.fromJson(json);
    }
    final commandsJson = json['commands'];
    final commands =
        (commandsJson as List<Object?>).map((item) => item as String).toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ExecuteCommandOptions(
      commands: commands,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The commands to be executed on the server
  final List<String> commands;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['commands'] = commands;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('commands');
      try {
        if (!obj.containsKey('commands')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final commands = obj['commands'];
        if (commands == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (commands is! List<Object?> ||
            commands.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecuteCommandOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecuteCommandOptions &&
        other.runtimeType == ExecuteCommandOptions &&
        listEqual(commands, other.commands, (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(commands),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a ExecuteCommandRequest.
class ExecuteCommandParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandParams.canParse,
    ExecuteCommandParams.fromJson,
  );

  ExecuteCommandParams({
    this.arguments,
    required this.command,
    this.workDoneToken,
  });
  static ExecuteCommandParams fromJson(Map<String, Object?> json) {
    final argumentsJson = json['arguments'];
    final arguments =
        (argumentsJson as List<Object?>?)?.map((item) => item).toList();
    final commandJson = json['command'];
    final command = commandJson as String;
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return ExecuteCommandParams(
      arguments: arguments,
      command: command,
      workDoneToken: workDoneToken,
    );
  }

  /// Arguments that the command should be invoked with.
  final List<Object?>? arguments;

  /// The identifier of the actual command handler.
  final String command;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (arguments != null) {
      result['arguments'] = arguments;
    }
    result['command'] = command;
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('arguments');
      try {
        final arguments = obj['arguments'];
        if (arguments != null &&
            (arguments is! List<Object?> || arguments.any((item) => false))) {
          reporter.reportError('must be of type List<Object?>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('command');
      try {
        if (!obj.containsKey('command')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final command = obj['command'];
        if (command == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (command is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecuteCommandParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecuteCommandParams &&
        other.runtimeType == ExecuteCommandParams &&
        listEqual(
            arguments, other.arguments, (Object? a, Object? b) => a == b) &&
        command == other.command &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(arguments),
        command,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a ExecuteCommandRequest.
class ExecuteCommandRegistrationOptions
    implements ExecuteCommandOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandRegistrationOptions.canParse,
    ExecuteCommandRegistrationOptions.fromJson,
  );

  ExecuteCommandRegistrationOptions({
    required this.commands,
    this.workDoneProgress,
  });
  static ExecuteCommandRegistrationOptions fromJson(Map<String, Object?> json) {
    final commandsJson = json['commands'];
    final commands =
        (commandsJson as List<Object?>).map((item) => item as String).toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ExecuteCommandRegistrationOptions(
      commands: commands,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The commands to be executed on the server
  @override
  final List<String> commands;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['commands'] = commands;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('commands');
      try {
        if (!obj.containsKey('commands')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final commands = obj['commands'];
        if (commands == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (commands is! List<Object?> ||
            commands.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecuteCommandRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecuteCommandRegistrationOptions &&
        other.runtimeType == ExecuteCommandRegistrationOptions &&
        listEqual(commands, other.commands, (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(commands),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ExecutionSummary implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecutionSummary.canParse,
    ExecutionSummary.fromJson,
  );

  ExecutionSummary({
    required this.executionOrder,
    this.success,
  });
  static ExecutionSummary fromJson(Map<String, Object?> json) {
    final executionOrderJson = json['executionOrder'];
    final executionOrder = executionOrderJson as int;
    final successJson = json['success'];
    final success = successJson as bool?;
    return ExecutionSummary(
      executionOrder: executionOrder,
      success: success,
    );
  }

  /// A strict monotonically increasing value indicating the execution order of
  /// a cell inside a notebook.
  final int executionOrder;

  /// Whether the execution was successful or not if known by the client.
  final bool? success;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['executionOrder'] = executionOrder;
    if (success != null) {
      result['success'] = success;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('executionOrder');
      try {
        if (!obj.containsKey('executionOrder')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final executionOrder = obj['executionOrder'];
        if (executionOrder == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (executionOrder is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('success');
      try {
        final success = obj['success'];
        if (success != null && success is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecutionSummary');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecutionSummary &&
        other.runtimeType == ExecutionSummary &&
        executionOrder == other.executionOrder &&
        success == other.success;
  }

  @override
  int get hashCode => Object.hash(
        executionOrder,
        success,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FailureHandlingKind implements ToJsonable {
  const FailureHandlingKind._(this._value);
  const FailureHandlingKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'abort':
      case 'textOnlyTransactional':
      case 'transactional':
      case 'undo':
        return true;
    }
    return false;
  }

  /// Applying the workspace change is simply aborted if one of the changes
  /// provided fails. All operations executed before the failing operation stay
  /// executed.
  static const Abort = FailureHandlingKind._('abort');

  /// If the workspace edit contains only textual file changes they are executed
  /// transactional. If resource changes (create, rename or delete file) are
  /// part of the change the failure handling strategy is abort.
  static const TextOnlyTransactional =
      FailureHandlingKind._('textOnlyTransactional');

  /// All operations are executed transactional. That means they either all
  /// succeed or no changes at all are applied to the workspace.
  static const Transactional = FailureHandlingKind._('transactional');

  /// The client tries to undo the operations already executed. But there is no
  /// guarantee that this is succeeding.
  static const Undo = FailureHandlingKind._('undo');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FailureHandlingKind && other._value == _value;
}

/// The file event type
class FileChangeType implements ToJsonable {
  const FileChangeType(this._value);
  const FileChangeType.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// The file got changed.
  static const Changed = FileChangeType(2);

  /// The file got created.
  static const Created = FileChangeType(1);

  /// The file got deleted.
  static const Deleted = FileChangeType(3);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FileChangeType && other._value == _value;
}

/// Represents information on a file/folder create.
///
/// @since 3.16.0
class FileCreate implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileCreate.canParse,
    FileCreate.fromJson,
  );

  FileCreate({
    required this.uri,
  });
  static FileCreate fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return FileCreate(
      uri: uri,
    );
  }

  /// A file:// URI for the location of the file/folder being created.
  final String uri;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileCreate');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileCreate &&
        other.runtimeType == FileCreate &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents information on a file/folder delete.
///
/// @since 3.16.0
class FileDelete implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileDelete.canParse,
    FileDelete.fromJson,
  );

  FileDelete({
    required this.uri,
  });
  static FileDelete fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return FileDelete(
      uri: uri,
    );
  }

  /// A file:// URI for the location of the file/folder being deleted.
  final String uri;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileDelete');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileDelete &&
        other.runtimeType == FileDelete &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An event describing a file change.
class FileEvent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileEvent.canParse,
    FileEvent.fromJson,
  );

  FileEvent({
    required this.type,
    required this.uri,
  });
  static FileEvent fromJson(Map<String, Object?> json) {
    final typeJson = json['type'];
    final type = FileChangeType.fromJson(typeJson as int);
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return FileEvent(
      type: type,
      uri: uri,
    );
  }

  /// The change type.
  final FileChangeType type;

  /// The file's uri.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['type'] = type.toJson();
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final type = obj['type'];
        if (type == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!FileChangeType.canParse(type, reporter)) {
          reporter.reportError('must be of type FileChangeType');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileEvent &&
        other.runtimeType == FileEvent &&
        type == other.type &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        type,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Capabilities relating to events from file operations by the user in the
/// client.
///
/// These events do not come from the file system, they come from user
/// operations like renaming a file in the UI.
///
/// @since 3.16.0
class FileOperationClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationClientCapabilities.canParse,
    FileOperationClientCapabilities.fromJson,
  );

  FileOperationClientCapabilities({
    this.didCreate,
    this.didDelete,
    this.didRename,
    this.dynamicRegistration,
    this.willCreate,
    this.willDelete,
    this.willRename,
  });
  static FileOperationClientCapabilities fromJson(Map<String, Object?> json) {
    final didCreateJson = json['didCreate'];
    final didCreate = didCreateJson as bool?;
    final didDeleteJson = json['didDelete'];
    final didDelete = didDeleteJson as bool?;
    final didRenameJson = json['didRename'];
    final didRename = didRenameJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final willCreateJson = json['willCreate'];
    final willCreate = willCreateJson as bool?;
    final willDeleteJson = json['willDelete'];
    final willDelete = willDeleteJson as bool?;
    final willRenameJson = json['willRename'];
    final willRename = willRenameJson as bool?;
    return FileOperationClientCapabilities(
      didCreate: didCreate,
      didDelete: didDelete,
      didRename: didRename,
      dynamicRegistration: dynamicRegistration,
      willCreate: willCreate,
      willDelete: willDelete,
      willRename: willRename,
    );
  }

  /// The client has support for sending didCreateFiles notifications.
  final bool? didCreate;

  /// The client has support for sending didDeleteFiles notifications.
  final bool? didDelete;

  /// The client has support for sending didRenameFiles notifications.
  final bool? didRename;

  /// Whether the client supports dynamic registration for file
  /// requests/notifications.
  final bool? dynamicRegistration;

  /// The client has support for sending willCreateFiles requests.
  final bool? willCreate;

  /// The client has support for sending willDeleteFiles requests.
  final bool? willDelete;

  /// The client has support for sending willRenameFiles requests.
  final bool? willRename;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (didCreate != null) {
      result['didCreate'] = didCreate;
    }
    if (didDelete != null) {
      result['didDelete'] = didDelete;
    }
    if (didRename != null) {
      result['didRename'] = didRename;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (willCreate != null) {
      result['willCreate'] = willCreate;
    }
    if (willDelete != null) {
      result['willDelete'] = willDelete;
    }
    if (willRename != null) {
      result['willRename'] = willRename;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('didCreate');
      try {
        final didCreate = obj['didCreate'];
        if (didCreate != null && didCreate is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didDelete');
      try {
        final didDelete = obj['didDelete'];
        if (didDelete != null && didDelete is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didRename');
      try {
        final didRename = obj['didRename'];
        if (didRename != null && didRename is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willCreate');
      try {
        final willCreate = obj['willCreate'];
        if (willCreate != null && willCreate is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willDelete');
      try {
        final willDelete = obj['willDelete'];
        if (willDelete != null && willDelete is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willRename');
      try {
        final willRename = obj['willRename'];
        if (willRename != null && willRename is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationClientCapabilities &&
        other.runtimeType == FileOperationClientCapabilities &&
        didCreate == other.didCreate &&
        didDelete == other.didDelete &&
        didRename == other.didRename &&
        dynamicRegistration == other.dynamicRegistration &&
        willCreate == other.willCreate &&
        willDelete == other.willDelete &&
        willRename == other.willRename;
  }

  @override
  int get hashCode => Object.hash(
        didCreate,
        didDelete,
        didRename,
        dynamicRegistration,
        willCreate,
        willDelete,
        willRename,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A filter to describe in which file operation requests or notifications the
/// server is interested in receiving.
///
/// @since 3.16.0
class FileOperationFilter implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationFilter.canParse,
    FileOperationFilter.fromJson,
  );

  FileOperationFilter({
    required this.pattern,
    this.scheme,
  });
  static FileOperationFilter fromJson(Map<String, Object?> json) {
    final patternJson = json['pattern'];
    final pattern =
        FileOperationPattern.fromJson(patternJson as Map<String, Object?>);
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return FileOperationFilter(
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The actual file operation pattern.
  final FileOperationPattern pattern;

  /// A Uri scheme like `file` or `untitled`.
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['pattern'] = pattern.toJson();
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('pattern');
      try {
        if (!obj.containsKey('pattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final pattern = obj['pattern'];
        if (pattern == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!FileOperationPattern.canParse(pattern, reporter)) {
          reporter.reportError('must be of type FileOperationPattern');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationFilter');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationFilter &&
        other.runtimeType == FileOperationFilter &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Options for notifications/requests for user operations on files.
///
/// @since 3.16.0
class FileOperationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationOptions.canParse,
    FileOperationOptions.fromJson,
  );

  FileOperationOptions({
    this.didCreate,
    this.didDelete,
    this.didRename,
    this.willCreate,
    this.willDelete,
    this.willRename,
  });
  static FileOperationOptions fromJson(Map<String, Object?> json) {
    final didCreateJson = json['didCreate'];
    final didCreate = didCreateJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didCreateJson as Map<String, Object?>)
        : null;
    final didDeleteJson = json['didDelete'];
    final didDelete = didDeleteJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didDeleteJson as Map<String, Object?>)
        : null;
    final didRenameJson = json['didRename'];
    final didRename = didRenameJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didRenameJson as Map<String, Object?>)
        : null;
    final willCreateJson = json['willCreate'];
    final willCreate = willCreateJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willCreateJson as Map<String, Object?>)
        : null;
    final willDeleteJson = json['willDelete'];
    final willDelete = willDeleteJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willDeleteJson as Map<String, Object?>)
        : null;
    final willRenameJson = json['willRename'];
    final willRename = willRenameJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willRenameJson as Map<String, Object?>)
        : null;
    return FileOperationOptions(
      didCreate: didCreate,
      didDelete: didDelete,
      didRename: didRename,
      willCreate: willCreate,
      willDelete: willDelete,
      willRename: willRename,
    );
  }

  /// The server is interested in receiving didCreateFiles notifications.
  final FileOperationRegistrationOptions? didCreate;

  /// The server is interested in receiving didDeleteFiles file notifications.
  final FileOperationRegistrationOptions? didDelete;

  /// The server is interested in receiving didRenameFiles notifications.
  final FileOperationRegistrationOptions? didRename;

  /// The server is interested in receiving willCreateFiles requests.
  final FileOperationRegistrationOptions? willCreate;

  /// The server is interested in receiving willDeleteFiles file requests.
  final FileOperationRegistrationOptions? willDelete;

  /// The server is interested in receiving willRenameFiles requests.
  final FileOperationRegistrationOptions? willRename;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (didCreate != null) {
      result['didCreate'] = didCreate?.toJson();
    }
    if (didDelete != null) {
      result['didDelete'] = didDelete?.toJson();
    }
    if (didRename != null) {
      result['didRename'] = didRename?.toJson();
    }
    if (willCreate != null) {
      result['willCreate'] = willCreate?.toJson();
    }
    if (willDelete != null) {
      result['willDelete'] = willDelete?.toJson();
    }
    if (willRename != null) {
      result['willRename'] = willRename?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('didCreate');
      try {
        final didCreate = obj['didCreate'];
        if (didCreate != null &&
            !FileOperationRegistrationOptions.canParse(didCreate, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didDelete');
      try {
        final didDelete = obj['didDelete'];
        if (didDelete != null &&
            !FileOperationRegistrationOptions.canParse(didDelete, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didRename');
      try {
        final didRename = obj['didRename'];
        if (didRename != null &&
            !FileOperationRegistrationOptions.canParse(didRename, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willCreate');
      try {
        final willCreate = obj['willCreate'];
        if (willCreate != null &&
            !FileOperationRegistrationOptions.canParse(willCreate, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willDelete');
      try {
        final willDelete = obj['willDelete'];
        if (willDelete != null &&
            !FileOperationRegistrationOptions.canParse(willDelete, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willRename');
      try {
        final willRename = obj['willRename'];
        if (willRename != null &&
            !FileOperationRegistrationOptions.canParse(willRename, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationOptions &&
        other.runtimeType == FileOperationOptions &&
        didCreate == other.didCreate &&
        didDelete == other.didDelete &&
        didRename == other.didRename &&
        willCreate == other.willCreate &&
        willDelete == other.willDelete &&
        willRename == other.willRename;
  }

  @override
  int get hashCode => Object.hash(
        didCreate,
        didDelete,
        didRename,
        willCreate,
        willDelete,
        willRename,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A pattern to describe in which file operation requests or notifications the
/// server is interested in receiving.
///
/// @since 3.16.0
class FileOperationPattern implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationPattern.canParse,
    FileOperationPattern.fromJson,
  );

  FileOperationPattern({
    required this.glob,
    this.matches,
    this.options,
  });
  static FileOperationPattern fromJson(Map<String, Object?> json) {
    final globJson = json['glob'];
    final glob = globJson as String;
    final matchesJson = json['matches'];
    final matches = matchesJson != null
        ? FileOperationPatternKind.fromJson(matchesJson as String)
        : null;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? FileOperationPatternOptions.fromJson(
            optionsJson as Map<String, Object?>)
        : null;
    return FileOperationPattern(
      glob: glob,
      matches: matches,
      options: options,
    );
  }

  /// The glob pattern to match. Glob patterns can have the following syntax:
  /// - `*` to match one or more characters in a path segment
  /// - `?` to match on one character in a path segment
  /// - `**` to match any number of path segments, including none
  /// - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}`
  /// matches all TypeScript and JavaScript files)
  /// - `[]` to declare a range of characters to match in a path segment (e.g.,
  /// `example.[0-9]` to match on `example.0`, `example.1`, …)
  /// - `[!...]` to negate a range of characters to match in a path segment
  /// (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not
  /// `example.0`)
  final String glob;

  /// Whether to match files or folders with this pattern.
  ///
  /// Matches both if undefined.
  final FileOperationPatternKind? matches;

  /// Additional options used during matching.
  final FileOperationPatternOptions? options;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['glob'] = glob;
    if (matches != null) {
      result['matches'] = matches?.toJson();
    }
    if (options != null) {
      result['options'] = options?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('glob');
      try {
        if (!obj.containsKey('glob')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final glob = obj['glob'];
        if (glob == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (glob is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('matches');
      try {
        final matches = obj['matches'];
        if (matches != null &&
            !FileOperationPatternKind.canParse(matches, reporter)) {
          reporter.reportError('must be of type FileOperationPatternKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        final options = obj['options'];
        if (options != null &&
            !FileOperationPatternOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type FileOperationPatternOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationPattern');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationPattern &&
        other.runtimeType == FileOperationPattern &&
        glob == other.glob &&
        matches == other.matches &&
        options == other.options;
  }

  @override
  int get hashCode => Object.hash(
        glob,
        matches,
        options,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A pattern kind describing if a glob pattern matches a file a folder or both.
///
/// @since 3.16.0
class FileOperationPatternKind implements ToJsonable {
  const FileOperationPatternKind(this._value);
  const FileOperationPatternKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// The pattern matches a file only.
  static const file = FileOperationPatternKind('file');

  /// The pattern matches a folder only.
  static const folder = FileOperationPatternKind('folder');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FileOperationPatternKind && other._value == _value;
}

/// Matching options for the file operation pattern.
///
/// @since 3.16.0
class FileOperationPatternOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationPatternOptions.canParse,
    FileOperationPatternOptions.fromJson,
  );

  FileOperationPatternOptions({
    this.ignoreCase,
  });
  static FileOperationPatternOptions fromJson(Map<String, Object?> json) {
    final ignoreCaseJson = json['ignoreCase'];
    final ignoreCase = ignoreCaseJson as bool?;
    return FileOperationPatternOptions(
      ignoreCase: ignoreCase,
    );
  }

  /// The pattern should be matched ignoring casing.
  final bool? ignoreCase;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (ignoreCase != null) {
      result['ignoreCase'] = ignoreCase;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ignoreCase');
      try {
        final ignoreCase = obj['ignoreCase'];
        if (ignoreCase != null && ignoreCase is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationPatternOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationPatternOptions &&
        other.runtimeType == FileOperationPatternOptions &&
        ignoreCase == other.ignoreCase;
  }

  @override
  int get hashCode => ignoreCase.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The options to register for file operations.
///
/// @since 3.16.0
class FileOperationRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationRegistrationOptions.canParse,
    FileOperationRegistrationOptions.fromJson,
  );

  FileOperationRegistrationOptions({
    required this.filters,
  });
  static FileOperationRegistrationOptions fromJson(Map<String, Object?> json) {
    final filtersJson = json['filters'];
    final filters = (filtersJson as List<Object?>)
        .map((item) =>
            FileOperationFilter.fromJson(item as Map<String, Object?>))
        .toList();
    return FileOperationRegistrationOptions(
      filters: filters,
    );
  }

  /// The actual filters.
  final List<FileOperationFilter> filters;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['filters'] = filters.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('filters');
      try {
        if (!obj.containsKey('filters')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final filters = obj['filters'];
        if (filters == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (filters is! List<Object?> ||
            filters
                .any((item) => !FileOperationFilter.canParse(item, reporter))) {
          reporter.reportError('must be of type List<FileOperationFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationRegistrationOptions &&
        other.runtimeType == FileOperationRegistrationOptions &&
        listEqual(filters, other.filters,
            (FileOperationFilter a, FileOperationFilter b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(filters);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents information on a file/folder rename.
///
/// @since 3.16.0
class FileRename implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileRename.canParse,
    FileRename.fromJson,
  );

  FileRename({
    required this.newUri,
    required this.oldUri,
  });
  static FileRename fromJson(Map<String, Object?> json) {
    final newUriJson = json['newUri'];
    final newUri = newUriJson as String;
    final oldUriJson = json['oldUri'];
    final oldUri = oldUriJson as String;
    return FileRename(
      newUri: newUri,
      oldUri: oldUri,
    );
  }

  /// A file:// URI for the new location of the file/folder being renamed.
  final String newUri;

  /// A file:// URI for the original location of the file/folder being renamed.
  final String oldUri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['newUri'] = newUri;
    result['oldUri'] = oldUri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('newUri');
      try {
        if (!obj.containsKey('newUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newUri = obj['newUri'];
        if (newUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('oldUri');
      try {
        if (!obj.containsKey('oldUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final oldUri = obj['oldUri'];
        if (oldUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (oldUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileRename');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileRename &&
        other.runtimeType == FileRename &&
        newUri == other.newUri &&
        oldUri == other.oldUri;
  }

  @override
  int get hashCode => Object.hash(
        newUri,
        oldUri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FileSystemWatcher implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileSystemWatcher.canParse,
    FileSystemWatcher.fromJson,
  );

  FileSystemWatcher({
    required this.globPattern,
    this.kind,
  });
  static FileSystemWatcher fromJson(Map<String, Object?> json) {
    final globPatternJson = json['globPattern'];
    final globPattern = globPatternJson is String
        ? Either2<String, RelativePattern>.t1(globPatternJson)
        : (RelativePattern.canParse(globPatternJson, nullLspJsonReporter)
            ? Either2<String, RelativePattern>.t2(RelativePattern.fromJson(
                globPatternJson as Map<String, Object?>))
            : (throw '''$globPatternJson was not one of (String, RelativePattern)'''));
    final kindJson = json['kind'];
    final kind = kindJson != null ? WatchKind.fromJson(kindJson as int) : null;
    return FileSystemWatcher(
      globPattern: globPattern,
      kind: kind,
    );
  }

  /// The glob pattern to watch. See {@link GlobPattern glob pattern} for more
  /// detail.
  ///
  /// @since 3.17.0 support for relative patterns.
  final Either2<String, RelativePattern> globPattern;

  /// The kind of events of interest. If omitted it defaults to WatchKind.Create
  /// | WatchKind.Change | WatchKind.Delete which is 7.
  final WatchKind? kind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['globPattern'] = globPattern;
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('globPattern');
      try {
        if (!obj.containsKey('globPattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final globPattern = obj['globPattern'];
        if (globPattern == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (globPattern is! String &&
            !RelativePattern.canParse(globPattern, reporter)) {
          reporter
              .reportError('must be of type Either2<String, RelativePattern>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !WatchKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type WatchKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileSystemWatcher');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileSystemWatcher &&
        other.runtimeType == FileSystemWatcher &&
        globPattern == other.globPattern &&
        kind == other.kind;
  }

  @override
  int get hashCode => Object.hash(
        globPattern,
        kind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a folding range. To be valid, start and end line must be bigger
/// than zero and smaller than the number of lines in the document. Clients are
/// free to ignore invalid ranges.
class FoldingRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRange.canParse,
    FoldingRange.fromJson,
  );

  FoldingRange({
    this.collapsedText,
    this.endCharacter,
    required this.endLine,
    this.kind,
    this.startCharacter,
    required this.startLine,
  });
  static FoldingRange fromJson(Map<String, Object?> json) {
    final collapsedTextJson = json['collapsedText'];
    final collapsedText = collapsedTextJson as String?;
    final endCharacterJson = json['endCharacter'];
    final endCharacter = endCharacterJson as int?;
    final endLineJson = json['endLine'];
    final endLine = endLineJson as int;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? FoldingRangeKind.fromJson(kindJson as String) : null;
    final startCharacterJson = json['startCharacter'];
    final startCharacter = startCharacterJson as int?;
    final startLineJson = json['startLine'];
    final startLine = startLineJson as int;
    return FoldingRange(
      collapsedText: collapsedText,
      endCharacter: endCharacter,
      endLine: endLine,
      kind: kind,
      startCharacter: startCharacter,
      startLine: startLine,
    );
  }

  /// The text that the client should show when the specified range is
  /// collapsed. If not defined or not supported by the client, a default will
  /// be chosen by the client.
  ///
  /// @since 3.17.0
  final String? collapsedText;

  /// The zero-based character offset before the folded range ends. If not
  /// defined, defaults to the length of the end line.
  final int? endCharacter;

  /// The zero-based end line of the range to fold. The folded area ends with
  /// the line's last character. To be valid, the end must be zero or larger and
  /// smaller than the number of lines in the document.
  final int endLine;

  /// Describes the kind of the folding range such as `comment' or 'region'. The
  /// kind is used to categorize folding ranges and used by commands like 'Fold
  /// all comments'. See FoldingRangeKind for an enumeration of standardized
  /// kinds.
  final FoldingRangeKind? kind;

  /// The zero-based character offset from where the folded range starts. If not
  /// defined, defaults to the length of the start line.
  final int? startCharacter;

  /// The zero-based start line of the range to fold. The folded area starts
  /// after the line's last character. To be valid, the end must be zero or
  /// larger and smaller than the number of lines in the document.
  final int startLine;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (collapsedText != null) {
      result['collapsedText'] = collapsedText;
    }
    if (endCharacter != null) {
      result['endCharacter'] = endCharacter;
    }
    result['endLine'] = endLine;
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    if (startCharacter != null) {
      result['startCharacter'] = startCharacter;
    }
    result['startLine'] = startLine;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('collapsedText');
      try {
        final collapsedText = obj['collapsedText'];
        if (collapsedText != null && collapsedText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('endCharacter');
      try {
        final endCharacter = obj['endCharacter'];
        if (endCharacter != null && endCharacter is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('endLine');
      try {
        if (!obj.containsKey('endLine')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final endLine = obj['endLine'];
        if (endLine == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (endLine is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !FoldingRangeKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type FoldingRangeKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('startCharacter');
      try {
        final startCharacter = obj['startCharacter'];
        if (startCharacter != null && startCharacter is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('startLine');
      try {
        if (!obj.containsKey('startLine')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final startLine = obj['startLine'];
        if (startLine == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (startLine is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRange &&
        other.runtimeType == FoldingRange &&
        collapsedText == other.collapsedText &&
        endCharacter == other.endCharacter &&
        endLine == other.endLine &&
        kind == other.kind &&
        startCharacter == other.startCharacter &&
        startLine == other.startLine;
  }

  @override
  int get hashCode => Object.hash(
        collapsedText,
        endCharacter,
        endLine,
        kind,
        startCharacter,
        startLine,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeClientCapabilities.canParse,
    FoldingRangeClientCapabilities.fromJson,
  );

  FoldingRangeClientCapabilities({
    this.dynamicRegistration,
    this.foldingRange,
    this.foldingRangeKind,
    this.lineFoldingOnly,
    this.rangeLimit,
  });
  static FoldingRangeClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final foldingRangeJson = json['foldingRange'];
    final foldingRange = foldingRangeJson != null
        ? FoldingRangeClientCapabilitiesFoldingRange.fromJson(
            foldingRangeJson as Map<String, Object?>)
        : null;
    final foldingRangeKindJson = json['foldingRangeKind'];
    final foldingRangeKind = foldingRangeKindJson != null
        ? FoldingRangeClientCapabilitiesFoldingRangeKind.fromJson(
            foldingRangeKindJson as Map<String, Object?>)
        : null;
    final lineFoldingOnlyJson = json['lineFoldingOnly'];
    final lineFoldingOnly = lineFoldingOnlyJson as bool?;
    final rangeLimitJson = json['rangeLimit'];
    final rangeLimit = rangeLimitJson as int?;
    return FoldingRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      foldingRange: foldingRange,
      foldingRangeKind: foldingRangeKind,
      lineFoldingOnly: lineFoldingOnly,
      rangeLimit: rangeLimit,
    );
  }

  /// Whether implementation supports dynamic registration for folding range
  /// providers. If this is set to `true` the client supports the new
  /// `FoldingRangeRegistrationOptions` return value for the corresponding
  /// server capability as well.
  final bool? dynamicRegistration;

  /// Specific options for the folding range.
  ///
  /// @since 3.17.0
  final FoldingRangeClientCapabilitiesFoldingRange? foldingRange;

  /// Specific options for the folding range kind.
  ///
  /// @since 3.17.0
  final FoldingRangeClientCapabilitiesFoldingRangeKind? foldingRangeKind;

  /// If set, the client signals that it only supports folding complete lines.
  /// If set, client will ignore specified `startCharacter` and `endCharacter`
  /// properties in a FoldingRange.
  final bool? lineFoldingOnly;

  /// The maximum number of folding ranges that the client prefers to receive
  /// per document. The value serves as a hint, servers are free to follow the
  /// limit.
  final int? rangeLimit;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (foldingRange != null) {
      result['foldingRange'] = foldingRange?.toJson();
    }
    if (foldingRangeKind != null) {
      result['foldingRangeKind'] = foldingRangeKind?.toJson();
    }
    if (lineFoldingOnly != null) {
      result['lineFoldingOnly'] = lineFoldingOnly;
    }
    if (rangeLimit != null) {
      result['rangeLimit'] = rangeLimit;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRange');
      try {
        final foldingRange = obj['foldingRange'];
        if (foldingRange != null &&
            !FoldingRangeClientCapabilitiesFoldingRange.canParse(
                foldingRange, reporter)) {
          reporter.reportError(
              'must be of type FoldingRangeClientCapabilitiesFoldingRange');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRangeKind');
      try {
        final foldingRangeKind = obj['foldingRangeKind'];
        if (foldingRangeKind != null &&
            !FoldingRangeClientCapabilitiesFoldingRangeKind.canParse(
                foldingRangeKind, reporter)) {
          reporter.reportError(
              'must be of type FoldingRangeClientCapabilitiesFoldingRangeKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('lineFoldingOnly');
      try {
        final lineFoldingOnly = obj['lineFoldingOnly'];
        if (lineFoldingOnly != null && lineFoldingOnly is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rangeLimit');
      try {
        final rangeLimit = obj['rangeLimit'];
        if (rangeLimit != null && rangeLimit is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRangeClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeClientCapabilities &&
        other.runtimeType == FoldingRangeClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        foldingRange == other.foldingRange &&
        foldingRangeKind == other.foldingRangeKind &&
        lineFoldingOnly == other.lineFoldingOnly &&
        rangeLimit == other.rangeLimit;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        foldingRange,
        foldingRangeKind,
        lineFoldingOnly,
        rangeLimit,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeClientCapabilitiesFoldingRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeClientCapabilitiesFoldingRange.canParse,
    FoldingRangeClientCapabilitiesFoldingRange.fromJson,
  );

  FoldingRangeClientCapabilitiesFoldingRange({
    this.collapsedText,
  });
  static FoldingRangeClientCapabilitiesFoldingRange fromJson(
      Map<String, Object?> json) {
    final collapsedTextJson = json['collapsedText'];
    final collapsedText = collapsedTextJson as bool?;
    return FoldingRangeClientCapabilitiesFoldingRange(
      collapsedText: collapsedText,
    );
  }

  /// If set, the client signals that it supports setting collapsedText on
  /// folding ranges to display custom labels instead of the default text.
  ///
  /// @since 3.17.0
  final bool? collapsedText;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (collapsedText != null) {
      result['collapsedText'] = collapsedText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('collapsedText');
      try {
        final collapsedText = obj['collapsedText'];
        if (collapsedText != null && collapsedText is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type FoldingRangeClientCapabilitiesFoldingRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeClientCapabilitiesFoldingRange &&
        other.runtimeType == FoldingRangeClientCapabilitiesFoldingRange &&
        collapsedText == other.collapsedText;
  }

  @override
  int get hashCode => collapsedText.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeClientCapabilitiesFoldingRangeKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeClientCapabilitiesFoldingRangeKind.canParse,
    FoldingRangeClientCapabilitiesFoldingRangeKind.fromJson,
  );

  FoldingRangeClientCapabilitiesFoldingRangeKind({
    this.valueSet,
  });
  static FoldingRangeClientCapabilitiesFoldingRangeKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => FoldingRangeKind.fromJson(item as String))
        .toList();
    return FoldingRangeClientCapabilitiesFoldingRangeKind(
      valueSet: valueSet,
    );
  }

  /// The folding range kind values the client supports. When this property
  /// exists the client also guarantees that it will handle values outside its
  /// set gracefully and falls back to a default value when unknown.
  final List<FoldingRangeKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        final valueSet = obj['valueSet'];
        if (valueSet != null &&
            (valueSet is! List<Object?> ||
                valueSet.any(
                    (item) => !FoldingRangeKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<FoldingRangeKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type FoldingRangeClientCapabilitiesFoldingRangeKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeClientCapabilitiesFoldingRangeKind &&
        other.runtimeType == FoldingRangeClientCapabilitiesFoldingRangeKind &&
        listEqual(valueSet, other.valueSet,
            (FoldingRangeKind a, FoldingRangeKind b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A set of predefined range kinds.
class FoldingRangeKind implements ToJsonable {
  const FoldingRangeKind(this._value);
  const FoldingRangeKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// Folding range for a comment
  static const Comment = FoldingRangeKind('comment');

  /// Folding range for an import or include
  static const Imports = FoldingRangeKind('imports');

  /// Folding range for a region (e.g. `#region`)
  static const Region = FoldingRangeKind('region');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FoldingRangeKind && other._value == _value;
}

class FoldingRangeOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeOptions.canParse,
    FoldingRangeOptions.fromJson,
  );

  FoldingRangeOptions({
    this.workDoneProgress,
  });
  static FoldingRangeOptions fromJson(Map<String, Object?> json) {
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return FoldingRangeOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRangeOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeOptions &&
        other.runtimeType == FoldingRangeOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a FoldingRangeRequest.
class FoldingRangeParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeParams.canParse,
    FoldingRangeParams.fromJson,
  );

  FoldingRangeParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static FoldingRangeParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return FoldingRangeParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeParams &&
        other.runtimeType == FoldingRangeParams &&
        partialResultToken == other.partialResultToken &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeRegistrationOptions
    implements
        FoldingRangeOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeRegistrationOptions.canParse,
    FoldingRangeRegistrationOptions.fromJson,
  );

  FoldingRangeRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static FoldingRangeRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return FoldingRangeRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeRegistrationOptions &&
        other.runtimeType == FoldingRangeRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Value-object describing what options formatting should use.
class FormattingOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FormattingOptions.canParse,
    FormattingOptions.fromJson,
  );

  FormattingOptions({
    this.insertFinalNewline,
    required this.insertSpaces,
    required this.tabSize,
    this.trimFinalNewlines,
    this.trimTrailingWhitespace,
  });
  static FormattingOptions fromJson(Map<String, Object?> json) {
    final insertFinalNewlineJson = json['insertFinalNewline'];
    final insertFinalNewline = insertFinalNewlineJson as bool?;
    final insertSpacesJson = json['insertSpaces'];
    final insertSpaces = insertSpacesJson as bool;
    final tabSizeJson = json['tabSize'];
    final tabSize = tabSizeJson as int;
    final trimFinalNewlinesJson = json['trimFinalNewlines'];
    final trimFinalNewlines = trimFinalNewlinesJson as bool?;
    final trimTrailingWhitespaceJson = json['trimTrailingWhitespace'];
    final trimTrailingWhitespace = trimTrailingWhitespaceJson as bool?;
    return FormattingOptions(
      insertFinalNewline: insertFinalNewline,
      insertSpaces: insertSpaces,
      tabSize: tabSize,
      trimFinalNewlines: trimFinalNewlines,
      trimTrailingWhitespace: trimTrailingWhitespace,
    );
  }

  /// Insert a newline character at the end of the file if one does not exist.
  ///
  /// @since 3.15.0
  final bool? insertFinalNewline;

  /// Prefer spaces over tabs.
  final bool insertSpaces;

  /// Size of a tab in spaces.
  final int tabSize;

  /// Trim all newlines after the final newline at the end of the file.
  ///
  /// @since 3.15.0
  final bool? trimFinalNewlines;

  /// Trim trailing whitespace on a line.
  ///
  /// @since 3.15.0
  final bool? trimTrailingWhitespace;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (insertFinalNewline != null) {
      result['insertFinalNewline'] = insertFinalNewline;
    }
    result['insertSpaces'] = insertSpaces;
    result['tabSize'] = tabSize;
    if (trimFinalNewlines != null) {
      result['trimFinalNewlines'] = trimFinalNewlines;
    }
    if (trimTrailingWhitespace != null) {
      result['trimTrailingWhitespace'] = trimTrailingWhitespace;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('insertFinalNewline');
      try {
        final insertFinalNewline = obj['insertFinalNewline'];
        if (insertFinalNewline != null && insertFinalNewline is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertSpaces');
      try {
        if (!obj.containsKey('insertSpaces')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final insertSpaces = obj['insertSpaces'];
        if (insertSpaces == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (insertSpaces is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tabSize');
      try {
        if (!obj.containsKey('tabSize')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tabSize = obj['tabSize'];
        if (tabSize == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tabSize is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('trimFinalNewlines');
      try {
        final trimFinalNewlines = obj['trimFinalNewlines'];
        if (trimFinalNewlines != null && trimFinalNewlines is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('trimTrailingWhitespace');
      try {
        final trimTrailingWhitespace = obj['trimTrailingWhitespace'];
        if (trimTrailingWhitespace != null && trimTrailingWhitespace is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FormattingOptions &&
        other.runtimeType == FormattingOptions &&
        insertFinalNewline == other.insertFinalNewline &&
        insertSpaces == other.insertSpaces &&
        tabSize == other.tabSize &&
        trimFinalNewlines == other.trimFinalNewlines &&
        trimTrailingWhitespace == other.trimTrailingWhitespace;
  }

  @override
  int get hashCode => Object.hash(
        insertFinalNewline,
        insertSpaces,
        tabSize,
        trimFinalNewlines,
        trimTrailingWhitespace,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A diagnostic report with a full set of problems.
///
/// @since 3.17.0
class FullDocumentDiagnosticReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FullDocumentDiagnosticReport.canParse,
    FullDocumentDiagnosticReport.fromJson,
  );

  FullDocumentDiagnosticReport({
    required this.items,
    this.kind = 'full',
    this.resultId,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static FullDocumentDiagnosticReport fromJson(Map<String, Object?> json) {
    if (WorkspaceFullDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceFullDocumentDiagnosticReport.fromJson(json);
    }
    if (RelatedFullDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return RelatedFullDocumentDiagnosticReport.fromJson(json);
    }
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return FullDocumentDiagnosticReport(
      items: items,
      kind: kind,
      resultId: resultId,
    );
  }

  /// The actual items.
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  final String kind;

  /// An optional result id. If provided it will be sent on the next diagnostic
  /// request for the same document.
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    result['kind'] = kind;
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) => !Diagnostic.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'full') {
          reporter.reportError('must be the literal \'full\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FullDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FullDocumentDiagnosticReport &&
        other.runtimeType == FullDocumentDiagnosticReport &&
        listEqual(items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
        kind == other.kind &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(items),
        kind,
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// General client capabilities.
///
/// @since 3.16.0
class GeneralClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    GeneralClientCapabilities.canParse,
    GeneralClientCapabilities.fromJson,
  );

  GeneralClientCapabilities({
    this.markdown,
    this.positionEncodings,
    this.regularExpressions,
    this.staleRequestSupport,
  });
  static GeneralClientCapabilities fromJson(Map<String, Object?> json) {
    final markdownJson = json['markdown'];
    final markdown = markdownJson != null
        ? MarkdownClientCapabilities.fromJson(
            markdownJson as Map<String, Object?>)
        : null;
    final positionEncodingsJson = json['positionEncodings'];
    final positionEncodings = (positionEncodingsJson as List<Object?>?)
        ?.map((item) => PositionEncodingKind.fromJson(item as String))
        .toList();
    final regularExpressionsJson = json['regularExpressions'];
    final regularExpressions = regularExpressionsJson != null
        ? RegularExpressionsClientCapabilities.fromJson(
            regularExpressionsJson as Map<String, Object?>)
        : null;
    final staleRequestSupportJson = json['staleRequestSupport'];
    final staleRequestSupport = staleRequestSupportJson != null
        ? GeneralClientCapabilitiesStaleRequestSupport.fromJson(
            staleRequestSupportJson as Map<String, Object?>)
        : null;
    return GeneralClientCapabilities(
      markdown: markdown,
      positionEncodings: positionEncodings,
      regularExpressions: regularExpressions,
      staleRequestSupport: staleRequestSupport,
    );
  }

  /// Client capabilities specific to the client's markdown parser.
  ///
  /// @since 3.16.0
  final MarkdownClientCapabilities? markdown;

  /// The position encodings supported by the client. Client and server have to
  /// agree on the same position encoding to ensure that offsets (e.g. character
  /// position in a line) are interpreted the same on both sides.
  ///
  /// To keep the protocol backwards compatible the following applies: if the
  /// value 'utf-16' is missing from the array of position encodings servers can
  /// assume that the client supports UTF-16. UTF-16 is therefore a mandatory
  /// encoding.
  ///
  /// If omitted it defaults to ['utf-16'].
  ///
  /// Implementation considerations: since the conversion from one encoding into
  /// another requires the content of the file / line the conversion is best
  /// done where the file is read which is usually on the server side.
  ///
  /// @since 3.17.0
  final List<PositionEncodingKind>? positionEncodings;

  /// Client capabilities specific to regular expressions.
  ///
  /// @since 3.16.0
  final RegularExpressionsClientCapabilities? regularExpressions;

  /// Client capability that signals how the client handles stale requests (e.g.
  /// a request for which the client will not process the response anymore since
  /// the information is outdated).
  ///
  /// @since 3.17.0
  final GeneralClientCapabilitiesStaleRequestSupport? staleRequestSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (markdown != null) {
      result['markdown'] = markdown?.toJson();
    }
    if (positionEncodings != null) {
      result['positionEncodings'] =
          positionEncodings?.map((item) => item.toJson()).toList();
    }
    if (regularExpressions != null) {
      result['regularExpressions'] = regularExpressions?.toJson();
    }
    if (staleRequestSupport != null) {
      result['staleRequestSupport'] = staleRequestSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('markdown');
      try {
        final markdown = obj['markdown'];
        if (markdown != null &&
            !MarkdownClientCapabilities.canParse(markdown, reporter)) {
          reporter.reportError('must be of type MarkdownClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('positionEncodings');
      try {
        final positionEncodings = obj['positionEncodings'];
        if (positionEncodings != null &&
            (positionEncodings is! List<Object?> ||
                positionEncodings.any((item) =>
                    !PositionEncodingKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<PositionEncodingKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('regularExpressions');
      try {
        final regularExpressions = obj['regularExpressions'];
        if (regularExpressions != null &&
            !RegularExpressionsClientCapabilities.canParse(
                regularExpressions, reporter)) {
          reporter.reportError(
              'must be of type RegularExpressionsClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('staleRequestSupport');
      try {
        final staleRequestSupport = obj['staleRequestSupport'];
        if (staleRequestSupport != null &&
            !GeneralClientCapabilitiesStaleRequestSupport.canParse(
                staleRequestSupport, reporter)) {
          reporter.reportError(
              'must be of type GeneralClientCapabilitiesStaleRequestSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type GeneralClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is GeneralClientCapabilities &&
        other.runtimeType == GeneralClientCapabilities &&
        markdown == other.markdown &&
        listEqual(positionEncodings, other.positionEncodings,
            (PositionEncodingKind a, PositionEncodingKind b) => a == b) &&
        regularExpressions == other.regularExpressions &&
        staleRequestSupport == other.staleRequestSupport;
  }

  @override
  int get hashCode => Object.hash(
        markdown,
        lspHashCode(positionEncodings),
        regularExpressions,
        staleRequestSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class GeneralClientCapabilitiesStaleRequestSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    GeneralClientCapabilitiesStaleRequestSupport.canParse,
    GeneralClientCapabilitiesStaleRequestSupport.fromJson,
  );

  GeneralClientCapabilitiesStaleRequestSupport({
    required this.cancel,
    required this.retryOnContentModified,
  });
  static GeneralClientCapabilitiesStaleRequestSupport fromJson(
      Map<String, Object?> json) {
    final cancelJson = json['cancel'];
    final cancel = cancelJson as bool;
    final retryOnContentModifiedJson = json['retryOnContentModified'];
    final retryOnContentModified = (retryOnContentModifiedJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return GeneralClientCapabilitiesStaleRequestSupport(
      cancel: cancel,
      retryOnContentModified: retryOnContentModified,
    );
  }

  /// The client will actively cancel the request.
  final bool cancel;

  /// The list of requests for which the client will retry the request if it
  /// receives a response with error code `ContentModified`
  final List<String> retryOnContentModified;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cancel'] = cancel;
    result['retryOnContentModified'] = retryOnContentModified;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cancel');
      try {
        if (!obj.containsKey('cancel')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final cancel = obj['cancel'];
        if (cancel == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (cancel is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('retryOnContentModified');
      try {
        if (!obj.containsKey('retryOnContentModified')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final retryOnContentModified = obj['retryOnContentModified'];
        if (retryOnContentModified == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (retryOnContentModified is! List<Object?> ||
            retryOnContentModified.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type GeneralClientCapabilitiesStaleRequestSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is GeneralClientCapabilitiesStaleRequestSupport &&
        other.runtimeType == GeneralClientCapabilitiesStaleRequestSupport &&
        cancel == other.cancel &&
        listEqual(retryOnContentModified, other.retryOnContentModified,
            (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        cancel,
        lspHashCode(retryOnContentModified),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result of a hover request.
class Hover implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Hover.canParse,
    Hover.fromJson,
  );

  Hover({
    required this.contents,
    this.range,
  });
  static Hover fromJson(Map<String, Object?> json) {
    final contentsJson = json['contents'];
    final contents = MarkupContent.canParse(contentsJson, nullLspJsonReporter)
        ? Either2<MarkupContent, String>.t1(
            MarkupContent.fromJson(contentsJson as Map<String, Object?>))
        : (contentsJson is String
            ? Either2<MarkupContent, String>.t2(contentsJson)
            : (throw '''$contentsJson was not one of (MarkupContent, String)'''));
    final rangeJson = json['range'];
    final range = rangeJson != null
        ? Range.fromJson(rangeJson as Map<String, Object?>)
        : null;
    return Hover(
      contents: contents,
      range: range,
    );
  }

  /// The hover's content
  final Either2<MarkupContent, String> contents;

  /// An optional range inside the text document that is used to visualize the
  /// hover, e.g. by changing the background color.
  final Range? range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['contents'] = contents;
    if (range != null) {
      result['range'] = range?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('contents');
      try {
        if (!obj.containsKey('contents')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final contents = obj['contents'];
        if (contents == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MarkupContent.canParse(contents, reporter) &&
            contents is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        final range = obj['range'];
        if (range != null && !Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Hover');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Hover &&
        other.runtimeType == Hover &&
        contents == other.contents &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        contents,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class HoverClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverClientCapabilities.canParse,
    HoverClientCapabilities.fromJson,
  );

  HoverClientCapabilities({
    this.contentFormat,
    this.dynamicRegistration,
  });
  static HoverClientCapabilities fromJson(Map<String, Object?> json) {
    final contentFormatJson = json['contentFormat'];
    final contentFormat = (contentFormatJson as List<Object?>?)
        ?.map((item) => MarkupKind.fromJson(item as String))
        .toList();
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return HoverClientCapabilities(
      contentFormat: contentFormat,
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Client supports the following content formats for the content property.
  /// The order describes the preferred format of the client.
  final List<MarkupKind>? contentFormat;

  /// Whether hover supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (contentFormat != null) {
      result['contentFormat'] =
          contentFormat?.map((item) => item.toJson()).toList();
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('contentFormat');
      try {
        final contentFormat = obj['contentFormat'];
        if (contentFormat != null &&
            (contentFormat is! List<Object?> ||
                contentFormat
                    .any((item) => !MarkupKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<MarkupKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type HoverClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is HoverClientCapabilities &&
        other.runtimeType == HoverClientCapabilities &&
        listEqual(contentFormat, other.contentFormat,
            (MarkupKind a, MarkupKind b) => a == b) &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(contentFormat),
        dynamicRegistration,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Hover options.
class HoverOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverOptions.canParse,
    HoverOptions.fromJson,
  );

  HoverOptions({
    this.workDoneProgress,
  });
  static HoverOptions fromJson(Map<String, Object?> json) {
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return HoverOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type HoverOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is HoverOptions &&
        other.runtimeType == HoverOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a HoverRequest.
class HoverParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverParams.canParse,
    HoverParams.fromJson,
  );

  HoverParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static HoverParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return HoverParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type HoverParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is HoverParams &&
        other.runtimeType == HoverParams &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a HoverRequest.
class HoverRegistrationOptions
    implements HoverOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverRegistrationOptions.canParse,
    HoverRegistrationOptions.fromJson,
  );

  HoverRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static HoverRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return HoverRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type HoverRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is HoverRegistrationOptions &&
        other.runtimeType == HoverRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.6.0
class ImplementationClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationClientCapabilities.canParse,
    ImplementationClientCapabilities.fromJson,
  );

  ImplementationClientCapabilities({
    this.dynamicRegistration,
    this.linkSupport,
  });
  static ImplementationClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final linkSupportJson = json['linkSupport'];
    final linkSupport = linkSupportJson as bool?;
    return ImplementationClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      linkSupport: linkSupport,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `ImplementationRegistrationOptions`
  /// return value for the corresponding server capability as well.
  final bool? dynamicRegistration;

  /// The client supports additional metadata in the form of definition links.
  ///
  /// @since 3.14.0
  final bool? linkSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (linkSupport != null) {
      result['linkSupport'] = linkSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        final linkSupport = obj['linkSupport'];
        if (linkSupport != null && linkSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ImplementationClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ImplementationClientCapabilities &&
        other.runtimeType == ImplementationClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        linkSupport == other.linkSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        linkSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ImplementationOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationOptions.canParse,
    ImplementationOptions.fromJson,
  );

  ImplementationOptions({
    this.workDoneProgress,
  });
  static ImplementationOptions fromJson(Map<String, Object?> json) {
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ImplementationOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ImplementationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ImplementationOptions &&
        other.runtimeType == ImplementationOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ImplementationParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationParams.canParse,
    ImplementationParams.fromJson,
  );

  ImplementationParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static ImplementationParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return ImplementationParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ImplementationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ImplementationParams &&
        other.runtimeType == ImplementationParams &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ImplementationRegistrationOptions
    implements
        ImplementationOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationRegistrationOptions.canParse,
    ImplementationRegistrationOptions.fromJson,
  );

  ImplementationRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static ImplementationRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ImplementationRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ImplementationRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ImplementationRegistrationOptions &&
        other.runtimeType == ImplementationRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The initialize parameters
class InitializeParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeParams.canParse,
    InitializeParams.fromJson,
  );

  InitializeParams({
    required this.capabilities,
    this.clientInfo,
    this.initializationOptions,
    this.locale,
    this.processId,
    this.rootPath,
    this.rootUri,
    this.trace,
    this.workDoneToken,
    this.workspaceFolders,
  });
  static InitializeParams fromJson(Map<String, Object?> json) {
    final capabilitiesJson = json['capabilities'];
    final capabilities =
        ClientCapabilities.fromJson(capabilitiesJson as Map<String, Object?>);
    final clientInfoJson = json['clientInfo'];
    final clientInfo = clientInfoJson != null
        ? InitializeParamsClientInfo.fromJson(
            clientInfoJson as Map<String, Object?>)
        : null;
    final initializationOptionsJson = json['initializationOptions'];
    final initializationOptions = initializationOptionsJson;
    final localeJson = json['locale'];
    final locale = localeJson as String?;
    final processIdJson = json['processId'];
    final processId = processIdJson as int?;
    final rootPathJson = json['rootPath'];
    final rootPath = rootPathJson as String?;
    final rootUriJson = json['rootUri'];
    final rootUri = rootUriJson as String?;
    final traceJson = json['trace'];
    final trace = const {null, 'off', 'messages', 'compact', 'verbose'}
            .contains(traceJson)
        ? traceJson as String?
        : throw '''$traceJson was not one of (null, 'off', 'messages', 'compact', 'verbose')''';
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = (workspaceFoldersJson as List<Object?>?)
        ?.map((item) => WorkspaceFolder.fromJson(item as Map<String, Object?>))
        .toList();
    return InitializeParams(
      capabilities: capabilities,
      clientInfo: clientInfo,
      initializationOptions: initializationOptions,
      locale: locale,
      processId: processId,
      rootPath: rootPath,
      rootUri: rootUri,
      trace: trace,
      workDoneToken: workDoneToken,
      workspaceFolders: workspaceFolders,
    );
  }

  /// The capabilities provided by the client (editor or tool)
  final ClientCapabilities capabilities;

  /// Information about the client
  ///
  /// @since 3.15.0
  final InitializeParamsClientInfo? clientInfo;

  /// User provided initialization options.
  final Object? initializationOptions;

  /// The locale the client is currently showing the user interface in. This
  /// must not necessarily be the locale of the operating system.
  ///
  /// Uses IETF language tags as the value's syntax (See
  /// https://en.wikipedia.org/wiki/IETF_language_tag)
  ///
  /// @since 3.16.0
  final String? locale;

  /// The process Id of the parent process that started the server.
  ///
  /// Is `null` if the process has not been started by another process. If the
  /// parent process is not alive then the server should exit.
  final int? processId;

  /// The rootPath of the workspace. Is null if no folder is open.
  ///
  /// @deprecated in favour of rootUri.
  final String? rootPath;

  /// The rootUri of the workspace. Is null if no folder is open. If both
  /// `rootPath` and `rootUri` are set `rootUri` wins.
  ///
  /// @deprecated in favour of workspaceFolders.
  final String? rootUri;

  /// The initial trace setting. If omitted trace is disabled ('off').
  final String? trace;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  /// The workspace folders configured in the client when the server starts.
  ///
  /// This property is only available if the client supports workspace folders.
  /// It can be `null` if the client supports workspace folders but none are
  /// configured.
  ///
  /// @since 3.6.0
  final List<WorkspaceFolder>? workspaceFolders;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['capabilities'] = capabilities.toJson();
    if (clientInfo != null) {
      result['clientInfo'] = clientInfo?.toJson();
    }
    if (initializationOptions != null) {
      result['initializationOptions'] = initializationOptions;
    }
    if (locale != null) {
      result['locale'] = locale;
    }
    result['processId'] = processId;
    if (rootPath != null) {
      result['rootPath'] = rootPath;
    }
    result['rootUri'] = rootUri;
    if (trace != null) {
      result['trace'] = trace;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    if (workspaceFolders != null) {
      result['workspaceFolders'] =
          workspaceFolders?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('capabilities');
      try {
        if (!obj.containsKey('capabilities')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final capabilities = obj['capabilities'];
        if (capabilities == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!ClientCapabilities.canParse(capabilities, reporter)) {
          reporter.reportError('must be of type ClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('clientInfo');
      try {
        final clientInfo = obj['clientInfo'];
        if (clientInfo != null &&
            !InitializeParamsClientInfo.canParse(clientInfo, reporter)) {
          reporter.reportError('must be of type InitializeParamsClientInfo');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('locale');
      try {
        final locale = obj['locale'];
        if (locale != null && locale is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('processId');
      try {
        if (!obj.containsKey('processId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final processId = obj['processId'];
        if (processId != null && processId is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rootPath');
      try {
        final rootPath = obj['rootPath'];
        if (rootPath != null && rootPath is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rootUri');
      try {
        if (!obj.containsKey('rootUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final rootUri = obj['rootUri'];
        if (rootUri != null && rootUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('trace');
      try {
        final trace = obj['trace'];
        if (trace != null &&
            trace != 'off' &&
            trace != 'messages' &&
            trace != 'compact' &&
            trace != 'verbose') {
          reporter.reportError(
              'must be one of the literals \'off\', \'messages\', \'compact\', \'verbose\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceFolders');
      try {
        final workspaceFolders = obj['workspaceFolders'];
        if (workspaceFolders != null &&
            (workspaceFolders is! List<Object?> ||
                workspaceFolders.any(
                    (item) => !WorkspaceFolder.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InitializeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializeParams &&
        other.runtimeType == InitializeParams &&
        capabilities == other.capabilities &&
        clientInfo == other.clientInfo &&
        initializationOptions == other.initializationOptions &&
        locale == other.locale &&
        processId == other.processId &&
        rootPath == other.rootPath &&
        rootUri == other.rootUri &&
        trace == other.trace &&
        workDoneToken == other.workDoneToken &&
        listEqual(workspaceFolders, other.workspaceFolders,
            (WorkspaceFolder a, WorkspaceFolder b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        capabilities,
        clientInfo,
        initializationOptions,
        locale,
        processId,
        rootPath,
        rootUri,
        trace,
        workDoneToken,
        lspHashCode(workspaceFolders),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InitializeParamsClientInfo implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeParamsClientInfo.canParse,
    InitializeParamsClientInfo.fromJson,
  );

  InitializeParamsClientInfo({
    required this.name,
    this.version,
  });
  static InitializeParamsClientInfo fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return InitializeParamsClientInfo(
      name: name,
      version: version,
    );
  }

  /// The name of the client as defined by the client.
  final String name;

  /// The client's version as defined by the client.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['name'] = name;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InitializeParamsClientInfo');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializeParamsClientInfo &&
        other.runtimeType == InitializeParamsClientInfo &&
        name == other.name &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        name,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result returned from an initialize request.
class InitializeResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeResult.canParse,
    InitializeResult.fromJson,
  );

  InitializeResult({
    required this.capabilities,
    this.serverInfo,
  });
  static InitializeResult fromJson(Map<String, Object?> json) {
    final capabilitiesJson = json['capabilities'];
    final capabilities =
        ServerCapabilities.fromJson(capabilitiesJson as Map<String, Object?>);
    final serverInfoJson = json['serverInfo'];
    final serverInfo = serverInfoJson != null
        ? InitializeResultServerInfo.fromJson(
            serverInfoJson as Map<String, Object?>)
        : null;
    return InitializeResult(
      capabilities: capabilities,
      serverInfo: serverInfo,
    );
  }

  /// The capabilities the language server provides.
  final ServerCapabilities capabilities;

  /// Information about the server.
  ///
  /// @since 3.15.0
  final InitializeResultServerInfo? serverInfo;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['capabilities'] = capabilities.toJson();
    if (serverInfo != null) {
      result['serverInfo'] = serverInfo?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('capabilities');
      try {
        if (!obj.containsKey('capabilities')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final capabilities = obj['capabilities'];
        if (capabilities == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!ServerCapabilities.canParse(capabilities, reporter)) {
          reporter.reportError('must be of type ServerCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('serverInfo');
      try {
        final serverInfo = obj['serverInfo'];
        if (serverInfo != null &&
            !InitializeResultServerInfo.canParse(serverInfo, reporter)) {
          reporter.reportError('must be of type InitializeResultServerInfo');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InitializeResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializeResult &&
        other.runtimeType == InitializeResult &&
        capabilities == other.capabilities &&
        serverInfo == other.serverInfo;
  }

  @override
  int get hashCode => Object.hash(
        capabilities,
        serverInfo,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InitializeResultServerInfo implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeResultServerInfo.canParse,
    InitializeResultServerInfo.fromJson,
  );

  InitializeResultServerInfo({
    required this.name,
    this.version,
  });
  static InitializeResultServerInfo fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return InitializeResultServerInfo(
      name: name,
      version: version,
    );
  }

  /// The name of the server as defined by the server.
  final String name;

  /// The server's version as defined by the server.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['name'] = name;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InitializeResultServerInfo');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializeResultServerInfo &&
        other.runtimeType == InitializeResultServerInfo &&
        name == other.name &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        name,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InitializedParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializedParams.canParse,
    InitializedParams.fromJson,
  );

  static InitializedParams fromJson(Map<String, Object?> json) {
    return InitializedParams();
  }

  @override
  Map<String, Object?> toJson() => {};

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError('must be of type InitializedParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializedParams && other.runtimeType == InitializedParams;
  }

  @override
  int get hashCode => 42;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint information.
///
/// @since 3.17.0
class InlayHint implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHint.canParse,
    InlayHint.fromJson,
  );

  InlayHint({
    this.data,
    this.kind,
    required this.label,
    this.paddingLeft,
    this.paddingRight,
    required this.position,
    this.textEdits,
    this.tooltip,
  });
  static InlayHint fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? InlayHintKind.fromJson(kindJson as int) : null;
    final labelJson = json['label'];
    final label = labelJson is List<Object?> &&
            labelJson.every((item) =>
                InlayHintLabelPart.canParse(item, nullLspJsonReporter))
        ? Either2<List<InlayHintLabelPart>, String>.t1(labelJson
            .map((item) =>
                InlayHintLabelPart.fromJson(item as Map<String, Object?>))
            .toList())
        : (labelJson is String
            ? Either2<List<InlayHintLabelPart>, String>.t2(labelJson)
            : (throw '''$labelJson was not one of (List<InlayHintLabelPart>, String)'''));
    final paddingLeftJson = json['paddingLeft'];
    final paddingLeft = paddingLeftJson as bool?;
    final paddingRightJson = json['paddingRight'];
    final paddingRight = paddingRightJson as bool?;
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textEditsJson = json['textEdits'];
    final textEdits = (textEditsJson as List<Object?>?)
        ?.map((item) => TextEdit.fromJson(item as Map<String, Object?>))
        .toList();
    final tooltipJson = json['tooltip'];
    final tooltip = tooltipJson == null
        ? null
        : (MarkupContent.canParse(tooltipJson, nullLspJsonReporter)
            ? Either2<MarkupContent, String>.t1(
                MarkupContent.fromJson(tooltipJson as Map<String, Object?>))
            : (tooltipJson is String
                ? Either2<MarkupContent, String>.t2(tooltipJson)
                : (throw '''$tooltipJson was not one of (MarkupContent, String)''')));
    return InlayHint(
      data: data,
      kind: kind,
      label: label,
      paddingLeft: paddingLeft,
      paddingRight: paddingRight,
      position: position,
      textEdits: textEdits,
      tooltip: tooltip,
    );
  }

  /// A data entry field that is preserved on an inlay hint between a
  /// `textDocument/inlayHint` and a `inlayHint/resolve` request.
  final Object? data;

  /// The kind of this hint. Can be omitted in which case the client should fall
  /// back to a reasonable default.
  final InlayHintKind? kind;

  /// The label of this hint. A human readable string or an array of
  /// InlayHintLabelPart label parts.
  ///
  /// *Note* that neither the string nor the label part can be empty.
  final Either2<List<InlayHintLabelPart>, String> label;

  /// Render padding before the hint.
  ///
  /// Note: Padding should use the editor's background color, not the background
  /// color of the hint itself. That means padding can be used to visually
  /// align/separate an inlay hint.
  final bool? paddingLeft;

  /// Render padding after the hint.
  ///
  /// Note: Padding should use the editor's background color, not the background
  /// color of the hint itself. That means padding can be used to visually
  /// align/separate an inlay hint.
  final bool? paddingRight;

  /// The position of this hint.
  final Position position;

  /// Optional text edits that are performed when accepting this inlay hint.
  ///
  /// *Note* that edits are expected to change the document so that the inlay
  /// hint (or its nearest variant) is now part of the document and the inlay
  /// hint itself is now obsolete.
  final List<TextEdit>? textEdits;

  /// The tooltip text when you hover over this item.
  final Either2<MarkupContent, String>? tooltip;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['label'] = label;
    if (paddingLeft != null) {
      result['paddingLeft'] = paddingLeft;
    }
    if (paddingRight != null) {
      result['paddingRight'] = paddingRight;
    }
    result['position'] = position.toJson();
    if (textEdits != null) {
      result['textEdits'] = textEdits?.map((item) => item.toJson()).toList();
    }
    if (tooltip != null) {
      result['tooltip'] = tooltip;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !InlayHintKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type InlayHintKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final label = obj['label'];
        if (label == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (label is! List<Object?> ||
            label.any((item) => !InlayHintLabelPart.canParse(item, reporter)) &&
                label is! String) {
          reporter.reportError(
              'must be of type Either2<List<InlayHintLabelPart>, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('paddingLeft');
      try {
        final paddingLeft = obj['paddingLeft'];
        if (paddingLeft != null && paddingLeft is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('paddingRight');
      try {
        final paddingRight = obj['paddingRight'];
        if (paddingRight != null && paddingRight is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textEdits');
      try {
        final textEdits = obj['textEdits'];
        if (textEdits != null &&
            (textEdits is! List<Object?> ||
                textEdits.any((item) => !TextEdit.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<TextEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tooltip');
      try {
        final tooltip = obj['tooltip'];
        if (tooltip != null &&
            !MarkupContent.canParse(tooltip, reporter) &&
            tooltip is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHint');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHint &&
        other.runtimeType == InlayHint &&
        data == other.data &&
        kind == other.kind &&
        label == other.label &&
        paddingLeft == other.paddingLeft &&
        paddingRight == other.paddingRight &&
        position == other.position &&
        listEqual(
            textEdits, other.textEdits, (TextEdit a, TextEdit b) => a == b) &&
        tooltip == other.tooltip;
  }

  @override
  int get hashCode => Object.hash(
        data,
        kind,
        label,
        paddingLeft,
        paddingRight,
        position,
        lspHashCode(textEdits),
        tooltip,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint client capabilities.
///
/// @since 3.17.0
class InlayHintClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintClientCapabilities.canParse,
    InlayHintClientCapabilities.fromJson,
  );

  InlayHintClientCapabilities({
    this.dynamicRegistration,
    this.resolveSupport,
  });
  static InlayHintClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final resolveSupportJson = json['resolveSupport'];
    final resolveSupport = resolveSupportJson != null
        ? InlayHintClientCapabilitiesResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    return InlayHintClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      resolveSupport: resolveSupport,
    );
  }

  /// Whether inlay hints support dynamic registration.
  final bool? dynamicRegistration;

  /// Indicates which properties a client can resolve lazily on an inlay hint.
  final InlayHintClientCapabilitiesResolveSupport? resolveSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (resolveSupport != null) {
      result['resolveSupport'] = resolveSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveSupport');
      try {
        final resolveSupport = obj['resolveSupport'];
        if (resolveSupport != null &&
            !InlayHintClientCapabilitiesResolveSupport.canParse(
                resolveSupport, reporter)) {
          reporter.reportError(
              'must be of type InlayHintClientCapabilitiesResolveSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintClientCapabilities &&
        other.runtimeType == InlayHintClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        resolveSupport == other.resolveSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        resolveSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InlayHintClientCapabilitiesResolveSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintClientCapabilitiesResolveSupport.canParse,
    InlayHintClientCapabilitiesResolveSupport.fromJson,
  );

  InlayHintClientCapabilitiesResolveSupport({
    required this.properties,
  });
  static InlayHintClientCapabilitiesResolveSupport fromJson(
      Map<String, Object?> json) {
    final propertiesJson = json['properties'];
    final properties = (propertiesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return InlayHintClientCapabilitiesResolveSupport(
      properties: properties,
    );
  }

  /// The properties that a client can resolve lazily.
  final List<String> properties;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('properties');
      try {
        if (!obj.containsKey('properties')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final properties = obj['properties'];
        if (properties == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (properties is! List<Object?> ||
            properties.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type InlayHintClientCapabilitiesResolveSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintClientCapabilitiesResolveSupport &&
        other.runtimeType == InlayHintClientCapabilitiesResolveSupport &&
        listEqual(properties, other.properties, (String a, String b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(properties);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint kinds.
///
/// @since 3.17.0
class InlayHintKind implements ToJsonable {
  const InlayHintKind(this._value);
  const InlayHintKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// An inlay hint that is for a parameter.
  static const Parameter = InlayHintKind(2);

  /// An inlay hint that for a type annotation.
  static const Type = InlayHintKind(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is InlayHintKind && other._value == _value;
}

/// An inlay hint label part allows for interactive and composite labels of
/// inlay hints.
///
/// @since 3.17.0
class InlayHintLabelPart implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintLabelPart.canParse,
    InlayHintLabelPart.fromJson,
  );

  InlayHintLabelPart({
    this.command,
    this.location,
    this.tooltip,
    required this.value,
  });
  static InlayHintLabelPart fromJson(Map<String, Object?> json) {
    final commandJson = json['command'];
    final command = commandJson != null
        ? Command.fromJson(commandJson as Map<String, Object?>)
        : null;
    final locationJson = json['location'];
    final location = locationJson != null
        ? Location.fromJson(locationJson as Map<String, Object?>)
        : null;
    final tooltipJson = json['tooltip'];
    final tooltip = tooltipJson == null
        ? null
        : (MarkupContent.canParse(tooltipJson, nullLspJsonReporter)
            ? Either2<MarkupContent, String>.t1(
                MarkupContent.fromJson(tooltipJson as Map<String, Object?>))
            : (tooltipJson is String
                ? Either2<MarkupContent, String>.t2(tooltipJson)
                : (throw '''$tooltipJson was not one of (MarkupContent, String)''')));
    final valueJson = json['value'];
    final value = valueJson as String;
    return InlayHintLabelPart(
      command: command,
      location: location,
      tooltip: tooltip,
      value: value,
    );
  }

  /// An optional command for this label part.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final Command? command;

  /// An optional source code location that represents this label part.
  ///
  /// The editor will use this location for the hover and for code navigation
  /// features: This part will become a clickable link that resolves to the
  /// definition of the symbol at the given location (not necessarily the
  /// location itself), it shows the hover that shows at the given location,
  /// and it shows a context menu with further code navigation commands.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final Location? location;

  /// The tooltip text when you hover over this label part. Depending on the
  /// client capability `inlayHint.resolveSupport` clients might resolve this
  /// property late using the resolve request.
  final Either2<MarkupContent, String>? tooltip;

  /// The value of this label part.
  final String value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (command != null) {
      result['command'] = command?.toJson();
    }
    if (location != null) {
      result['location'] = location?.toJson();
    }
    if (tooltip != null) {
      result['tooltip'] = tooltip;
    }
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('command');
      try {
        final command = obj['command'];
        if (command != null && !Command.canParse(command, reporter)) {
          reporter.reportError('must be of type Command');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('location');
      try {
        final location = obj['location'];
        if (location != null && !Location.canParse(location, reporter)) {
          reporter.reportError('must be of type Location');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tooltip');
      try {
        final tooltip = obj['tooltip'];
        if (tooltip != null &&
            !MarkupContent.canParse(tooltip, reporter) &&
            tooltip is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final value = obj['value'];
        if (value == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (value is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintLabelPart');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintLabelPart &&
        other.runtimeType == InlayHintLabelPart &&
        command == other.command &&
        location == other.location &&
        tooltip == other.tooltip &&
        value == other.value;
  }

  @override
  int get hashCode => Object.hash(
        command,
        location,
        tooltip,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint options used during static registration.
///
/// @since 3.17.0
class InlayHintOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintOptions.canParse,
    InlayHintOptions.fromJson,
  );

  InlayHintOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static InlayHintOptions fromJson(Map<String, Object?> json) {
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlayHintOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The server provides support to resolve additional information for an inlay
  /// hint item.
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintOptions &&
        other.runtimeType == InlayHintOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in inlay hint requests.
///
/// @since 3.17.0
class InlayHintParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintParams.canParse,
    InlayHintParams.fromJson,
  );

  InlayHintParams({
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static InlayHintParams fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return InlayHintParams(
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The document range for which inlay hints should be computed.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintParams &&
        other.runtimeType == InlayHintParams &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint options used during static or dynamic registration.
///
/// @since 3.17.0
class InlayHintRegistrationOptions
    implements
        InlayHintOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintRegistrationOptions.canParse,
    InlayHintRegistrationOptions.fromJson,
  );

  InlayHintRegistrationOptions({
    this.documentSelector,
    this.id,
    this.resolveProvider,
    this.workDoneProgress,
  });
  static InlayHintRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlayHintRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// The server provides support to resolve additional information for an inlay
  /// hint item.
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintRegistrationOptions &&
        other.runtimeType == InlayHintRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client workspace capabilities specific to inlay hints.
///
/// @since 3.17.0
class InlayHintWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintWorkspaceClientCapabilities.canParse,
    InlayHintWorkspaceClientCapabilities.fromJson,
  );

  InlayHintWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static InlayHintWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return InlayHintWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// inlay hints currently shown. It should be used with absolute care and is
  /// useful for situation where a server for example detects a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('refreshSupport');
      try {
        final refreshSupport = obj['refreshSupport'];
        if (refreshSupport != null && refreshSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type InlayHintWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintWorkspaceClientCapabilities &&
        other.runtimeType == InlayHintWorkspaceClientCapabilities &&
        refreshSupport == other.refreshSupport;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to inline values.
///
/// @since 3.17.0
class InlineValueClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueClientCapabilities.canParse,
    InlineValueClientCapabilities.fromJson,
  );

  InlineValueClientCapabilities({
    this.dynamicRegistration,
  });
  static InlineValueClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return InlineValueClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration for inline value
  /// providers.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueClientCapabilities &&
        other.runtimeType == InlineValueClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.17.0
class InlineValueContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueContext.canParse,
    InlineValueContext.fromJson,
  );

  InlineValueContext({
    required this.frameId,
    required this.stoppedLocation,
  });
  static InlineValueContext fromJson(Map<String, Object?> json) {
    final frameIdJson = json['frameId'];
    final frameId = frameIdJson as int;
    final stoppedLocationJson = json['stoppedLocation'];
    final stoppedLocation =
        Range.fromJson(stoppedLocationJson as Map<String, Object?>);
    return InlineValueContext(
      frameId: frameId,
      stoppedLocation: stoppedLocation,
    );
  }

  /// The stack frame (as a DAP Id) where the execution has stopped.
  final int frameId;

  /// The document range where execution has stopped. Typically the end position
  /// of the range denotes the line where the inline values are shown.
  final Range stoppedLocation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['frameId'] = frameId;
    result['stoppedLocation'] = stoppedLocation.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('frameId');
      try {
        if (!obj.containsKey('frameId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final frameId = obj['frameId'];
        if (frameId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (frameId is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('stoppedLocation');
      try {
        if (!obj.containsKey('stoppedLocation')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final stoppedLocation = obj['stoppedLocation'];
        if (stoppedLocation == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(stoppedLocation, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueContext &&
        other.runtimeType == InlineValueContext &&
        frameId == other.frameId &&
        stoppedLocation == other.stoppedLocation;
  }

  @override
  int get hashCode => Object.hash(
        frameId,
        stoppedLocation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provide an inline value through an expression evaluation. If only a range is
/// specified, the expression will be extracted from the underlying document. An
/// optional expression can be used to override the extracted expression.
///
/// @since 3.17.0
class InlineValueEvaluatableExpression implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueEvaluatableExpression.canParse,
    InlineValueEvaluatableExpression.fromJson,
  );

  InlineValueEvaluatableExpression({
    this.expression,
    required this.range,
  });
  static InlineValueEvaluatableExpression fromJson(Map<String, Object?> json) {
    final expressionJson = json['expression'];
    final expression = expressionJson as String?;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return InlineValueEvaluatableExpression(
      expression: expression,
      range: range,
    );
  }

  /// If specified the expression overrides the extracted expression.
  final String? expression;

  /// The document range for which the inline value applies. The range is used
  /// to extract the evaluatable expression from the underlying document.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (expression != null) {
      result['expression'] = expression;
    }
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('expression');
      try {
        final expression = obj['expression'];
        if (expression != null && expression is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueEvaluatableExpression');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueEvaluatableExpression &&
        other.runtimeType == InlineValueEvaluatableExpression &&
        expression == other.expression &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        expression,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inline value options used during static registration.
///
/// @since 3.17.0
class InlineValueOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueOptions.canParse,
    InlineValueOptions.fromJson,
  );

  InlineValueOptions({
    this.workDoneProgress,
  });
  static InlineValueOptions fromJson(Map<String, Object?> json) {
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlineValueOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueOptions &&
        other.runtimeType == InlineValueOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in inline value requests.
///
/// @since 3.17.0
class InlineValueParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueParams.canParse,
    InlineValueParams.fromJson,
  );

  InlineValueParams({
    required this.context,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static InlineValueParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context =
        InlineValueContext.fromJson(contextJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return InlineValueParams(
      context: context,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// Additional information about the context in which inline values were
  /// requested.
  final InlineValueContext context;

  /// The document range for which inline values should be computed.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['context'] = context.toJson();
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('context');
      try {
        if (!obj.containsKey('context')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final context = obj['context'];
        if (context == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!InlineValueContext.canParse(context, reporter)) {
          reporter.reportError('must be of type InlineValueContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueParams &&
        other.runtimeType == InlineValueParams &&
        context == other.context &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        context,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inline value options used during static or dynamic registration.
///
/// @since 3.17.0
class InlineValueRegistrationOptions
    implements
        InlineValueOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueRegistrationOptions.canParse,
    InlineValueRegistrationOptions.fromJson,
  );

  InlineValueRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static InlineValueRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlineValueRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueRegistrationOptions &&
        other.runtimeType == InlineValueRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provide inline value as text.
///
/// @since 3.17.0
class InlineValueText implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueText.canParse,
    InlineValueText.fromJson,
  );

  InlineValueText({
    required this.range,
    required this.text,
  });
  static InlineValueText fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textJson = json['text'];
    final text = textJson as String;
    return InlineValueText(
      range: range,
      text: text,
    );
  }

  /// The document range for which the inline value applies.
  final Range range;

  /// The text of the inline value.
  final String text;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    result['text'] = text;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final text = obj['text'];
        if (text == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (text is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueText');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueText &&
        other.runtimeType == InlineValueText &&
        range == other.range &&
        text == other.text;
  }

  @override
  int get hashCode => Object.hash(
        range,
        text,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provide inline value through a variable lookup. If only a range is
/// specified, the variable name will be extracted from the underlying document.
/// An optional variable name can be used to override the extracted name.
///
/// @since 3.17.0
class InlineValueVariableLookup implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueVariableLookup.canParse,
    InlineValueVariableLookup.fromJson,
  );

  InlineValueVariableLookup({
    required this.caseSensitiveLookup,
    required this.range,
    this.variableName,
  });
  static InlineValueVariableLookup fromJson(Map<String, Object?> json) {
    final caseSensitiveLookupJson = json['caseSensitiveLookup'];
    final caseSensitiveLookup = caseSensitiveLookupJson as bool;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final variableNameJson = json['variableName'];
    final variableName = variableNameJson as String?;
    return InlineValueVariableLookup(
      caseSensitiveLookup: caseSensitiveLookup,
      range: range,
      variableName: variableName,
    );
  }

  /// How to perform the lookup.
  final bool caseSensitiveLookup;

  /// The document range for which the inline value applies. The range is used
  /// to extract the variable name from the underlying document.
  final Range range;

  /// If specified the name of the variable to look up.
  final String? variableName;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['caseSensitiveLookup'] = caseSensitiveLookup;
    result['range'] = range.toJson();
    if (variableName != null) {
      result['variableName'] = variableName;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('caseSensitiveLookup');
      try {
        if (!obj.containsKey('caseSensitiveLookup')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final caseSensitiveLookup = obj['caseSensitiveLookup'];
        if (caseSensitiveLookup == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (caseSensitiveLookup is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('variableName');
      try {
        final variableName = obj['variableName'];
        if (variableName != null && variableName is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueVariableLookup');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueVariableLookup &&
        other.runtimeType == InlineValueVariableLookup &&
        caseSensitiveLookup == other.caseSensitiveLookup &&
        range == other.range &&
        variableName == other.variableName;
  }

  @override
  int get hashCode => Object.hash(
        caseSensitiveLookup,
        range,
        variableName,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client workspace capabilities specific to inline values.
///
/// @since 3.17.0
class InlineValueWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueWorkspaceClientCapabilities.canParse,
    InlineValueWorkspaceClientCapabilities.fromJson,
  );

  InlineValueWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static InlineValueWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return InlineValueWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// inline values currently shown. It should be used with absolute care and is
  /// useful for situation where a server for example detects a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('refreshSupport');
      try {
        final refreshSupport = obj['refreshSupport'];
        if (refreshSupport != null && refreshSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type InlineValueWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueWorkspaceClientCapabilities &&
        other.runtimeType == InlineValueWorkspaceClientCapabilities &&
        refreshSupport == other.refreshSupport;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A special text edit to provide an insert and a replace operation.
///
/// @since 3.16.0
class InsertReplaceEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InsertReplaceEdit.canParse,
    InsertReplaceEdit.fromJson,
  );

  InsertReplaceEdit({
    required this.insert,
    required this.newText,
    required this.replace,
  });
  static InsertReplaceEdit fromJson(Map<String, Object?> json) {
    final insertJson = json['insert'];
    final insert = Range.fromJson(insertJson as Map<String, Object?>);
    final newTextJson = json['newText'];
    final newText = newTextJson as String;
    final replaceJson = json['replace'];
    final replace = Range.fromJson(replaceJson as Map<String, Object?>);
    return InsertReplaceEdit(
      insert: insert,
      newText: newText,
      replace: replace,
    );
  }

  /// The range if the insert is requested
  final Range insert;

  /// The string to be inserted.
  final String newText;

  /// The range if the replace is requested.
  final Range replace;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['insert'] = insert.toJson();
    result['newText'] = newText;
    result['replace'] = replace.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('insert');
      try {
        if (!obj.containsKey('insert')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final insert = obj['insert'];
        if (insert == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(insert, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('newText');
      try {
        if (!obj.containsKey('newText')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newText = obj['newText'];
        if (newText == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('replace');
      try {
        if (!obj.containsKey('replace')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final replace = obj['replace'];
        if (replace == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(replace, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InsertReplaceEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InsertReplaceEdit &&
        other.runtimeType == InsertReplaceEdit &&
        insert == other.insert &&
        newText == other.newText &&
        replace == other.replace;
  }

  @override
  int get hashCode => Object.hash(
        insert,
        newText,
        replace,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines whether the insert text in a completion item should be interpreted
/// as plain text or a snippet.
class InsertTextFormat implements ToJsonable {
  const InsertTextFormat._(this._value);
  const InsertTextFormat.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 1:
      case 2:
        return true;
    }
    return false;
  }

  /// The primary text to be inserted is treated as a plain string.
  static const PlainText = InsertTextFormat._(1);

  /// The primary text to be inserted is treated as a snippet.
  ///
  /// A snippet can define tab stops and placeholders with `$1`, `$2` and
  /// `${3:foo}`. `$0` defines the final tab stop, it defaults to the end of the
  /// snippet. Placeholders with equal identifiers are linked,
  /// that is typing in one will update others too.
  ///
  /// See also:
  /// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax
  static const Snippet = InsertTextFormat._(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is InsertTextFormat && other._value == _value;
}

/// How whitespace and indentation is handled during completion item insertion.
///
/// @since 3.16.0
class InsertTextMode implements ToJsonable {
  const InsertTextMode(this._value);
  const InsertTextMode.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// The editor adjusts leading whitespace of new lines so that they match the
  /// indentation up to the cursor of the line for which the item is accepted.
  ///
  /// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a multi
  /// line completion item is indented using 2 tabs and all following lines
  /// inserted will be indented using 2 tabs as well.
  static const adjustIndentation = InsertTextMode(2);

  /// The insertion or replace strings is taken as it is. If the value is multi
  /// line the lines below the cursor will be inserted using the indentation
  /// defined in the string value. The client will not apply any kind of
  /// adjustments to the string.
  static const asIs = InsertTextMode(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is InsertTextMode && other._value == _value;
}

/// Client capabilities for the linked editing range request.
///
/// @since 3.16.0
class LinkedEditingRangeClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeClientCapabilities.canParse,
    LinkedEditingRangeClientCapabilities.fromJson,
  );

  LinkedEditingRangeClientCapabilities({
    this.dynamicRegistration,
  });
  static LinkedEditingRangeClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return LinkedEditingRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type LinkedEditingRangeClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRangeClientCapabilities &&
        other.runtimeType == LinkedEditingRangeClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LinkedEditingRangeOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeOptions.canParse,
    LinkedEditingRangeOptions.fromJson,
  );

  LinkedEditingRangeOptions({
    this.workDoneProgress,
  });
  static LinkedEditingRangeOptions fromJson(Map<String, Object?> json) {
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return LinkedEditingRangeOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LinkedEditingRangeOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRangeOptions &&
        other.runtimeType == LinkedEditingRangeOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LinkedEditingRangeParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeParams.canParse,
    LinkedEditingRangeParams.fromJson,
  );

  LinkedEditingRangeParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static LinkedEditingRangeParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return LinkedEditingRangeParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LinkedEditingRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRangeParams &&
        other.runtimeType == LinkedEditingRangeParams &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LinkedEditingRangeRegistrationOptions
    implements
        LinkedEditingRangeOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeRegistrationOptions.canParse,
    LinkedEditingRangeRegistrationOptions.fromJson,
  );

  LinkedEditingRangeRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static LinkedEditingRangeRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return LinkedEditingRangeRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type LinkedEditingRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRangeRegistrationOptions &&
        other.runtimeType == LinkedEditingRangeRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result of a linked editing range request.
///
/// @since 3.16.0
class LinkedEditingRanges implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRanges.canParse,
    LinkedEditingRanges.fromJson,
  );

  LinkedEditingRanges({
    required this.ranges,
    this.wordPattern,
  });
  static LinkedEditingRanges fromJson(Map<String, Object?> json) {
    final rangesJson = json['ranges'];
    final ranges = (rangesJson as List<Object?>)
        .map((item) => Range.fromJson(item as Map<String, Object?>))
        .toList();
    final wordPatternJson = json['wordPattern'];
    final wordPattern = wordPatternJson as String?;
    return LinkedEditingRanges(
      ranges: ranges,
      wordPattern: wordPattern,
    );
  }

  /// A list of ranges that can be edited together. The ranges must have
  /// identical length and contain identical text content. The ranges cannot
  /// overlap.
  final List<Range> ranges;

  /// An optional word pattern (regular expression) that describes valid
  /// contents for the given ranges. If no pattern is provided, the client
  /// configuration's word pattern will be used.
  final String? wordPattern;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['ranges'] = ranges.map((item) => item.toJson()).toList();
    if (wordPattern != null) {
      result['wordPattern'] = wordPattern;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ranges');
      try {
        if (!obj.containsKey('ranges')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final ranges = obj['ranges'];
        if (ranges == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (ranges is! List<Object?> ||
            ranges.any((item) => !Range.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Range>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('wordPattern');
      try {
        final wordPattern = obj['wordPattern'];
        if (wordPattern != null && wordPattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LinkedEditingRanges');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRanges &&
        other.runtimeType == LinkedEditingRanges &&
        listEqual(ranges, other.ranges, (Range a, Range b) => a == b) &&
        wordPattern == other.wordPattern;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(ranges),
        wordPattern,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a location inside a resource, such as a line inside a text file.
class Location implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Location.canParse,
    Location.fromJson,
  );

  Location({
    required this.range,
    required this.uri,
  });
  static Location fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return Location(
      range: range,
      uri: uri,
    );
  }

  final Range range;
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Location');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Location &&
        other.runtimeType == Location &&
        range == other.range &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        range,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents the connection of two locations. Provides additional metadata
/// over normal locations,
/// including an origin range.
class LocationLink implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LocationLink.canParse,
    LocationLink.fromJson,
  );

  LocationLink({
    this.originSelectionRange,
    required this.targetRange,
    required this.targetSelectionRange,
    required this.targetUri,
  });
  static LocationLink fromJson(Map<String, Object?> json) {
    final originSelectionRangeJson = json['originSelectionRange'];
    final originSelectionRange = originSelectionRangeJson != null
        ? Range.fromJson(originSelectionRangeJson as Map<String, Object?>)
        : null;
    final targetRangeJson = json['targetRange'];
    final targetRange = Range.fromJson(targetRangeJson as Map<String, Object?>);
    final targetSelectionRangeJson = json['targetSelectionRange'];
    final targetSelectionRange =
        Range.fromJson(targetSelectionRangeJson as Map<String, Object?>);
    final targetUriJson = json['targetUri'];
    final targetUri = targetUriJson as String;
    return LocationLink(
      originSelectionRange: originSelectionRange,
      targetRange: targetRange,
      targetSelectionRange: targetSelectionRange,
      targetUri: targetUri,
    );
  }

  /// Span of the origin of this link.
  ///
  /// Used as the underlined span for mouse interaction. Defaults to the word
  /// range at the definition position.
  final Range? originSelectionRange;

  /// The full target range of this link. If the target for example is a symbol
  /// then target range is the range enclosing this symbol not including
  /// leading/trailing whitespace but everything else like comments. This
  /// information is typically used to highlight the range in the editor.
  final Range targetRange;

  /// The range that should be selected and revealed when this link is being
  /// followed, e.g the name of a function. Must be contained by the
  /// `targetRange`. See also `DocumentSymbol#range`
  final Range targetSelectionRange;

  /// The target resource identifier of this link.
  final String targetUri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (originSelectionRange != null) {
      result['originSelectionRange'] = originSelectionRange?.toJson();
    }
    result['targetRange'] = targetRange.toJson();
    result['targetSelectionRange'] = targetSelectionRange.toJson();
    result['targetUri'] = targetUri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('originSelectionRange');
      try {
        final originSelectionRange = obj['originSelectionRange'];
        if (originSelectionRange != null &&
            !Range.canParse(originSelectionRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('targetRange');
      try {
        if (!obj.containsKey('targetRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final targetRange = obj['targetRange'];
        if (targetRange == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(targetRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('targetSelectionRange');
      try {
        if (!obj.containsKey('targetSelectionRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final targetSelectionRange = obj['targetSelectionRange'];
        if (targetSelectionRange == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(targetSelectionRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('targetUri');
      try {
        if (!obj.containsKey('targetUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final targetUri = obj['targetUri'];
        if (targetUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (targetUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LocationLink');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LocationLink &&
        other.runtimeType == LocationLink &&
        originSelectionRange == other.originSelectionRange &&
        targetRange == other.targetRange &&
        targetSelectionRange == other.targetSelectionRange &&
        targetUri == other.targetUri;
  }

  @override
  int get hashCode => Object.hash(
        originSelectionRange,
        targetRange,
        targetSelectionRange,
        targetUri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The log message parameters.
class LogMessageParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LogMessageParams.canParse,
    LogMessageParams.fromJson,
  );

  LogMessageParams({
    required this.message,
    required this.type,
  });
  static LogMessageParams fromJson(Map<String, Object?> json) {
    final messageJson = json['message'];
    final message = messageJson as String;
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    return LogMessageParams(
      message: message,
      type: type,
    );
  }

  /// The actual message.
  final String message;

  /// The message type. See {@link MessageType}
  final MessageType type;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['message'] = message;
    result['type'] = type.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final type = obj['type'];
        if (type == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MessageType.canParse(type, reporter)) {
          reporter.reportError('must be of type MessageType');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LogMessageParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LogMessageParams &&
        other.runtimeType == LogMessageParams &&
        message == other.message &&
        type == other.type;
  }

  @override
  int get hashCode => Object.hash(
        message,
        type,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LogTraceParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LogTraceParams.canParse,
    LogTraceParams.fromJson,
  );

  LogTraceParams({
    required this.message,
    this.verbose,
  });
  static LogTraceParams fromJson(Map<String, Object?> json) {
    final messageJson = json['message'];
    final message = messageJson as String;
    final verboseJson = json['verbose'];
    final verbose = verboseJson as String?;
    return LogTraceParams(
      message: message,
      verbose: verbose,
    );
  }

  final String message;
  final String? verbose;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['message'] = message;
    if (verbose != null) {
      result['verbose'] = verbose;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('verbose');
      try {
        final verbose = obj['verbose'];
        if (verbose != null && verbose is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LogTraceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LogTraceParams &&
        other.runtimeType == LogTraceParams &&
        message == other.message &&
        verbose == other.verbose;
  }

  @override
  int get hashCode => Object.hash(
        message,
        verbose,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to the used markdown parser.
///
/// @since 3.16.0
class MarkdownClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MarkdownClientCapabilities.canParse,
    MarkdownClientCapabilities.fromJson,
  );

  MarkdownClientCapabilities({
    this.allowedTags,
    required this.parser,
    this.version,
  });
  static MarkdownClientCapabilities fromJson(Map<String, Object?> json) {
    final allowedTagsJson = json['allowedTags'];
    final allowedTags = (allowedTagsJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final parserJson = json['parser'];
    final parser = parserJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return MarkdownClientCapabilities(
      allowedTags: allowedTags,
      parser: parser,
      version: version,
    );
  }

  /// A list of HTML tags that the client allows / supports in Markdown.
  ///
  /// @since 3.17.0
  final List<String>? allowedTags;

  /// The name of the parser.
  final String parser;

  /// The version of the parser.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (allowedTags != null) {
      result['allowedTags'] = allowedTags;
    }
    result['parser'] = parser;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('allowedTags');
      try {
        final allowedTags = obj['allowedTags'];
        if (allowedTags != null &&
            (allowedTags is! List<Object?> ||
                allowedTags.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('parser');
      try {
        if (!obj.containsKey('parser')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final parser = obj['parser'];
        if (parser == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (parser is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MarkdownClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MarkdownClientCapabilities &&
        other.runtimeType == MarkdownClientCapabilities &&
        listEqual(
            allowedTags, other.allowedTags, (String a, String b) => a == b) &&
        parser == other.parser &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(allowedTags),
        parser,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A `MarkupContent` literal represents a string value which content is
/// interpreted base on its kind flag. Currently the protocol supports
/// `plaintext` and `markdown` as markup kinds.
///
/// If the kind is `markdown` then the value can contain fenced code blocks like
/// in GitHub issues. See
/// https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting
///
/// Here is an example how such a string can be constructed using JavaScript /
/// TypeScript:
/// ```ts let markdown: MarkdownContent = {
///  kind: MarkupKind.Markdown,
///  value: [
///    '# Header',
///    'Some text',
///    '```typescript',
///    'someCode();',
///    '```'
///  ].join('\n')
/// };
/// ```
///
/// *Please Note* that clients might sanitize the return markdown. A client
/// could decide to remove HTML from the markdown to avoid script execution.
class MarkupContent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MarkupContent.canParse,
    MarkupContent.fromJson,
  );

  MarkupContent({
    required this.kind,
    required this.value,
  });
  static MarkupContent fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = MarkupKind.fromJson(kindJson as String);
    final valueJson = json['value'];
    final value = valueJson as String;
    return MarkupContent(
      kind: kind,
      value: value,
    );
  }

  /// The type of the Markup
  final MarkupKind kind;

  /// The content itself
  final String value;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MarkupKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type MarkupKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final value = obj['value'];
        if (value == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (value is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MarkupContent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MarkupContent &&
        other.runtimeType == MarkupContent &&
        kind == other.kind &&
        value == other.value;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Describes the content type that a client supports in various result literals
/// like `Hover`, `ParameterInfo` or `CompletionItem`.
///
/// Please note that `MarkupKinds` must not start with a `$`. This kinds are
/// reserved for internal usage.
class MarkupKind implements ToJsonable {
  const MarkupKind._(this._value);
  const MarkupKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'markdown':
      case 'plaintext':
        return true;
    }
    return false;
  }

  /// Markdown is supported as a content format
  static const Markdown = MarkupKind._('markdown');

  /// Plain text is supported as a content format
  static const PlainText = MarkupKind._('plaintext');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is MarkupKind && other._value == _value;
}

class MessageActionItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MessageActionItem.canParse,
    MessageActionItem.fromJson,
  );

  MessageActionItem({
    required this.title,
  });
  static MessageActionItem fromJson(Map<String, Object?> json) {
    final titleJson = json['title'];
    final title = titleJson as String;
    return MessageActionItem(
      title: title,
    );
  }

  /// A short title like 'Retry', 'Open Log' etc.
  final String title;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('title');
      try {
        if (!obj.containsKey('title')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final title = obj['title'];
        if (title == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (title is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MessageActionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MessageActionItem &&
        other.runtimeType == MessageActionItem &&
        title == other.title;
  }

  @override
  int get hashCode => title.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The message type
class MessageType implements ToJsonable {
  const MessageType(this._value);
  const MessageType.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// An error message.
  static const Error = MessageType(1);

  /// An information message.
  static const Info = MessageType(3);

  /// A log message.
  static const Log = MessageType(4);

  /// A warning message.
  static const Warning = MessageType(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is MessageType && other._value == _value;
}

/// All standard LSP Methods read from the JSON spec.
class Method implements ToJsonable {
  const Method(this._value);
  const Method.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// Constant for the 'callHierarchy/incomingCalls' method.
  static const callHierarchy_incomingCalls =
      Method('callHierarchy/incomingCalls');

  /// Constant for the 'callHierarchy/outgoingCalls' method.
  static const callHierarchy_outgoingCalls =
      Method('callHierarchy/outgoingCalls');

  /// Constant for the '$/cancelRequest' method.
  static const cancelRequest = Method(r'$/cancelRequest');

  /// Constant for the 'client/registerCapability' method.
  static const client_registerCapability = Method('client/registerCapability');

  /// Constant for the 'client/unregisterCapability' method.
  static const client_unregisterCapability =
      Method('client/unregisterCapability');

  /// Constant for the 'codeAction/resolve' method.
  static const codeAction_resolve = Method('codeAction/resolve');

  /// Constant for the 'codeLens/resolve' method.
  static const codeLens_resolve = Method('codeLens/resolve');

  /// Constant for the 'completionItem/resolve' method.
  static const completionItem_resolve = Method('completionItem/resolve');

  /// Constant for the 'documentLink/resolve' method.
  static const documentLink_resolve = Method('documentLink/resolve');

  /// Constant for the 'exit' method.
  static const exit = Method('exit');

  /// Constant for the 'initialize' method.
  static const initialize = Method('initialize');

  /// Constant for the 'initialized' method.
  static const initialized = Method('initialized');

  /// Constant for the 'inlayHint/resolve' method.
  static const inlayHint_resolve = Method('inlayHint/resolve');

  /// Constant for the '$/logTrace' method.
  static const logTrace = Method(r'$/logTrace');

  /// Constant for the 'notebookDocument/didChange' method.
  static const notebookDocument_didChange =
      Method('notebookDocument/didChange');

  /// Constant for the 'notebookDocument/didClose' method.
  static const notebookDocument_didClose = Method('notebookDocument/didClose');

  /// Constant for the 'notebookDocument/didOpen' method.
  static const notebookDocument_didOpen = Method('notebookDocument/didOpen');

  /// Constant for the 'notebookDocument/didSave' method.
  static const notebookDocument_didSave = Method('notebookDocument/didSave');

  /// Constant for the '$/progress' method.
  static const progress = Method(r'$/progress');

  /// Constant for the '$/setTrace' method.
  static const setTrace = Method(r'$/setTrace');

  /// Constant for the 'shutdown' method.
  static const shutdown = Method('shutdown');

  /// Constant for the 'telemetry/event' method.
  static const telemetry_event = Method('telemetry/event');

  /// Constant for the 'textDocument/codeAction' method.
  static const textDocument_codeAction = Method('textDocument/codeAction');

  /// Constant for the 'textDocument/codeLens' method.
  static const textDocument_codeLens = Method('textDocument/codeLens');

  /// Constant for the 'textDocument/colorPresentation' method.
  static const textDocument_colorPresentation =
      Method('textDocument/colorPresentation');

  /// Constant for the 'textDocument/completion' method.
  static const textDocument_completion = Method('textDocument/completion');

  /// Constant for the 'textDocument/declaration' method.
  static const textDocument_declaration = Method('textDocument/declaration');

  /// Constant for the 'textDocument/definition' method.
  static const textDocument_definition = Method('textDocument/definition');

  /// Constant for the 'textDocument/diagnostic' method.
  static const textDocument_diagnostic = Method('textDocument/diagnostic');

  /// Constant for the 'textDocument/didChange' method.
  static const textDocument_didChange = Method('textDocument/didChange');

  /// Constant for the 'textDocument/didClose' method.
  static const textDocument_didClose = Method('textDocument/didClose');

  /// Constant for the 'textDocument/didOpen' method.
  static const textDocument_didOpen = Method('textDocument/didOpen');

  /// Constant for the 'textDocument/didSave' method.
  static const textDocument_didSave = Method('textDocument/didSave');

  /// Constant for the 'textDocument/documentColor' method.
  static const textDocument_documentColor =
      Method('textDocument/documentColor');

  /// Constant for the 'textDocument/documentHighlight' method.
  static const textDocument_documentHighlight =
      Method('textDocument/documentHighlight');

  /// Constant for the 'textDocument/documentLink' method.
  static const textDocument_documentLink = Method('textDocument/documentLink');

  /// Constant for the 'textDocument/documentSymbol' method.
  static const textDocument_documentSymbol =
      Method('textDocument/documentSymbol');

  /// Constant for the 'textDocument/foldingRange' method.
  static const textDocument_foldingRange = Method('textDocument/foldingRange');

  /// Constant for the 'textDocument/formatting' method.
  static const textDocument_formatting = Method('textDocument/formatting');

  /// Constant for the 'textDocument/hover' method.
  static const textDocument_hover = Method('textDocument/hover');

  /// Constant for the 'textDocument/implementation' method.
  static const textDocument_implementation =
      Method('textDocument/implementation');

  /// Constant for the 'textDocument/inlayHint' method.
  static const textDocument_inlayHint = Method('textDocument/inlayHint');

  /// Constant for the 'textDocument/inlineValue' method.
  static const textDocument_inlineValue = Method('textDocument/inlineValue');

  /// Constant for the 'textDocument/linkedEditingRange' method.
  static const textDocument_linkedEditingRange =
      Method('textDocument/linkedEditingRange');

  /// Constant for the 'textDocument/moniker' method.
  static const textDocument_moniker = Method('textDocument/moniker');

  /// Constant for the 'textDocument/onTypeFormatting' method.
  static const textDocument_onTypeFormatting =
      Method('textDocument/onTypeFormatting');

  /// Constant for the 'textDocument/prepareCallHierarchy' method.
  static const textDocument_prepareCallHierarchy =
      Method('textDocument/prepareCallHierarchy');

  /// Constant for the 'textDocument/prepareRename' method.
  static const textDocument_prepareRename =
      Method('textDocument/prepareRename');

  /// Constant for the 'textDocument/prepareTypeHierarchy' method.
  static const textDocument_prepareTypeHierarchy =
      Method('textDocument/prepareTypeHierarchy');

  /// Constant for the 'textDocument/publishDiagnostics' method.
  static const textDocument_publishDiagnostics =
      Method('textDocument/publishDiagnostics');

  /// Constant for the 'textDocument/rangeFormatting' method.
  static const textDocument_rangeFormatting =
      Method('textDocument/rangeFormatting');

  /// Constant for the 'textDocument/references' method.
  static const textDocument_references = Method('textDocument/references');

  /// Constant for the 'textDocument/rename' method.
  static const textDocument_rename = Method('textDocument/rename');

  /// Constant for the 'textDocument/selectionRange' method.
  static const textDocument_selectionRange =
      Method('textDocument/selectionRange');

  /// Constant for the 'textDocument/semanticTokens/full' method.
  static const textDocument_semanticTokens_full =
      Method('textDocument/semanticTokens/full');

  /// Constant for the 'textDocument/semanticTokens/full/delta' method.
  static const textDocument_semanticTokens_full_delta =
      Method('textDocument/semanticTokens/full/delta');

  /// Constant for the 'textDocument/semanticTokens/range' method.
  static const textDocument_semanticTokens_range =
      Method('textDocument/semanticTokens/range');

  /// Constant for the 'textDocument/signatureHelp' method.
  static const textDocument_signatureHelp =
      Method('textDocument/signatureHelp');

  /// Constant for the 'textDocument/typeDefinition' method.
  static const textDocument_typeDefinition =
      Method('textDocument/typeDefinition');

  /// Constant for the 'textDocument/willSave' method.
  static const textDocument_willSave = Method('textDocument/willSave');

  /// Constant for the 'textDocument/willSaveWaitUntil' method.
  static const textDocument_willSaveWaitUntil =
      Method('textDocument/willSaveWaitUntil');

  /// Constant for the 'typeHierarchy/subtypes' method.
  static const typeHierarchy_subtypes = Method('typeHierarchy/subtypes');

  /// Constant for the 'typeHierarchy/supertypes' method.
  static const typeHierarchy_supertypes = Method('typeHierarchy/supertypes');

  /// Constant for the 'window/logMessage' method.
  static const window_logMessage = Method('window/logMessage');

  /// Constant for the 'window/showDocument' method.
  static const window_showDocument = Method('window/showDocument');

  /// Constant for the 'window/showMessage' method.
  static const window_showMessage = Method('window/showMessage');

  /// Constant for the 'window/showMessageRequest' method.
  static const window_showMessageRequest = Method('window/showMessageRequest');

  /// Constant for the 'window/workDoneProgress/cancel' method.
  static const window_workDoneProgress_cancel =
      Method('window/workDoneProgress/cancel');

  /// Constant for the 'window/workDoneProgress/create' method.
  static const window_workDoneProgress_create =
      Method('window/workDoneProgress/create');

  /// Constant for the 'workspace/applyEdit' method.
  static const workspace_applyEdit = Method('workspace/applyEdit');

  /// Constant for the 'workspace/codeLens/refresh' method.
  static const workspace_codeLens_refresh =
      Method('workspace/codeLens/refresh');

  /// Constant for the 'workspace/configuration' method.
  static const workspace_configuration = Method('workspace/configuration');

  /// Constant for the 'workspace/diagnostic' method.
  static const workspace_diagnostic = Method('workspace/diagnostic');

  /// Constant for the 'workspace/diagnostic/refresh' method.
  static const workspace_diagnostic_refresh =
      Method('workspace/diagnostic/refresh');

  /// Constant for the 'workspace/didChangeConfiguration' method.
  static const workspace_didChangeConfiguration =
      Method('workspace/didChangeConfiguration');

  /// Constant for the 'workspace/didChangeWatchedFiles' method.
  static const workspace_didChangeWatchedFiles =
      Method('workspace/didChangeWatchedFiles');

  /// Constant for the 'workspace/didChangeWorkspaceFolders' method.
  static const workspace_didChangeWorkspaceFolders =
      Method('workspace/didChangeWorkspaceFolders');

  /// Constant for the 'workspace/didCreateFiles' method.
  static const workspace_didCreateFiles = Method('workspace/didCreateFiles');

  /// Constant for the 'workspace/didDeleteFiles' method.
  static const workspace_didDeleteFiles = Method('workspace/didDeleteFiles');

  /// Constant for the 'workspace/didRenameFiles' method.
  static const workspace_didRenameFiles = Method('workspace/didRenameFiles');

  /// Constant for the 'workspace/executeCommand' method.
  static const workspace_executeCommand = Method('workspace/executeCommand');

  /// Constant for the 'workspace/inlayHint/refresh' method.
  static const workspace_inlayHint_refresh =
      Method('workspace/inlayHint/refresh');

  /// Constant for the 'workspace/inlineValue/refresh' method.
  static const workspace_inlineValue_refresh =
      Method('workspace/inlineValue/refresh');

  /// Constant for the 'workspace/semanticTokens/refresh' method.
  static const workspace_semanticTokens_refresh =
      Method('workspace/semanticTokens/refresh');

  /// Constant for the 'workspace/symbol' method.
  static const workspace_symbol = Method('workspace/symbol');

  /// Constant for the 'workspace/willCreateFiles' method.
  static const workspace_willCreateFiles = Method('workspace/willCreateFiles');

  /// Constant for the 'workspace/willDeleteFiles' method.
  static const workspace_willDeleteFiles = Method('workspace/willDeleteFiles');

  /// Constant for the 'workspace/willRenameFiles' method.
  static const workspace_willRenameFiles = Method('workspace/willRenameFiles');

  /// Constant for the 'workspace/workspaceFolders' method.
  static const workspace_workspaceFolders =
      Method('workspace/workspaceFolders');

  /// Constant for the 'workspaceSymbol/resolve' method.
  static const workspaceSymbol_resolve = Method('workspaceSymbol/resolve');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) => other is Method && other._value == _value;
}

/// Moniker definition to match LSIF 0.5 moniker definition.
///
/// @since 3.16.0
class Moniker implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Moniker.canParse,
    Moniker.fromJson,
  );

  Moniker({
    required this.identifier,
    this.kind,
    required this.scheme,
    required this.unique,
  });
  static Moniker fromJson(Map<String, Object?> json) {
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? MonikerKind.fromJson(kindJson as String) : null;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    final uniqueJson = json['unique'];
    final unique = UniquenessLevel.fromJson(uniqueJson as String);
    return Moniker(
      identifier: identifier,
      kind: kind,
      scheme: scheme,
      unique: unique,
    );
  }

  /// The identifier of the moniker. The value is opaque in LSIF however schema
  /// owners are allowed to define the structure if they want.
  final String identifier;

  /// The moniker kind if known.
  final MonikerKind? kind;

  /// The scheme of the moniker. For example tsc or .Net
  final String scheme;

  /// The scope in which the moniker is unique
  final UniquenessLevel unique;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['identifier'] = identifier;
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['scheme'] = scheme;
    result['unique'] = unique.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('identifier');
      try {
        if (!obj.containsKey('identifier')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final identifier = obj['identifier'];
        if (identifier == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (identifier is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !MonikerKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type MonikerKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        if (!obj.containsKey('scheme')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final scheme = obj['scheme'];
        if (scheme == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('unique');
      try {
        if (!obj.containsKey('unique')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final unique = obj['unique'];
        if (unique == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!UniquenessLevel.canParse(unique, reporter)) {
          reporter.reportError('must be of type UniquenessLevel');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Moniker');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Moniker &&
        other.runtimeType == Moniker &&
        identifier == other.identifier &&
        kind == other.kind &&
        scheme == other.scheme &&
        unique == other.unique;
  }

  @override
  int get hashCode => Object.hash(
        identifier,
        kind,
        scheme,
        unique,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to the moniker request.
///
/// @since 3.16.0
class MonikerClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerClientCapabilities.canParse,
    MonikerClientCapabilities.fromJson,
  );

  MonikerClientCapabilities({
    this.dynamicRegistration,
  });
  static MonikerClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return MonikerClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether moniker supports dynamic registration. If this is set to `true`
  /// the client supports the new `MonikerRegistrationOptions` return value for
  /// the corresponding server capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MonikerClientCapabilities &&
        other.runtimeType == MonikerClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The moniker kind.
///
/// @since 3.16.0
class MonikerKind implements ToJsonable {
  const MonikerKind(this._value);
  const MonikerKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// The moniker represents a symbol that is exported from a project
  static const export = MonikerKind('export');

  /// The moniker represent a symbol that is imported into a project
  static const import = MonikerKind('import');

  /// The moniker represents a symbol that is local to a project (e.g. a local
  /// variable of a function, a class not visible outside the project, ...)
  static const local = MonikerKind('local');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is MonikerKind && other._value == _value;
}

class MonikerOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerOptions.canParse,
    MonikerOptions.fromJson,
  );

  MonikerOptions({
    this.workDoneProgress,
  });
  static MonikerOptions fromJson(Map<String, Object?> json) {
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return MonikerOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MonikerOptions &&
        other.runtimeType == MonikerOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class MonikerParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerParams.canParse,
    MonikerParams.fromJson,
  );

  MonikerParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static MonikerParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return MonikerParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MonikerParams &&
        other.runtimeType == MonikerParams &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class MonikerRegistrationOptions
    implements MonikerOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerRegistrationOptions.canParse,
    MonikerRegistrationOptions.fromJson,
  );

  MonikerRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static MonikerRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return MonikerRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MonikerRegistrationOptions &&
        other.runtimeType == MonikerRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A notebook cell.
///
/// A cell's document URI must be unique across ALL notebook cells and can
/// therefore be used to uniquely identify a notebook cell or the cell's text
/// document.
///
/// @since 3.17.0
class NotebookCell implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookCell.canParse,
    NotebookCell.fromJson,
  );

  NotebookCell({
    required this.document,
    this.executionSummary,
    required this.kind,
    this.metadata,
  });
  static NotebookCell fromJson(Map<String, Object?> json) {
    final documentJson = json['document'];
    final document = documentJson as String;
    final executionSummaryJson = json['executionSummary'];
    final executionSummary = executionSummaryJson != null
        ? ExecutionSummary.fromJson(
            executionSummaryJson as Map<String, Object?>)
        : null;
    final kindJson = json['kind'];
    final kind = NotebookCellKind.fromJson(kindJson as int);
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    return NotebookCell(
      document: document,
      executionSummary: executionSummary,
      kind: kind,
      metadata: metadata,
    );
  }

  /// The URI of the cell's text document content.
  final String document;

  /// Additional execution summary information if supported by the client.
  final ExecutionSummary? executionSummary;

  /// The cell's kind
  final NotebookCellKind kind;

  /// Additional metadata stored with the cell.
  ///
  /// Note: should always be an object literal (e.g. LSPObject)
  final Object? metadata;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['document'] = document;
    if (executionSummary != null) {
      result['executionSummary'] = executionSummary?.toJson();
    }
    result['kind'] = kind.toJson();
    if (metadata != null) {
      result['metadata'] = metadata;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('document');
      try {
        if (!obj.containsKey('document')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final document = obj['document'];
        if (document == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (document is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executionSummary');
      try {
        final executionSummary = obj['executionSummary'];
        if (executionSummary != null &&
            !ExecutionSummary.canParse(executionSummary, reporter)) {
          reporter.reportError('must be of type ExecutionSummary');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookCellKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type NotebookCellKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookCell');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookCell &&
        other.runtimeType == NotebookCell &&
        document == other.document &&
        executionSummary == other.executionSummary &&
        kind == other.kind &&
        metadata == other.metadata;
  }

  @override
  int get hashCode => Object.hash(
        document,
        executionSummary,
        kind,
        metadata,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A change describing how to move a `NotebookCell` array from state S to S'.
///
/// @since 3.17.0
class NotebookCellArrayChange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookCellArrayChange.canParse,
    NotebookCellArrayChange.fromJson,
  );

  NotebookCellArrayChange({
    this.cells,
    required this.deleteCount,
    required this.start,
  });
  static NotebookCellArrayChange fromJson(Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>?)
        ?.map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final deleteCountJson = json['deleteCount'];
    final deleteCount = deleteCountJson as int;
    final startJson = json['start'];
    final start = startJson as int;
    return NotebookCellArrayChange(
      cells: cells,
      deleteCount: deleteCount,
      start: start,
    );
  }

  /// The new cells, if any
  final List<NotebookCell>? cells;

  /// The deleted cells
  final int deleteCount;

  /// The start oftest of the cell that changed.
  final int start;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cells != null) {
      result['cells'] = cells?.map((item) => item.toJson()).toList();
    }
    result['deleteCount'] = deleteCount;
    result['start'] = start;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        final cells = obj['cells'];
        if (cells != null &&
            (cells is! List<Object?> ||
                cells.any((item) => !NotebookCell.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<NotebookCell>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deleteCount');
      try {
        if (!obj.containsKey('deleteCount')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final deleteCount = obj['deleteCount'];
        if (deleteCount == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (deleteCount is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('start');
      try {
        if (!obj.containsKey('start')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final start = obj['start'];
        if (start == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (start is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookCellArrayChange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookCellArrayChange &&
        other.runtimeType == NotebookCellArrayChange &&
        listEqual(
            cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
        deleteCount == other.deleteCount &&
        start == other.start;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        deleteCount,
        start,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A notebook cell kind.
///
/// @since 3.17.0
class NotebookCellKind implements ToJsonable {
  const NotebookCellKind(this._value);
  const NotebookCellKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// A code-cell is source code.
  static const Code = NotebookCellKind(2);

  /// A markup-cell is formatted source that is used for display.
  static const Markup = NotebookCellKind(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is NotebookCellKind && other._value == _value;
}

/// A notebook cell text document filter denotes a cell text document by
/// different properties.
///
/// @since 3.17.0
class NotebookCellTextDocumentFilter implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookCellTextDocumentFilter.canParse,
    NotebookCellTextDocumentFilter.fromJson,
  );

  NotebookCellTextDocumentFilter({
    this.language,
    required this.notebook,
  });
  static NotebookCellTextDocumentFilter fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String?;
    final notebookJson = json['notebook'];
    final notebook = NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter) ||
            NotebookDocumentFilter2.canParse(
                notebookJson, nullLspJsonReporter) ||
            NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter)
        ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t1(
            NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter)
                ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t1(NotebookDocumentFilter1.fromJson(
                    notebookJson as Map<String, Object?>))
                : (NotebookDocumentFilter2.canParse(notebookJson, nullLspJsonReporter)
                    ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t2(NotebookDocumentFilter2.fromJson(
                        notebookJson as Map<String, Object?>))
                    : (NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter)
                        ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t3(NotebookDocumentFilter3.fromJson(notebookJson as Map<String, Object?>))
                        : (throw '''$notebookJson was not one of (NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3)'''))))
        : (notebookJson is String ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t2(notebookJson) : (throw '''$notebookJson was not one of (Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String)'''));
    return NotebookCellTextDocumentFilter(
      language: language,
      notebook: notebook,
    );
  }

  /// A language id like `python`.
  ///
  /// Will be matched against the language id of the notebook cell document. '*'
  /// matches every language.
  final String? language;

  /// A filter that matches against the notebook containing the notebook cell.
  /// If a string value is provided it matches against the notebook type. '*'
  /// matches every notebook.
  final Either2<
      Either3<NotebookDocumentFilter1, NotebookDocumentFilter2,
          NotebookDocumentFilter3>,
      String> notebook;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (language != null) {
      result['language'] = language;
    }
    result['notebook'] = notebook;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        final language = obj['language'];
        if (language != null && language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebook');
      try {
        if (!obj.containsKey('notebook')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebook = obj['notebook'];
        if (notebook == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocumentFilter1.canParse(notebook, reporter) &&
            !NotebookDocumentFilter2.canParse(notebook, reporter) &&
            !NotebookDocumentFilter3.canParse(notebook, reporter) &&
            notebook is! String) {
          reporter.reportError(
              'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookCellTextDocumentFilter');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookCellTextDocumentFilter &&
        other.runtimeType == NotebookCellTextDocumentFilter &&
        language == other.language &&
        notebook == other.notebook;
  }

  @override
  int get hashCode => Object.hash(
        language,
        notebook,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A notebook document.
///
/// @since 3.17.0
class NotebookDocument implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocument.canParse,
    NotebookDocument.fromJson,
  );

  NotebookDocument({
    required this.cells,
    this.metadata,
    required this.notebookType,
    required this.uri,
    required this.version,
  });
  static NotebookDocument fromJson(Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>)
        .map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return NotebookDocument(
      cells: cells,
      metadata: metadata,
      notebookType: notebookType,
      uri: uri,
      version: version,
    );
  }

  /// The cells of a notebook.
  final List<NotebookCell> cells;

  /// Additional metadata stored with the notebook document.
  ///
  /// Note: should always be an object literal (e.g. LSPObject)
  final Object? metadata;

  /// The type of the notebook.
  final String notebookType;

  /// The notebook document's uri.
  final String uri;

  /// The version number of this document (it will increase after each change,
  /// including undo/redo).
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cells'] = cells.map((item) => item.toJson()).toList();
    if (metadata != null) {
      result['metadata'] = metadata;
    }
    result['notebookType'] = notebookType;
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        if (!obj.containsKey('cells')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final cells = obj['cells'];
        if (cells == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (cells is! List<Object?> ||
            cells.any((item) => !NotebookCell.canParse(item, reporter))) {
          reporter.reportError('must be of type List<NotebookCell>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookType');
      try {
        if (!obj.containsKey('notebookType')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookType = obj['notebookType'];
        if (notebookType == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (notebookType is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocument');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocument &&
        other.runtimeType == NotebookDocument &&
        listEqual(
            cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
        metadata == other.metadata &&
        notebookType == other.notebookType &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        metadata,
        notebookType,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A change event for a notebook document.
///
/// @since 3.17.0
class NotebookDocumentChangeEvent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEvent.canParse,
    NotebookDocumentChangeEvent.fromJson,
  );

  NotebookDocumentChangeEvent({
    this.cells,
    this.metadata,
  });
  static NotebookDocumentChangeEvent fromJson(Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = cellsJson != null
        ? NotebookDocumentChangeEventCells.fromJson(
            cellsJson as Map<String, Object?>)
        : null;
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    return NotebookDocumentChangeEvent(
      cells: cells,
      metadata: metadata,
    );
  }

  /// Changes to cells
  final NotebookDocumentChangeEventCells? cells;

  /// The changed meta data if any.
  ///
  /// Note: should always be an object literal (e.g. LSPObject)
  final Object? metadata;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cells != null) {
      result['cells'] = cells?.toJson();
    }
    if (metadata != null) {
      result['metadata'] = metadata;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        final cells = obj['cells'];
        if (cells != null &&
            !NotebookDocumentChangeEventCells.canParse(cells, reporter)) {
          reporter
              .reportError('must be of type NotebookDocumentChangeEventCells');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentChangeEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentChangeEvent &&
        other.runtimeType == NotebookDocumentChangeEvent &&
        cells == other.cells &&
        metadata == other.metadata;
  }

  @override
  int get hashCode => Object.hash(
        cells,
        metadata,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentChangeEventCells implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEventCells.canParse,
    NotebookDocumentChangeEventCells.fromJson,
  );

  NotebookDocumentChangeEventCells({
    this.data,
    this.structure,
    this.textContent,
  });
  static NotebookDocumentChangeEventCells fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = (dataJson as List<Object?>?)
        ?.map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final structureJson = json['structure'];
    final structure = structureJson != null
        ? NotebookDocumentChangeEventCellsStructure.fromJson(
            structureJson as Map<String, Object?>)
        : null;
    final textContentJson = json['textContent'];
    final textContent = (textContentJson as List<Object?>?)
        ?.map((item) => NotebookDocumentChangeEventCellsTextContent.fromJson(
            item as Map<String, Object?>))
        .toList();
    return NotebookDocumentChangeEventCells(
      data: data,
      structure: structure,
      textContent: textContent,
    );
  }

  /// Changes to notebook cells properties like its kind, execution summary or
  /// metadata.
  final List<NotebookCell>? data;

  /// Changes to the cell structure to add or remove cells.
  final NotebookDocumentChangeEventCellsStructure? structure;

  /// Changes to the text content of notebook cells.
  final List<NotebookDocumentChangeEventCellsTextContent>? textContent;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data?.map((item) => item.toJson()).toList();
    }
    if (structure != null) {
      result['structure'] = structure?.toJson();
    }
    if (textContent != null) {
      result['textContent'] =
          textContent?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('data');
      try {
        final data = obj['data'];
        if (data != null &&
            (data is! List<Object?> ||
                data.any((item) => !NotebookCell.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<NotebookCell>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('structure');
      try {
        final structure = obj['structure'];
        if (structure != null &&
            !NotebookDocumentChangeEventCellsStructure.canParse(
                structure, reporter)) {
          reporter.reportError(
              'must be of type NotebookDocumentChangeEventCellsStructure');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textContent');
      try {
        final textContent = obj['textContent'];
        if (textContent != null &&
            (textContent is! List<Object?> ||
                textContent.any((item) =>
                    !NotebookDocumentChangeEventCellsTextContent.canParse(
                        item, reporter)))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentChangeEventCellsTextContent>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentChangeEventCells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentChangeEventCells &&
        other.runtimeType == NotebookDocumentChangeEventCells &&
        listEqual(
            data, other.data, (NotebookCell a, NotebookCell b) => a == b) &&
        structure == other.structure &&
        listEqual(
            textContent,
            other.textContent,
            (NotebookDocumentChangeEventCellsTextContent a,
                    NotebookDocumentChangeEventCellsTextContent b) =>
                a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        structure,
        lspHashCode(textContent),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentChangeEventCellsStructure implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEventCellsStructure.canParse,
    NotebookDocumentChangeEventCellsStructure.fromJson,
  );

  NotebookDocumentChangeEventCellsStructure({
    required this.array,
    this.didClose,
    this.didOpen,
  });
  static NotebookDocumentChangeEventCellsStructure fromJson(
      Map<String, Object?> json) {
    final arrayJson = json['array'];
    final array =
        NotebookCellArrayChange.fromJson(arrayJson as Map<String, Object?>);
    final didCloseJson = json['didClose'];
    final didClose = (didCloseJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentIdentifier.fromJson(item as Map<String, Object?>))
        .toList();
    final didOpenJson = json['didOpen'];
    final didOpen = (didOpenJson as List<Object?>?)
        ?.map((item) => TextDocumentItem.fromJson(item as Map<String, Object?>))
        .toList();
    return NotebookDocumentChangeEventCellsStructure(
      array: array,
      didClose: didClose,
      didOpen: didOpen,
    );
  }

  /// The change to the cell array.
  final NotebookCellArrayChange array;

  /// Additional closed cell text documents.
  final List<TextDocumentIdentifier>? didClose;

  /// Additional opened cell text documents.
  final List<TextDocumentItem>? didOpen;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['array'] = array.toJson();
    if (didClose != null) {
      result['didClose'] = didClose?.map((item) => item.toJson()).toList();
    }
    if (didOpen != null) {
      result['didOpen'] = didOpen?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('array');
      try {
        if (!obj.containsKey('array')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final array = obj['array'];
        if (array == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookCellArrayChange.canParse(array, reporter)) {
          reporter.reportError('must be of type NotebookCellArrayChange');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didClose');
      try {
        final didClose = obj['didClose'];
        if (didClose != null &&
            (didClose is! List<Object?> ||
                didClose.any((item) =>
                    !TextDocumentIdentifier.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<TextDocumentIdentifier>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didOpen');
      try {
        final didOpen = obj['didOpen'];
        if (didOpen != null &&
            (didOpen is! List<Object?> ||
                didOpen.any(
                    (item) => !TextDocumentItem.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<TextDocumentItem>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentChangeEventCellsStructure');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentChangeEventCellsStructure &&
        other.runtimeType == NotebookDocumentChangeEventCellsStructure &&
        array == other.array &&
        listEqual(didClose, other.didClose,
            (TextDocumentIdentifier a, TextDocumentIdentifier b) => a == b) &&
        listEqual(didOpen, other.didOpen,
            (TextDocumentItem a, TextDocumentItem b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        array,
        lspHashCode(didClose),
        lspHashCode(didOpen),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentChangeEventCellsTextContent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEventCellsTextContent.canParse,
    NotebookDocumentChangeEventCellsTextContent.fromJson,
  );

  NotebookDocumentChangeEventCellsTextContent({
    required this.changes,
    required this.document,
  });
  static NotebookDocumentChangeEventCellsTextContent fromJson(
      Map<String, Object?> json) {
    final changesJson = json['changes'];
    final changes = (changesJson as List<Object?>)
        .map((item) => TextDocumentContentChangeEvent1.canParse(
                item, nullLspJsonReporter)
            ? Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>.t1(
                TextDocumentContentChangeEvent1.fromJson(
                    item as Map<String, Object?>))
            : (TextDocumentContentChangeEvent2.canParse(item, nullLspJsonReporter)
                ? Either2<TextDocumentContentChangeEvent1,
                        TextDocumentContentChangeEvent2>.t2(
                    TextDocumentContentChangeEvent2.fromJson(item as Map<String, Object?>))
                : (throw '''$item was not one of (TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2)''')))
        .toList();
    final documentJson = json['document'];
    final document = VersionedTextDocumentIdentifier.fromJson(
        documentJson as Map<String, Object?>);
    return NotebookDocumentChangeEventCellsTextContent(
      changes: changes,
      document: document,
    );
  }

  final List<
      Either2<TextDocumentContentChangeEvent1,
          TextDocumentContentChangeEvent2>> changes;
  final VersionedTextDocumentIdentifier document;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['changes'] = changes;
    result['document'] = document.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('changes');
      try {
        if (!obj.containsKey('changes')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final changes = obj['changes'];
        if (changes == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (changes is! List<Object?> ||
            changes.any((item) =>
                !TextDocumentContentChangeEvent1.canParse(item, reporter) &&
                !TextDocumentContentChangeEvent2.canParse(item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('document');
      try {
        if (!obj.containsKey('document')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final document = obj['document'];
        if (document == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!VersionedTextDocumentIdentifier.canParse(document, reporter)) {
          reporter
              .reportError('must be of type VersionedTextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentChangeEventCellsTextContent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentChangeEventCellsTextContent &&
        other.runtimeType == NotebookDocumentChangeEventCellsTextContent &&
        listEqual(
            changes,
            other.changes,
            (Either2<TextDocumentContentChangeEvent1,
                            TextDocumentContentChangeEvent2>
                        a,
                    Either2<TextDocumentContentChangeEvent1,
                            TextDocumentContentChangeEvent2>
                        b) =>
                a == b) &&
        document == other.document;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(changes),
        document,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Capabilities specific to the notebook document support.
///
/// @since 3.17.0
class NotebookDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentClientCapabilities.canParse,
    NotebookDocumentClientCapabilities.fromJson,
  );

  NotebookDocumentClientCapabilities({
    required this.synchronization,
  });
  static NotebookDocumentClientCapabilities fromJson(
      Map<String, Object?> json) {
    final synchronizationJson = json['synchronization'];
    final synchronization = NotebookDocumentSyncClientCapabilities.fromJson(
        synchronizationJson as Map<String, Object?>);
    return NotebookDocumentClientCapabilities(
      synchronization: synchronization,
    );
  }

  /// Capabilities specific to notebook document synchronization
  ///
  /// @since 3.17.0
  final NotebookDocumentSyncClientCapabilities synchronization;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['synchronization'] = synchronization.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('synchronization');
      try {
        if (!obj.containsKey('synchronization')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final synchronization = obj['synchronization'];
        if (synchronization == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocumentSyncClientCapabilities.canParse(
            synchronization, reporter)) {
          reporter.reportError(
              'must be of type NotebookDocumentSyncClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type NotebookDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentClientCapabilities &&
        other.runtimeType == NotebookDocumentClientCapabilities &&
        synchronization == other.synchronization;
  }

  @override
  int get hashCode => synchronization.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentFilter1 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentFilter1.canParse,
    NotebookDocumentFilter1.fromJson,
  );

  NotebookDocumentFilter1({
    required this.notebookType,
    this.pattern,
    this.scheme,
  });
  static NotebookDocumentFilter1 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return NotebookDocumentFilter1(
      notebookType: notebookType,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The type of the enclosing notebook. */
  final String notebookType;

  /// A glob pattern. */
  final String? pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['notebookType'] = notebookType;
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookType');
      try {
        if (!obj.containsKey('notebookType')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookType = obj['notebookType'];
        if (notebookType == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (notebookType is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        final pattern = obj['pattern'];
        if (pattern != null && pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentFilter1');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentFilter1 &&
        other.runtimeType == NotebookDocumentFilter1 &&
        notebookType == other.notebookType &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        notebookType,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentFilter2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentFilter2.canParse,
    NotebookDocumentFilter2.fromJson,
  );

  NotebookDocumentFilter2({
    this.notebookType,
    this.pattern,
    required this.scheme,
  });
  static NotebookDocumentFilter2 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    return NotebookDocumentFilter2(
      notebookType: notebookType,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The type of the enclosing notebook. */
  final String? notebookType;

  /// A glob pattern. */
  final String? pattern;

  /// A Uri scheme, like `file` or `untitled`.*/
  final String scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (notebookType != null) {
      result['notebookType'] = notebookType;
    }
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    result['scheme'] = scheme;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookType');
      try {
        final notebookType = obj['notebookType'];
        if (notebookType != null && notebookType is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        final pattern = obj['pattern'];
        if (pattern != null && pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        if (!obj.containsKey('scheme')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final scheme = obj['scheme'];
        if (scheme == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentFilter2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentFilter2 &&
        other.runtimeType == NotebookDocumentFilter2 &&
        notebookType == other.notebookType &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        notebookType,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentFilter3 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentFilter3.canParse,
    NotebookDocumentFilter3.fromJson,
  );

  NotebookDocumentFilter3({
    this.notebookType,
    required this.pattern,
    this.scheme,
  });
  static NotebookDocumentFilter3 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return NotebookDocumentFilter3(
      notebookType: notebookType,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The type of the enclosing notebook. */
  final String? notebookType;

  /// A glob pattern. */
  final String pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (notebookType != null) {
      result['notebookType'] = notebookType;
    }
    result['pattern'] = pattern;
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookType');
      try {
        final notebookType = obj['notebookType'];
        if (notebookType != null && notebookType is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        if (!obj.containsKey('pattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final pattern = obj['pattern'];
        if (pattern == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentFilter3');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentFilter3 &&
        other.runtimeType == NotebookDocumentFilter3 &&
        notebookType == other.notebookType &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        notebookType,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A literal to identify a notebook document in the client.
///
/// @since 3.17.0
class NotebookDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentIdentifier.canParse,
    NotebookDocumentIdentifier.fromJson,
  );

  NotebookDocumentIdentifier({
    required this.uri,
  });
  static NotebookDocumentIdentifier fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return NotebookDocumentIdentifier(
      uri: uri,
    );
  }

  /// The notebook document's uri.
  final String uri;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentIdentifier &&
        other.runtimeType == NotebookDocumentIdentifier &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Notebook specific client capabilities.
///
/// @since 3.17.0
class NotebookDocumentSyncClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncClientCapabilities.canParse,
    NotebookDocumentSyncClientCapabilities.fromJson,
  );

  NotebookDocumentSyncClientCapabilities({
    this.dynamicRegistration,
    this.executionSummarySupport,
  });
  static NotebookDocumentSyncClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final executionSummarySupportJson = json['executionSummarySupport'];
    final executionSummarySupport = executionSummarySupportJson as bool?;
    return NotebookDocumentSyncClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      executionSummarySupport: executionSummarySupport,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  /// The client supports sending execution summary data per cell.
  final bool? executionSummarySupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (executionSummarySupport != null) {
      result['executionSummarySupport'] = executionSummarySupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executionSummarySupport');
      try {
        final executionSummarySupport = obj['executionSummarySupport'];
        if (executionSummarySupport != null &&
            executionSummarySupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncClientCapabilities &&
        other.runtimeType == NotebookDocumentSyncClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        executionSummarySupport == other.executionSummarySupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        executionSummarySupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Options specific to a notebook plus its cells to be synced to the server.
///
/// If a selector provides a notebook document filter but no cell selector all
/// cells of a matching notebook document will be synced.
///
/// If a selector provides no notebook document filter but only a cell selector
/// all notebook document that contain at least one matching cell will be
/// synced.
///
/// @since 3.17.0
class NotebookDocumentSyncOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptions.canParse,
    NotebookDocumentSyncOptions.fromJson,
  );

  NotebookDocumentSyncOptions({
    required this.notebookSelector,
    this.save,
  });
  static NotebookDocumentSyncOptions fromJson(Map<String, Object?> json) {
    if (NotebookDocumentSyncRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return NotebookDocumentSyncRegistrationOptions.fromJson(json);
    }
    final notebookSelectorJson = json['notebookSelector'];
    final notebookSelector = (notebookSelectorJson as List<Object?>)
        .map((item) => NotebookDocumentSyncOptionsNotebookSelector.canParse(
                item, nullLspJsonReporter)
            ? Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>.t1(
                NotebookDocumentSyncOptionsNotebookSelector.fromJson(
                    item as Map<String, Object?>))
            : (NotebookDocumentSyncOptionsNotebookSelector2.canParse(item, nullLspJsonReporter)
                ? Either2<NotebookDocumentSyncOptionsNotebookSelector,
                        NotebookDocumentSyncOptionsNotebookSelector2>.t2(
                    NotebookDocumentSyncOptionsNotebookSelector2.fromJson(item as Map<String, Object?>))
                : (throw '''$item was not one of (NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2)''')))
        .toList();
    final saveJson = json['save'];
    final save = saveJson as bool?;
    return NotebookDocumentSyncOptions(
      notebookSelector: notebookSelector,
      save: save,
    );
  }

  /// The notebooks to be synced
  final List<
      Either2<NotebookDocumentSyncOptionsNotebookSelector,
          NotebookDocumentSyncOptionsNotebookSelector2>> notebookSelector;

  /// Whether save notification should be forwarded to the server. Will only be
  /// honored if mode === `notebook`.
  final bool? save;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['notebookSelector'] = notebookSelector;
    if (save != null) {
      result['save'] = save;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookSelector');
      try {
        if (!obj.containsKey('notebookSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookSelector = obj['notebookSelector'];
        if (notebookSelector == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (notebookSelector is! List<Object?> ||
            notebookSelector.any((item) =>
                !NotebookDocumentSyncOptionsNotebookSelector.canParse(
                    item, reporter) &&
                !NotebookDocumentSyncOptionsNotebookSelector2.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('save');
      try {
        final save = obj['save'];
        if (save != null && save is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentSyncOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptions &&
        other.runtimeType == NotebookDocumentSyncOptions &&
        listEqual(
            notebookSelector,
            other.notebookSelector,
            (Either2<NotebookDocumentSyncOptionsNotebookSelector,
                            NotebookDocumentSyncOptionsNotebookSelector2>
                        a,
                    Either2<NotebookDocumentSyncOptionsNotebookSelector,
                            NotebookDocumentSyncOptionsNotebookSelector2>
                        b) =>
                a == b) &&
        save == other.save;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(notebookSelector),
        save,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelector implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelector.canParse,
    NotebookDocumentSyncOptionsNotebookSelector.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelector({
    this.cells,
    required this.notebook,
  });
  static NotebookDocumentSyncOptionsNotebookSelector fromJson(
      Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>?)
        ?.map((item) =>
            NotebookDocumentSyncOptionsNotebookSelectorCells.fromJson(
                item as Map<String, Object?>))
        .toList();
    final notebookJson = json['notebook'];
    final notebook = NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter) ||
            NotebookDocumentFilter2.canParse(
                notebookJson, nullLspJsonReporter) ||
            NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter)
        ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t1(
            NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter)
                ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t1(NotebookDocumentFilter1.fromJson(
                    notebookJson as Map<String, Object?>))
                : (NotebookDocumentFilter2.canParse(notebookJson, nullLspJsonReporter)
                    ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t2(NotebookDocumentFilter2.fromJson(
                        notebookJson as Map<String, Object?>))
                    : (NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter)
                        ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t3(NotebookDocumentFilter3.fromJson(notebookJson as Map<String, Object?>))
                        : (throw '''$notebookJson was not one of (NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3)'''))))
        : (notebookJson is String ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t2(notebookJson) : (throw '''$notebookJson was not one of (Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String)'''));
    return NotebookDocumentSyncOptionsNotebookSelector(
      cells: cells,
      notebook: notebook,
    );
  }

  /// The cells of the matching notebook to be synced.
  final List<NotebookDocumentSyncOptionsNotebookSelectorCells>? cells;

  /// The notebook to be synced If a string value is provided it matches against
  /// the notebook type. '*' matches every notebook.
  final Either2<
      Either3<NotebookDocumentFilter1, NotebookDocumentFilter2,
          NotebookDocumentFilter3>,
      String> notebook;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cells != null) {
      result['cells'] = cells?.map((item) => item.toJson()).toList();
    }
    result['notebook'] = notebook;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        final cells = obj['cells'];
        if (cells != null &&
            (cells is! List<Object?> ||
                cells.any((item) =>
                    !NotebookDocumentSyncOptionsNotebookSelectorCells.canParse(
                        item, reporter)))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentSyncOptionsNotebookSelectorCells>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebook');
      try {
        if (!obj.containsKey('notebook')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebook = obj['notebook'];
        if (notebook == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocumentFilter1.canParse(notebook, reporter) &&
            !NotebookDocumentFilter2.canParse(notebook, reporter) &&
            !NotebookDocumentFilter3.canParse(notebook, reporter) &&
            notebook is! String) {
          reporter.reportError(
              'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelector');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptionsNotebookSelector &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelector &&
        listEqual(
            cells,
            other.cells,
            (NotebookDocumentSyncOptionsNotebookSelectorCells a,
                    NotebookDocumentSyncOptionsNotebookSelectorCells b) =>
                a == b) &&
        notebook == other.notebook;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        notebook,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelector2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelector2.canParse,
    NotebookDocumentSyncOptionsNotebookSelector2.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelector2({
    required this.cells,
    this.notebook,
  });
  static NotebookDocumentSyncOptionsNotebookSelector2 fromJson(
      Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>)
        .map((item) =>
            NotebookDocumentSyncOptionsNotebookSelector2Cells.fromJson(
                item as Map<String, Object?>))
        .toList();
    final notebookJson = json['notebook'];
    final notebook = notebookJson == null
        ? null
        : (NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter) ||
                NotebookDocumentFilter2.canParse(
                    notebookJson, nullLspJsonReporter) ||
                NotebookDocumentFilter3.canParse(
                    notebookJson, nullLspJsonReporter)
            ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t1(
                NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter)
                    ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t1(
                        NotebookDocumentFilter1.fromJson(
                            notebookJson as Map<String, Object?>))
                    : (NotebookDocumentFilter2.canParse(notebookJson, nullLspJsonReporter)
                        ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t2(
                            NotebookDocumentFilter2.fromJson(notebookJson as Map<String, Object?>))
                        : (NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter) ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t3(NotebookDocumentFilter3.fromJson(notebookJson as Map<String, Object?>)) : (throw '''$notebookJson was not one of (NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3)'''))))
            : (notebookJson is String ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t2(notebookJson) : (throw '''$notebookJson was not one of (Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String)''')));
    return NotebookDocumentSyncOptionsNotebookSelector2(
      cells: cells,
      notebook: notebook,
    );
  }

  /// The cells of the matching notebook to be synced.
  final List<NotebookDocumentSyncOptionsNotebookSelector2Cells> cells;

  /// The notebook to be synced If a string value is provided it matches against
  /// the notebook type. '*' matches every notebook.
  final Either2<
      Either3<NotebookDocumentFilter1, NotebookDocumentFilter2,
          NotebookDocumentFilter3>,
      String>? notebook;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cells'] = cells.map((item) => item.toJson()).toList();
    if (notebook != null) {
      result['notebook'] = notebook;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        if (!obj.containsKey('cells')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final cells = obj['cells'];
        if (cells == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (cells is! List<Object?> ||
            cells.any((item) =>
                !NotebookDocumentSyncOptionsNotebookSelector2Cells.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentSyncOptionsNotebookSelector2Cells>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebook');
      try {
        final notebook = obj['notebook'];
        if (notebook != null &&
            !NotebookDocumentFilter1.canParse(notebook, reporter) &&
            !NotebookDocumentFilter2.canParse(notebook, reporter) &&
            !NotebookDocumentFilter3.canParse(notebook, reporter) &&
            notebook is! String) {
          reporter.reportError(
              'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelector2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptionsNotebookSelector2 &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelector2 &&
        listEqual(
            cells,
            other.cells,
            (NotebookDocumentSyncOptionsNotebookSelector2Cells a,
                    NotebookDocumentSyncOptionsNotebookSelector2Cells b) =>
                a == b) &&
        notebook == other.notebook;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        notebook,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelector2Cells implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelector2Cells.canParse,
    NotebookDocumentSyncOptionsNotebookSelector2Cells.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelector2Cells({
    required this.language,
  });
  static NotebookDocumentSyncOptionsNotebookSelector2Cells fromJson(
      Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String;
    return NotebookDocumentSyncOptionsNotebookSelector2Cells(
      language: language,
    );
  }

  final String language;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        if (!obj.containsKey('language')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final language = obj['language'];
        if (language == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelector2Cells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptionsNotebookSelector2Cells &&
        other.runtimeType ==
            NotebookDocumentSyncOptionsNotebookSelector2Cells &&
        language == other.language;
  }

  @override
  int get hashCode => language.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelectorCells implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelectorCells.canParse,
    NotebookDocumentSyncOptionsNotebookSelectorCells.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelectorCells({
    required this.language,
  });
  static NotebookDocumentSyncOptionsNotebookSelectorCells fromJson(
      Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String;
    return NotebookDocumentSyncOptionsNotebookSelectorCells(
      language: language,
    );
  }

  final String language;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        if (!obj.containsKey('language')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final language = obj['language'];
        if (language == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelectorCells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptionsNotebookSelectorCells &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelectorCells &&
        language == other.language;
  }

  @override
  int get hashCode => language.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options specific to a notebook.
///
/// @since 3.17.0
class NotebookDocumentSyncRegistrationOptions
    implements
        NotebookDocumentSyncOptions,
        StaticRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncRegistrationOptions.canParse,
    NotebookDocumentSyncRegistrationOptions.fromJson,
  );

  NotebookDocumentSyncRegistrationOptions({
    this.id,
    required this.notebookSelector,
    this.save,
  });
  static NotebookDocumentSyncRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final idJson = json['id'];
    final id = idJson as String?;
    final notebookSelectorJson = json['notebookSelector'];
    final notebookSelector = (notebookSelectorJson as List<Object?>)
        .map((item) => NotebookDocumentSyncOptionsNotebookSelector.canParse(
                item, nullLspJsonReporter)
            ? Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>.t1(
                NotebookDocumentSyncOptionsNotebookSelector.fromJson(
                    item as Map<String, Object?>))
            : (NotebookDocumentSyncOptionsNotebookSelector2.canParse(item, nullLspJsonReporter)
                ? Either2<NotebookDocumentSyncOptionsNotebookSelector,
                        NotebookDocumentSyncOptionsNotebookSelector2>.t2(
                    NotebookDocumentSyncOptionsNotebookSelector2.fromJson(item as Map<String, Object?>))
                : (throw '''$item was not one of (NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2)''')))
        .toList();
    final saveJson = json['save'];
    final save = saveJson as bool?;
    return NotebookDocumentSyncRegistrationOptions(
      id: id,
      notebookSelector: notebookSelector,
      save: save,
    );
  }

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// The notebooks to be synced
  @override
  final List<
      Either2<NotebookDocumentSyncOptionsNotebookSelector,
          NotebookDocumentSyncOptionsNotebookSelector2>> notebookSelector;

  /// Whether save notification should be forwarded to the server. Will only be
  /// honored if mode === `notebook`.
  @override
  final bool? save;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (id != null) {
      result['id'] = id;
    }
    result['notebookSelector'] = notebookSelector;
    if (save != null) {
      result['save'] = save;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookSelector');
      try {
        if (!obj.containsKey('notebookSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookSelector = obj['notebookSelector'];
        if (notebookSelector == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (notebookSelector is! List<Object?> ||
            notebookSelector.any((item) =>
                !NotebookDocumentSyncOptionsNotebookSelector.canParse(
                    item, reporter) &&
                !NotebookDocumentSyncOptionsNotebookSelector2.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('save');
      try {
        final save = obj['save'];
        if (save != null && save is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncRegistrationOptions &&
        other.runtimeType == NotebookDocumentSyncRegistrationOptions &&
        id == other.id &&
        listEqual(
            notebookSelector,
            other.notebookSelector,
            (Either2<NotebookDocumentSyncOptionsNotebookSelector,
                            NotebookDocumentSyncOptionsNotebookSelector2>
                        a,
                    Either2<NotebookDocumentSyncOptionsNotebookSelector,
                            NotebookDocumentSyncOptionsNotebookSelector2>
                        b) =>
                a == b) &&
        save == other.save;
  }

  @override
  int get hashCode => Object.hash(
        id,
        lspHashCode(notebookSelector),
        save,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A text document identifier to optionally denote a specific version of a text
/// document.
class OptionalVersionedTextDocumentIdentifier
    implements TextDocumentIdentifier, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    OptionalVersionedTextDocumentIdentifier.canParse,
    OptionalVersionedTextDocumentIdentifier.fromJson,
  );

  OptionalVersionedTextDocumentIdentifier({
    required this.uri,
    this.version,
  });
  static OptionalVersionedTextDocumentIdentifier fromJson(
      Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return OptionalVersionedTextDocumentIdentifier(
      uri: uri,
      version: version,
    );
  }

  /// The text document's uri.
  @override
  final String uri;

  /// The version number of this document. If a versioned text document
  /// identifier is sent from the server to the client and the file is not open
  /// in the editor (the server has not received an open notification before)
  /// the server can send `null` to indicate that the version is unknown and the
  /// content on disk is the truth (as specified with document content
  /// ownership).
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version != null && version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type OptionalVersionedTextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is OptionalVersionedTextDocumentIdentifier &&
        other.runtimeType == OptionalVersionedTextDocumentIdentifier &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a parameter of a callable-signature. A parameter can have a label
/// and a doc-comment.
class ParameterInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ParameterInformation.canParse,
    ParameterInformation.fromJson,
  );

  ParameterInformation({
    this.documentation,
    required this.label,
  });
  static ParameterInformation fromJson(Map<String, Object?> json) {
    final documentationJson = json['documentation'];
    final documentation = documentationJson == null
        ? null
        : (MarkupContent.canParse(documentationJson, nullLspJsonReporter)
            ? Either2<MarkupContent, String>.t1(MarkupContent.fromJson(
                documentationJson as Map<String, Object?>))
            : (documentationJson is String
                ? Either2<MarkupContent, String>.t2(documentationJson)
                : (throw '''$documentationJson was not one of (MarkupContent, String)''')));
    final labelJson = json['label'];
    final label = labelJson as String;
    return ParameterInformation(
      documentation: documentation,
      label: label,
    );
  }

  /// The human-readable doc-comment of this parameter. Will be shown in the UI
  /// but can be omitted.
  final Either2<MarkupContent, String>? documentation;

  /// The label of this parameter information.
  ///
  /// Either a string or an inclusive start and exclusive end offsets within its
  /// containing signature label. (see SignatureInformation.label). The offsets
  /// are based on a UTF-16 string representation as `Position` and `Range`
  /// does.
  ///
  /// *Note*: a label of type string should be a substring of its containing
  /// signature label. Its intended use case is to highlight the parameter label
  /// part in the `SignatureInformation.label`.
  final String label;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (documentation != null) {
      result['documentation'] = documentation;
    }
    result['label'] = label;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentation');
      try {
        final documentation = obj['documentation'];
        if (documentation != null &&
            !MarkupContent.canParse(documentation, reporter) &&
            documentation is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final label = obj['label'];
        if (label == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ParameterInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ParameterInformation &&
        other.runtimeType == ParameterInformation &&
        documentation == other.documentation &&
        label == other.label;
  }

  @override
  int get hashCode => Object.hash(
        documentation,
        label,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PartialResultParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PartialResultParams.canParse,
    PartialResultParams.fromJson,
  );

  PartialResultParams({
    this.partialResultToken,
  });
  static PartialResultParams fromJson(Map<String, Object?> json) {
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (DocumentDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return DocumentDiagnosticParams.fromJson(json);
    }
    if (WorkspaceDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceDiagnosticParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (TypeHierarchySubtypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySubtypesParams.fromJson(json);
    }
    if (TypeHierarchySupertypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySupertypesParams.fromJson(json);
    }
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    return PartialResultParams(
      partialResultToken: partialResultToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<int, String>? partialResultToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PartialResultParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PartialResultParams &&
        other.runtimeType == PartialResultParams &&
        partialResultToken == other.partialResultToken;
  }

  @override
  int get hashCode => partialResultToken.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PlaceholderAndRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PlaceholderAndRange.canParse,
    PlaceholderAndRange.fromJson,
  );

  PlaceholderAndRange({
    required this.placeholder,
    required this.range,
  });
  static PlaceholderAndRange fromJson(Map<String, Object?> json) {
    final placeholderJson = json['placeholder'];
    final placeholder = placeholderJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return PlaceholderAndRange(
      placeholder: placeholder,
      range: range,
    );
  }

  final String placeholder;
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['placeholder'] = placeholder;
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('placeholder');
      try {
        if (!obj.containsKey('placeholder')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final placeholder = obj['placeholder'];
        if (placeholder == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (placeholder is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PlaceholderAndRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PlaceholderAndRange &&
        other.runtimeType == PlaceholderAndRange &&
        placeholder == other.placeholder &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        placeholder,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Position in a text document expressed as zero-based line and character
/// offset. Prior to 3.17 the offsets were always based on a UTF-16 string
/// representation. So a string of the form `a𐐀b` the character offset of the
/// character `a` is 0, the character offset of `𐐀` is 1 and the character
/// offset of b is 3 since `𐐀` is represented using two code units in UTF-16.
/// Since 3.17 clients and servers can agree on a different string encoding
/// representation (e.g. UTF-8). The client announces it's supported encoding
/// via the client capability `general.positionEncodings`. The value is an array
/// of position encodings the client supports, with decreasing preference (e.g.
/// the encoding at index `0` is the most preferred one). To stay backwards
/// compatible the only mandatory encoding is UTF-16 represented via the string
/// `utf-16`. The server can pick one of the encodings offered by the client and
/// signals that encoding back to the client via the initialize result's
/// property `capabilities.positionEncoding`. If the string value `utf-16` is
/// missing from the client's capability `general.positionEncodings` servers can
/// safely assume that the client supports UTF-16. If the server omits the
/// position encoding in its initialize result the encoding defaults to the
/// string value `utf-16`. Implementation considerations: since the conversion
/// from one encoding into another requires the content of the file / line the
/// conversion is best done where the file is read which is usually on the
/// server side.
///
/// Positions are line end character agnostic. So you can not specify a position
/// that denotes `\r|\n` or `\n|` where `|` represents the character offset.
///
/// @since 3.17.0 - support for negotiated position encoding.
class Position implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Position.canParse,
    Position.fromJson,
  );

  Position({
    required this.character,
    required this.line,
  });
  static Position fromJson(Map<String, Object?> json) {
    final characterJson = json['character'];
    final character = characterJson as int;
    final lineJson = json['line'];
    final line = lineJson as int;
    return Position(
      character: character,
      line: line,
    );
  }

  /// Character offset on a line in a document (zero-based).
  ///
  /// The meaning of this offset is determined by the negotiated
  /// `PositionEncodingKind`.
  ///
  /// If the character value is greater than the line length it defaults back to
  /// the line length.
  final int character;

  /// Line position in a document (zero-based).
  ///
  /// If a line number is greater than the number of lines in a document, it
  /// defaults back to the number of lines in the document. If a line number is
  /// negative, it defaults to 0.
  final int line;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['character'] = character;
    result['line'] = line;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('character');
      try {
        if (!obj.containsKey('character')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final character = obj['character'];
        if (character == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (character is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('line');
      try {
        if (!obj.containsKey('line')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final line = obj['line'];
        if (line == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (line is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Position');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Position &&
        other.runtimeType == Position &&
        character == other.character &&
        line == other.line;
  }

  @override
  int get hashCode => Object.hash(
        character,
        line,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A set of predefined position encoding kinds.
///
/// @since 3.17.0
class PositionEncodingKind implements ToJsonable {
  const PositionEncodingKind(this._value);
  const PositionEncodingKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// Character offsets count UTF-16 code units.
  ///
  /// This is the default and must always be supported by servers
  static const UTF16 = PositionEncodingKind('utf-16');

  /// Character offsets count UTF-32 code units.
  ///
  /// Implementation note: these are the same as Unicode code points,
  /// so this `PositionEncodingKind` may also be used for an encoding-agnostic
  /// representation of character offsets.
  static const UTF32 = PositionEncodingKind('utf-32');

  /// Character offsets count UTF-8 code units.
  static const UTF8 = PositionEncodingKind('utf-8');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is PositionEncodingKind && other._value == _value;
}

class PrepareRenameParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PrepareRenameParams.canParse,
    PrepareRenameParams.fromJson,
  );

  PrepareRenameParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static PrepareRenameParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return PrepareRenameParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PrepareRenameParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PrepareRenameParams &&
        other.runtimeType == PrepareRenameParams &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PrepareRenameResult2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PrepareRenameResult2.canParse,
    PrepareRenameResult2.fromJson,
  );

  PrepareRenameResult2({
    required this.defaultBehavior,
  });
  static PrepareRenameResult2 fromJson(Map<String, Object?> json) {
    final defaultBehaviorJson = json['defaultBehavior'];
    final defaultBehavior = defaultBehaviorJson as bool;
    return PrepareRenameResult2(
      defaultBehavior: defaultBehavior,
    );
  }

  final bool defaultBehavior;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('defaultBehavior');
      try {
        if (!obj.containsKey('defaultBehavior')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final defaultBehavior = obj['defaultBehavior'];
        if (defaultBehavior == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (defaultBehavior is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PrepareRenameResult2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PrepareRenameResult2 &&
        other.runtimeType == PrepareRenameResult2 &&
        defaultBehavior == other.defaultBehavior;
  }

  @override
  int get hashCode => defaultBehavior.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PrepareSupportDefaultBehavior implements ToJsonable {
  const PrepareSupportDefaultBehavior(this._value);
  const PrepareSupportDefaultBehavior.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// The client's default behavior is to select the identifier according the to
  /// language's syntax rule.
  static const Identifier = PrepareSupportDefaultBehavior(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is PrepareSupportDefaultBehavior && other._value == _value;
}

/// A previous result id in a workspace pull request.
///
/// @since 3.17.0
class PreviousResultId implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PreviousResultId.canParse,
    PreviousResultId.fromJson,
  );

  PreviousResultId({
    required this.uri,
    required this.value,
  });
  static PreviousResultId fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final valueJson = json['value'];
    final value = valueJson as String;
    return PreviousResultId(
      uri: uri,
      value: value,
    );
  }

  /// The URI for which the client knowns a result id.
  final String uri;

  /// The value of the previous result id.
  final String value;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final value = obj['value'];
        if (value == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (value is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PreviousResultId');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PreviousResultId &&
        other.runtimeType == PreviousResultId &&
        uri == other.uri &&
        value == other.value;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ProgressParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ProgressParams.canParse,
    ProgressParams.fromJson,
  );

  ProgressParams({
    required this.token,
    this.value,
  });
  static ProgressParams fromJson(Map<String, Object?> json) {
    final tokenJson = json['token'];
    final token = tokenJson is int
        ? Either2<int, String>.t1(tokenJson)
        : (tokenJson is String
            ? Either2<int, String>.t2(tokenJson)
            : (throw '''$tokenJson was not one of (int, String)'''));
    final valueJson = json['value'];
    final value = valueJson;
    return ProgressParams(
      token: token,
      value: value,
    );
  }

  /// The progress token provided by the client or server.
  final Either2<int, String> token;

  /// The progress data.
  final Object? value;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('token');
      try {
        if (!obj.containsKey('token')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final token = obj['token'];
        if (token == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (token is! int && token is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ProgressParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ProgressParams &&
        other.runtimeType == ProgressParams &&
        token == other.token &&
        value == other.value;
  }

  @override
  int get hashCode => Object.hash(
        token,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The publish diagnostic client capabilities.
class PublishDiagnosticsClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PublishDiagnosticsClientCapabilities.canParse,
    PublishDiagnosticsClientCapabilities.fromJson,
  );

  PublishDiagnosticsClientCapabilities({
    this.codeDescriptionSupport,
    this.dataSupport,
    this.relatedInformation,
    this.tagSupport,
    this.versionSupport,
  });
  static PublishDiagnosticsClientCapabilities fromJson(
      Map<String, Object?> json) {
    final codeDescriptionSupportJson = json['codeDescriptionSupport'];
    final codeDescriptionSupport = codeDescriptionSupportJson as bool?;
    final dataSupportJson = json['dataSupport'];
    final dataSupport = dataSupportJson as bool?;
    final relatedInformationJson = json['relatedInformation'];
    final relatedInformation = relatedInformationJson as bool?;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? PublishDiagnosticsClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    final versionSupportJson = json['versionSupport'];
    final versionSupport = versionSupportJson as bool?;
    return PublishDiagnosticsClientCapabilities(
      codeDescriptionSupport: codeDescriptionSupport,
      dataSupport: dataSupport,
      relatedInformation: relatedInformation,
      tagSupport: tagSupport,
      versionSupport: versionSupport,
    );
  }

  /// Client supports a codeDescription property
  ///
  /// @since 3.16.0
  final bool? codeDescriptionSupport;

  /// Whether code action supports the `data` property which is preserved
  /// between a `textDocument/publishDiagnostics` and `textDocument/codeAction`
  /// request.
  ///
  /// @since 3.16.0
  final bool? dataSupport;

  /// Whether the clients accepts diagnostics with related information.
  final bool? relatedInformation;

  /// Client supports the tag property to provide meta data about a diagnostic.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///
  /// @since 3.15.0
  final PublishDiagnosticsClientCapabilitiesTagSupport? tagSupport;

  /// Whether the client interprets the version property of the
  /// `textDocument/publishDiagnostics` notification's parameter.
  ///
  /// @since 3.15.0
  final bool? versionSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (codeDescriptionSupport != null) {
      result['codeDescriptionSupport'] = codeDescriptionSupport;
    }
    if (dataSupport != null) {
      result['dataSupport'] = dataSupport;
    }
    if (relatedInformation != null) {
      result['relatedInformation'] = relatedInformation;
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    if (versionSupport != null) {
      result['versionSupport'] = versionSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('codeDescriptionSupport');
      try {
        final codeDescriptionSupport = obj['codeDescriptionSupport'];
        if (codeDescriptionSupport != null && codeDescriptionSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dataSupport');
      try {
        final dataSupport = obj['dataSupport'];
        if (dataSupport != null && dataSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('relatedInformation');
      try {
        final relatedInformation = obj['relatedInformation'];
        if (relatedInformation != null && relatedInformation is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        final tagSupport = obj['tagSupport'];
        if (tagSupport != null &&
            !PublishDiagnosticsClientCapabilitiesTagSupport.canParse(
                tagSupport, reporter)) {
          reporter.reportError(
              'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('versionSupport');
      try {
        final versionSupport = obj['versionSupport'];
        if (versionSupport != null && versionSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type PublishDiagnosticsClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PublishDiagnosticsClientCapabilities &&
        other.runtimeType == PublishDiagnosticsClientCapabilities &&
        codeDescriptionSupport == other.codeDescriptionSupport &&
        dataSupport == other.dataSupport &&
        relatedInformation == other.relatedInformation &&
        tagSupport == other.tagSupport &&
        versionSupport == other.versionSupport;
  }

  @override
  int get hashCode => Object.hash(
        codeDescriptionSupport,
        dataSupport,
        relatedInformation,
        tagSupport,
        versionSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PublishDiagnosticsClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PublishDiagnosticsClientCapabilitiesTagSupport.canParse,
    PublishDiagnosticsClientCapabilitiesTagSupport.fromJson,
  );

  PublishDiagnosticsClientCapabilitiesTagSupport({
    required this.valueSet,
  });
  static PublishDiagnosticsClientCapabilitiesTagSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => DiagnosticTag.fromJson(item as int))
        .toList();
    return PublishDiagnosticsClientCapabilitiesTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<DiagnosticTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final valueSet = obj['valueSet'];
        if (valueSet == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (valueSet is! List<Object?> ||
            valueSet.any((item) => !DiagnosticTag.canParse(item, reporter))) {
          reporter.reportError('must be of type List<DiagnosticTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PublishDiagnosticsClientCapabilitiesTagSupport &&
        other.runtimeType == PublishDiagnosticsClientCapabilitiesTagSupport &&
        listEqual(valueSet, other.valueSet,
            (DiagnosticTag a, DiagnosticTag b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The publish diagnostic notification's parameters.
class PublishDiagnosticsParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PublishDiagnosticsParams.canParse,
    PublishDiagnosticsParams.fromJson,
  );

  PublishDiagnosticsParams({
    required this.diagnostics,
    required this.uri,
    this.version,
  });
  static PublishDiagnosticsParams fromJson(Map<String, Object?> json) {
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = (diagnosticsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return PublishDiagnosticsParams(
      diagnostics: diagnostics,
      uri: uri,
      version: version,
    );
  }

  /// An array of diagnostic information items.
  final List<Diagnostic> diagnostics;

  /// The URI for which diagnostic information is reported.
  final String uri;

  /// Optional the version number of the document the diagnostics are published
  /// for.
  ///
  /// @since 3.15.0
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['diagnostics'] = diagnostics.map((item) => item.toJson()).toList();
    result['uri'] = uri;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('diagnostics');
      try {
        if (!obj.containsKey('diagnostics')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final diagnostics = obj['diagnostics'];
        if (diagnostics == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (diagnostics is! List<Object?> ||
            diagnostics.any((item) => !Diagnostic.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PublishDiagnosticsParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PublishDiagnosticsParams &&
        other.runtimeType == PublishDiagnosticsParams &&
        listEqual(diagnostics, other.diagnostics,
            (Diagnostic a, Diagnostic b) => a == b) &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(diagnostics),
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A range in a text document expressed as (zero-based) start and end
/// positions.
///
/// If you want to specify a range that contains a line including the line
/// ending character(s) then use an end position denoting the start of the next
/// line. For example:
/// ```ts
/// {
///     start: { line: 5, character: 23 }
///     end : { line 6, character : 0 }
/// }
/// ```
class Range implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Range.canParse,
    Range.fromJson,
  );

  Range({
    required this.end,
    required this.start,
  });
  static Range fromJson(Map<String, Object?> json) {
    final endJson = json['end'];
    final end = Position.fromJson(endJson as Map<String, Object?>);
    final startJson = json['start'];
    final start = Position.fromJson(startJson as Map<String, Object?>);
    return Range(
      end: end,
      start: start,
    );
  }

  /// The range's end position.
  final Position end;

  /// The range's start position.
  final Position start;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['end'] = end.toJson();
    result['start'] = start.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('end');
      try {
        if (!obj.containsKey('end')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final end = obj['end'];
        if (end == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(end, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('start');
      try {
        if (!obj.containsKey('start')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final start = obj['start'];
        if (start == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(start, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Range');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Range &&
        other.runtimeType == Range &&
        end == other.end &&
        start == other.start;
  }

  @override
  int get hashCode => Object.hash(
        end,
        start,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client Capabilities for a ReferencesRequest.
class ReferenceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceClientCapabilities.canParse,
    ReferenceClientCapabilities.fromJson,
  );

  ReferenceClientCapabilities({
    this.dynamicRegistration,
  });
  static ReferenceClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return ReferenceClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether references supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceClientCapabilities &&
        other.runtimeType == ReferenceClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Value-object that contains additional information when requesting
/// references.
class ReferenceContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceContext.canParse,
    ReferenceContext.fromJson,
  );

  ReferenceContext({
    required this.includeDeclaration,
  });
  static ReferenceContext fromJson(Map<String, Object?> json) {
    final includeDeclarationJson = json['includeDeclaration'];
    final includeDeclaration = includeDeclarationJson as bool;
    return ReferenceContext(
      includeDeclaration: includeDeclaration,
    );
  }

  /// Include the declaration of the current symbol.
  final bool includeDeclaration;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('includeDeclaration');
      try {
        if (!obj.containsKey('includeDeclaration')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final includeDeclaration = obj['includeDeclaration'];
        if (includeDeclaration == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (includeDeclaration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceContext &&
        other.runtimeType == ReferenceContext &&
        includeDeclaration == other.includeDeclaration;
  }

  @override
  int get hashCode => includeDeclaration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Reference options.
class ReferenceOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceOptions.canParse,
    ReferenceOptions.fromJson,
  );

  ReferenceOptions({
    this.workDoneProgress,
  });
  static ReferenceOptions fromJson(Map<String, Object?> json) {
    if (ReferenceRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ReferenceOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceOptions &&
        other.runtimeType == ReferenceOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a ReferencesRequest.
class ReferenceParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceParams.canParse,
    ReferenceParams.fromJson,
  );

  ReferenceParams({
    required this.context,
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static ReferenceParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context =
        ReferenceContext.fromJson(contextJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return ReferenceParams(
      context: context,
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  final ReferenceContext context;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['context'] = context.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('context');
      try {
        if (!obj.containsKey('context')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final context = obj['context'];
        if (context == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!ReferenceContext.canParse(context, reporter)) {
          reporter.reportError('must be of type ReferenceContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceParams &&
        other.runtimeType == ReferenceParams &&
        context == other.context &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        context,
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a ReferencesRequest.
class ReferenceRegistrationOptions
    implements ReferenceOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceRegistrationOptions.canParse,
    ReferenceRegistrationOptions.fromJson,
  );

  ReferenceRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static ReferenceRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ReferenceRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceRegistrationOptions &&
        other.runtimeType == ReferenceRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// General parameters to to register for an notification or to register a
/// provider.
class Registration implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Registration.canParse,
    Registration.fromJson,
  );

  Registration({
    required this.id,
    required this.method,
    this.registerOptions,
  });
  static Registration fromJson(Map<String, Object?> json) {
    final idJson = json['id'];
    final id = idJson as String;
    final methodJson = json['method'];
    final method = methodJson as String;
    final registerOptionsJson = json['registerOptions'];
    final registerOptions = registerOptionsJson;
    return Registration(
      id: id,
      method: method,
      registerOptions: registerOptions,
    );
  }

  /// The id used to register the request. The id can be used to deregister the
  /// request again.
  final String id;

  /// The method / capability to register for.
  final String method;

  /// Options necessary for the registration.
  final Object? registerOptions;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['id'] = id;
    result['method'] = method;
    if (registerOptions != null) {
      result['registerOptions'] = registerOptions;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final id = obj['id'];
        if (id == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('method');
      try {
        if (!obj.containsKey('method')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final method = obj['method'];
        if (method == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (method is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Registration');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Registration &&
        other.runtimeType == Registration &&
        id == other.id &&
        method == other.method &&
        registerOptions == other.registerOptions;
  }

  @override
  int get hashCode => Object.hash(
        id,
        method,
        registerOptions,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RegistrationParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RegistrationParams.canParse,
    RegistrationParams.fromJson,
  );

  RegistrationParams({
    required this.registrations,
  });
  static RegistrationParams fromJson(Map<String, Object?> json) {
    final registrationsJson = json['registrations'];
    final registrations = (registrationsJson as List<Object?>)
        .map((item) => Registration.fromJson(item as Map<String, Object?>))
        .toList();
    return RegistrationParams(
      registrations: registrations,
    );
  }

  final List<Registration> registrations;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['registrations'] =
        registrations.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('registrations');
      try {
        if (!obj.containsKey('registrations')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final registrations = obj['registrations'];
        if (registrations == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (registrations is! List<Object?> ||
            registrations
                .any((item) => !Registration.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Registration>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RegistrationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RegistrationParams &&
        other.runtimeType == RegistrationParams &&
        listEqual(registrations, other.registrations,
            (Registration a, Registration b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(registrations);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to regular expressions.
///
/// @since 3.16.0
class RegularExpressionsClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RegularExpressionsClientCapabilities.canParse,
    RegularExpressionsClientCapabilities.fromJson,
  );

  RegularExpressionsClientCapabilities({
    required this.engine,
    this.version,
  });
  static RegularExpressionsClientCapabilities fromJson(
      Map<String, Object?> json) {
    final engineJson = json['engine'];
    final engine = engineJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return RegularExpressionsClientCapabilities(
      engine: engine,
      version: version,
    );
  }

  /// The engine's name.
  final String engine;

  /// The engine's version.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['engine'] = engine;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('engine');
      try {
        if (!obj.containsKey('engine')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final engine = obj['engine'];
        if (engine == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (engine is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type RegularExpressionsClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RegularExpressionsClientCapabilities &&
        other.runtimeType == RegularExpressionsClientCapabilities &&
        engine == other.engine &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        engine,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A full diagnostic report with a set of related documents.
///
/// @since 3.17.0
class RelatedFullDocumentDiagnosticReport
    implements FullDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RelatedFullDocumentDiagnosticReport.canParse,
    RelatedFullDocumentDiagnosticReport.fromJson,
  );

  RelatedFullDocumentDiagnosticReport({
    required this.items,
    this.kind = 'full',
    this.relatedDocuments,
    this.resultId,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static RelatedFullDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>?)
        ?.map((key, value) => MapEntry(
            key as String,
            FullDocumentDiagnosticReport.canParse(value, nullLspJsonReporter)
                ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t1(
                    FullDocumentDiagnosticReport.fromJson(
                        value as Map<String, Object?>))
                : (UnchangedDocumentDiagnosticReport.canParse(
                        value, nullLspJsonReporter)
                    ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t2(
                        UnchangedDocumentDiagnosticReport.fromJson(
                            value as Map<String, Object?>))
                    : (throw '''$value was not one of (FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport)'''))));
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return RelatedFullDocumentDiagnosticReport(
      items: items,
      kind: kind,
      relatedDocuments: relatedDocuments,
      resultId: resultId,
    );
  }

  /// The actual items.
  @override
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  @override
  final String kind;

  /// Diagnostics of related documents. This information is useful in
  /// programming languages where code in a file A can generate diagnostics in a
  /// file B which A depends on. An example of such a language is C/C++ where
  /// marco definitions in a file a.cpp and result in errors in a header file
  /// b.hpp.
  ///
  /// @since 3.17.0
  final Map<
      String,
      Either2<FullDocumentDiagnosticReport,
          UnchangedDocumentDiagnosticReport>>? relatedDocuments;

  /// An optional result id. If provided it will be sent on the next diagnostic
  /// request for the same document.
  @override
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    result['kind'] = kind;
    if (relatedDocuments != null) {
      result['relatedDocuments'] = relatedDocuments;
    }
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) => !Diagnostic.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'full') {
          reporter.reportError('must be the literal \'full\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('relatedDocuments');
      try {
        final relatedDocuments = obj['relatedDocuments'];
        if (relatedDocuments != null &&
            (relatedDocuments is! Map ||
                (relatedDocuments.keys.any((item) =>
                    item is! String ||
                    relatedDocuments.values.any((item) =>
                        !FullDocumentDiagnosticReport.canParse(
                            item, reporter) &&
                        !UnchangedDocumentDiagnosticReport.canParse(
                            item, reporter)))))) {
          reporter.reportError(
              'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type RelatedFullDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RelatedFullDocumentDiagnosticReport &&
        other.runtimeType == RelatedFullDocumentDiagnosticReport &&
        listEqual(items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
        kind == other.kind &&
        mapEqual(
            relatedDocuments,
            other.relatedDocuments,
            (Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        a,
                    Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        b) =>
                a == b) &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(items),
        kind,
        lspHashCode(relatedDocuments),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An unchanged diagnostic report with a set of related documents.
///
/// @since 3.17.0
class RelatedUnchangedDocumentDiagnosticReport
    implements UnchangedDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RelatedUnchangedDocumentDiagnosticReport.canParse,
    RelatedUnchangedDocumentDiagnosticReport.fromJson,
  );

  RelatedUnchangedDocumentDiagnosticReport({
    this.kind = 'unchanged',
    this.relatedDocuments,
    required this.resultId,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static RelatedUnchangedDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>?)
        ?.map((key, value) => MapEntry(
            key as String,
            FullDocumentDiagnosticReport.canParse(value, nullLspJsonReporter)
                ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t1(
                    FullDocumentDiagnosticReport.fromJson(
                        value as Map<String, Object?>))
                : (UnchangedDocumentDiagnosticReport.canParse(
                        value, nullLspJsonReporter)
                    ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t2(
                        UnchangedDocumentDiagnosticReport.fromJson(
                            value as Map<String, Object?>))
                    : (throw '''$value was not one of (FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport)'''))));
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    return RelatedUnchangedDocumentDiagnosticReport(
      kind: kind,
      relatedDocuments: relatedDocuments,
      resultId: resultId,
    );
  }

  /// A document diagnostic report indicating no changes to the last result. A
  /// server can only return `unchanged` if result ids are provided.
  @override
  final String kind;

  /// Diagnostics of related documents. This information is useful in
  /// programming languages where code in a file A can generate diagnostics in a
  /// file B which A depends on. An example of such a language is C/C++ where
  /// marco definitions in a file a.cpp and result in errors in a header file
  /// b.hpp.
  ///
  /// @since 3.17.0
  final Map<
      String,
      Either2<FullDocumentDiagnosticReport,
          UnchangedDocumentDiagnosticReport>>? relatedDocuments;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  @override
  final String resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    if (relatedDocuments != null) {
      result['relatedDocuments'] = relatedDocuments;
    }
    result['resultId'] = resultId;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'unchanged') {
          reporter.reportError('must be the literal \'unchanged\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('relatedDocuments');
      try {
        final relatedDocuments = obj['relatedDocuments'];
        if (relatedDocuments != null &&
            (relatedDocuments is! Map ||
                (relatedDocuments.keys.any((item) =>
                    item is! String ||
                    relatedDocuments.values.any((item) =>
                        !FullDocumentDiagnosticReport.canParse(
                            item, reporter) &&
                        !UnchangedDocumentDiagnosticReport.canParse(
                            item, reporter)))))) {
          reporter.reportError(
              'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        if (!obj.containsKey('resultId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final resultId = obj['resultId'];
        if (resultId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type RelatedUnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RelatedUnchangedDocumentDiagnosticReport &&
        other.runtimeType == RelatedUnchangedDocumentDiagnosticReport &&
        kind == other.kind &&
        mapEqual(
            relatedDocuments,
            other.relatedDocuments,
            (Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        a,
                    Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        b) =>
                a == b) &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        lspHashCode(relatedDocuments),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A relative pattern is a helper to construct glob patterns that are matched
/// relatively to a base URI. The common value for a `baseUri` is a workspace
/// folder root, but it can be another absolute URI as well.
///
/// @since 3.17.0
class RelativePattern implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RelativePattern.canParse,
    RelativePattern.fromJson,
  );

  RelativePattern({
    required this.baseUri,
    required this.pattern,
  });
  static RelativePattern fromJson(Map<String, Object?> json) {
    final baseUriJson = json['baseUri'];
    final baseUri = baseUriJson is String
        ? Either2<String, WorkspaceFolder>.t1(baseUriJson)
        : (WorkspaceFolder.canParse(baseUriJson, nullLspJsonReporter)
            ? Either2<String, WorkspaceFolder>.t2(
                WorkspaceFolder.fromJson(baseUriJson as Map<String, Object?>))
            : (throw '''$baseUriJson was not one of (String, WorkspaceFolder)'''));
    final patternJson = json['pattern'];
    final pattern = patternJson as String;
    return RelativePattern(
      baseUri: baseUri,
      pattern: pattern,
    );
  }

  /// A workspace folder or a base URI to which this pattern will be matched
  /// against relatively.
  final Either2<String, WorkspaceFolder> baseUri;

  /// The actual glob pattern;
  final String pattern;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['baseUri'] = baseUri;
    result['pattern'] = pattern;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('baseUri');
      try {
        if (!obj.containsKey('baseUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final baseUri = obj['baseUri'];
        if (baseUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (baseUri is! String &&
            !WorkspaceFolder.canParse(baseUri, reporter)) {
          reporter
              .reportError('must be of type Either2<String, WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        if (!obj.containsKey('pattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final pattern = obj['pattern'];
        if (pattern == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RelativePattern');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RelativePattern &&
        other.runtimeType == RelativePattern &&
        baseUri == other.baseUri &&
        pattern == other.pattern;
  }

  @override
  int get hashCode => Object.hash(
        baseUri,
        pattern,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RenameClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameClientCapabilities.canParse,
    RenameClientCapabilities.fromJson,
  );

  RenameClientCapabilities({
    this.dynamicRegistration,
    this.honorsChangeAnnotations,
    this.prepareSupport,
    this.prepareSupportDefaultBehavior,
  });
  static RenameClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final honorsChangeAnnotationsJson = json['honorsChangeAnnotations'];
    final honorsChangeAnnotations = honorsChangeAnnotationsJson as bool?;
    final prepareSupportJson = json['prepareSupport'];
    final prepareSupport = prepareSupportJson as bool?;
    final prepareSupportDefaultBehaviorJson =
        json['prepareSupportDefaultBehavior'];
    final prepareSupportDefaultBehavior =
        prepareSupportDefaultBehaviorJson != null
            ? PrepareSupportDefaultBehavior.fromJson(
                prepareSupportDefaultBehaviorJson as int)
            : null;
    return RenameClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      honorsChangeAnnotations: honorsChangeAnnotations,
      prepareSupport: prepareSupport,
      prepareSupportDefaultBehavior: prepareSupportDefaultBehavior,
    );
  }

  /// Whether rename supports dynamic registration.
  final bool? dynamicRegistration;

  /// Whether the client honors the change annotations in text edits and
  /// resource operations returned via the rename request's workspace edit by
  /// for example presenting the workspace edit in the user interface and asking
  /// for confirmation.
  ///
  /// @since 3.16.0
  final bool? honorsChangeAnnotations;

  /// Client supports testing for validity of rename operations before
  /// execution.
  ///
  /// @since 3.12.0
  final bool? prepareSupport;

  /// Client supports the default behavior result.
  ///
  /// The value indicates the default behavior used by the client.
  ///
  /// @since 3.16.0
  final PrepareSupportDefaultBehavior? prepareSupportDefaultBehavior;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (honorsChangeAnnotations != null) {
      result['honorsChangeAnnotations'] = honorsChangeAnnotations;
    }
    if (prepareSupport != null) {
      result['prepareSupport'] = prepareSupport;
    }
    if (prepareSupportDefaultBehavior != null) {
      result['prepareSupportDefaultBehavior'] =
          prepareSupportDefaultBehavior?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('honorsChangeAnnotations');
      try {
        final honorsChangeAnnotations = obj['honorsChangeAnnotations'];
        if (honorsChangeAnnotations != null &&
            honorsChangeAnnotations is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('prepareSupport');
      try {
        final prepareSupport = obj['prepareSupport'];
        if (prepareSupport != null && prepareSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('prepareSupportDefaultBehavior');
      try {
        final prepareSupportDefaultBehavior =
            obj['prepareSupportDefaultBehavior'];
        if (prepareSupportDefaultBehavior != null &&
            !PrepareSupportDefaultBehavior.canParse(
                prepareSupportDefaultBehavior, reporter)) {
          reporter.reportError('must be of type PrepareSupportDefaultBehavior');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameClientCapabilities &&
        other.runtimeType == RenameClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        honorsChangeAnnotations == other.honorsChangeAnnotations &&
        prepareSupport == other.prepareSupport &&
        prepareSupportDefaultBehavior == other.prepareSupportDefaultBehavior;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        honorsChangeAnnotations,
        prepareSupport,
        prepareSupportDefaultBehavior,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Rename file operation
class RenameFile implements ResourceOperation, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFile.canParse,
    RenameFile.fromJson,
  );

  RenameFile({
    this.annotationId,
    this.kind = 'rename',
    required this.newUri,
    required this.oldUri,
    this.options,
  }) {
    if (kind != 'rename') {
      throw 'kind may only be the literal \'rename\'';
    }
  }
  static RenameFile fromJson(Map<String, Object?> json) {
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final newUriJson = json['newUri'];
    final newUri = newUriJson as String;
    final oldUriJson = json['oldUri'];
    final oldUri = oldUriJson as String;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? RenameFileOptions.fromJson(optionsJson as Map<String, Object?>)
        : null;
    return RenameFile(
      annotationId: annotationId,
      kind: kind,
      newUri: newUri,
      oldUri: oldUri,
      options: options,
    );
  }

  /// An optional annotation identifier describing the operation.
  ///
  /// @since 3.16.0
  @override
  final String? annotationId;

  /// A rename
  @override
  final String kind;

  /// The new location.
  final String newUri;

  /// The old (existing) location.
  final String oldUri;

  /// Rename options.
  final RenameFileOptions? options;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (annotationId != null) {
      result['annotationId'] = annotationId;
    }
    result['kind'] = kind;
    result['newUri'] = newUri;
    result['oldUri'] = oldUri;
    if (options != null) {
      result['options'] = options?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('annotationId');
      try {
        final annotationId = obj['annotationId'];
        if (annotationId != null && annotationId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'rename') {
          reporter.reportError('must be the literal \'rename\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('newUri');
      try {
        if (!obj.containsKey('newUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newUri = obj['newUri'];
        if (newUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('oldUri');
      try {
        if (!obj.containsKey('oldUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final oldUri = obj['oldUri'];
        if (oldUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (oldUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        final options = obj['options'];
        if (options != null && !RenameFileOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type RenameFileOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameFile');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameFile &&
        other.runtimeType == RenameFile &&
        annotationId == other.annotationId &&
        kind == other.kind &&
        newUri == other.newUri &&
        oldUri == other.oldUri &&
        options == other.options;
  }

  @override
  int get hashCode => Object.hash(
        annotationId,
        kind,
        newUri,
        oldUri,
        options,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Rename file options
class RenameFileOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFileOptions.canParse,
    RenameFileOptions.fromJson,
  );

  RenameFileOptions({
    this.ignoreIfExists,
    this.overwrite,
  });
  static RenameFileOptions fromJson(Map<String, Object?> json) {
    final ignoreIfExistsJson = json['ignoreIfExists'];
    final ignoreIfExists = ignoreIfExistsJson as bool?;
    final overwriteJson = json['overwrite'];
    final overwrite = overwriteJson as bool?;
    return RenameFileOptions(
      ignoreIfExists: ignoreIfExists,
      overwrite: overwrite,
    );
  }

  /// Ignores if target exists.
  final bool? ignoreIfExists;

  /// Overwrite target if existing. Overwrite wins over `ignoreIfExists`
  final bool? overwrite;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (ignoreIfExists != null) {
      result['ignoreIfExists'] = ignoreIfExists;
    }
    if (overwrite != null) {
      result['overwrite'] = overwrite;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ignoreIfExists');
      try {
        final ignoreIfExists = obj['ignoreIfExists'];
        if (ignoreIfExists != null && ignoreIfExists is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('overwrite');
      try {
        final overwrite = obj['overwrite'];
        if (overwrite != null && overwrite is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameFileOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameFileOptions &&
        other.runtimeType == RenameFileOptions &&
        ignoreIfExists == other.ignoreIfExists &&
        overwrite == other.overwrite;
  }

  @override
  int get hashCode => Object.hash(
        ignoreIfExists,
        overwrite,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters sent in notifications/requests for user-initiated renames of
/// files.
///
/// @since 3.16.0
class RenameFilesParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFilesParams.canParse,
    RenameFilesParams.fromJson,
  );

  RenameFilesParams({
    required this.files,
  });
  static RenameFilesParams fromJson(Map<String, Object?> json) {
    final filesJson = json['files'];
    final files = (filesJson as List<Object?>)
        .map((item) => FileRename.fromJson(item as Map<String, Object?>))
        .toList();
    return RenameFilesParams(
      files: files,
    );
  }

  /// An array of all files/folders renamed in this operation. When a folder is
  /// renamed, only the folder will be included, and not its children.
  final List<FileRename> files;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('files');
      try {
        if (!obj.containsKey('files')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final files = obj['files'];
        if (files == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (files is! List<Object?> ||
            files.any((item) => !FileRename.canParse(item, reporter))) {
          reporter.reportError('must be of type List<FileRename>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameFilesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameFilesParams &&
        other.runtimeType == RenameFilesParams &&
        listEqual(files, other.files, (FileRename a, FileRename b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(files);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a RenameRequest.
class RenameOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameOptions.canParse,
    RenameOptions.fromJson,
  );

  RenameOptions({
    this.prepareProvider,
    this.workDoneProgress,
  });
  static RenameOptions fromJson(Map<String, Object?> json) {
    if (RenameRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return RenameRegistrationOptions.fromJson(json);
    }
    final prepareProviderJson = json['prepareProvider'];
    final prepareProvider = prepareProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return RenameOptions(
      prepareProvider: prepareProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Renames should be checked and tested before being executed.
  ///
  /// @since version 3.12.0
  final bool? prepareProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (prepareProvider != null) {
      result['prepareProvider'] = prepareProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('prepareProvider');
      try {
        final prepareProvider = obj['prepareProvider'];
        if (prepareProvider != null && prepareProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameOptions &&
        other.runtimeType == RenameOptions &&
        prepareProvider == other.prepareProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        prepareProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a RenameRequest.
class RenameParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameParams.canParse,
    RenameParams.fromJson,
  );

  RenameParams({
    required this.newName,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static RenameParams fromJson(Map<String, Object?> json) {
    final newNameJson = json['newName'];
    final newName = newNameJson as String;
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return RenameParams(
      newName: newName,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The new name of the symbol. If the given name is not valid the request
  /// must return a ResponseError with an appropriate message set.
  final String newName;

  /// The position at which this request was sent.
  final Position position;

  /// The document to rename.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['newName'] = newName;
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('newName');
      try {
        if (!obj.containsKey('newName')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newName = obj['newName'];
        if (newName == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newName is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameParams &&
        other.runtimeType == RenameParams &&
        newName == other.newName &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        newName,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a RenameRequest.
class RenameRegistrationOptions
    implements RenameOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameRegistrationOptions.canParse,
    RenameRegistrationOptions.fromJson,
  );

  RenameRegistrationOptions({
    this.documentSelector,
    this.prepareProvider,
    this.workDoneProgress,
  });
  static RenameRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final prepareProviderJson = json['prepareProvider'];
    final prepareProvider = prepareProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return RenameRegistrationOptions(
      documentSelector: documentSelector,
      prepareProvider: prepareProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// Renames should be checked and tested before being executed.
  ///
  /// @since version 3.12.0
  @override
  final bool? prepareProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (prepareProvider != null) {
      result['prepareProvider'] = prepareProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('prepareProvider');
      try {
        final prepareProvider = obj['prepareProvider'];
        if (prepareProvider != null && prepareProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameRegistrationOptions &&
        other.runtimeType == RenameRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        prepareProvider == other.prepareProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        prepareProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A generic resource operation.
class ResourceOperation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ResourceOperation.canParse,
    ResourceOperation.fromJson,
  );

  ResourceOperation({
    this.annotationId,
    required this.kind,
  });
  static ResourceOperation fromJson(Map<String, Object?> json) {
    if (RenameFile.canParse(json, nullLspJsonReporter)) {
      return RenameFile.fromJson(json);
    }
    if (CreateFile.canParse(json, nullLspJsonReporter)) {
      return CreateFile.fromJson(json);
    }
    if (DeleteFile.canParse(json, nullLspJsonReporter)) {
      return DeleteFile.fromJson(json);
    }
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    return ResourceOperation(
      annotationId: annotationId,
      kind: kind,
    );
  }

  /// An optional annotation identifier describing the operation.
  ///
  /// @since 3.16.0
  final String? annotationId;

  /// The resource operation kind.
  final String kind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (annotationId != null) {
      result['annotationId'] = annotationId;
    }
    result['kind'] = kind;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('annotationId');
      try {
        final annotationId = obj['annotationId'];
        if (annotationId != null && annotationId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ResourceOperation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ResourceOperation &&
        other.runtimeType == ResourceOperation &&
        annotationId == other.annotationId &&
        kind == other.kind;
  }

  @override
  int get hashCode => Object.hash(
        annotationId,
        kind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ResourceOperationKind implements ToJsonable {
  const ResourceOperationKind._(this._value);
  const ResourceOperationKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'create':
      case 'delete':
      case 'rename':
        return true;
    }
    return false;
  }

  /// Supports creating new files and folders.
  static const Create = ResourceOperationKind._('create');

  /// Supports deleting existing files and folders.
  static const Delete = ResourceOperationKind._('delete');

  /// Supports renaming existing files and folders.
  static const Rename = ResourceOperationKind._('rename');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is ResourceOperationKind && other._value == _value;
}

/// Save options.
class SaveOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SaveOptions.canParse,
    SaveOptions.fromJson,
  );

  SaveOptions({
    this.includeText,
  });
  static SaveOptions fromJson(Map<String, Object?> json) {
    if (TextDocumentSaveRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentSaveRegistrationOptions.fromJson(json);
    }
    final includeTextJson = json['includeText'];
    final includeText = includeTextJson as bool?;
    return SaveOptions(
      includeText: includeText,
    );
  }

  /// The client is supposed to include the content on save.
  final bool? includeText;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (includeText != null) {
      result['includeText'] = includeText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('includeText');
      try {
        final includeText = obj['includeText'];
        if (includeText != null && includeText is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SaveOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SaveOptions &&
        other.runtimeType == SaveOptions &&
        includeText == other.includeText;
  }

  @override
  int get hashCode => includeText.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A selection range represents a part of a selection hierarchy. A selection
/// range may have a parent selection range that contains it.
class SelectionRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRange.canParse,
    SelectionRange.fromJson,
  );

  SelectionRange({
    this.parent,
    required this.range,
  });
  static SelectionRange fromJson(Map<String, Object?> json) {
    final parentJson = json['parent'];
    final parent = parentJson != null
        ? SelectionRange.fromJson(parentJson as Map<String, Object?>)
        : null;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return SelectionRange(
      parent: parent,
      range: range,
    );
  }

  /// The parent selection range containing this range. Therefore `parent.range`
  /// must contain `this.range`.
  final SelectionRange? parent;

  /// The range of this selection range.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (parent != null) {
      result['parent'] = parent?.toJson();
    }
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('parent');
      try {
        final parent = obj['parent'];
        if (parent != null && !SelectionRange.canParse(parent, reporter)) {
          reporter.reportError('must be of type SelectionRange');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRange &&
        other.runtimeType == SelectionRange &&
        parent == other.parent &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        parent,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeClientCapabilities.canParse,
    SelectionRangeClientCapabilities.fromJson,
  );

  SelectionRangeClientCapabilities({
    this.dynamicRegistration,
  });
  static SelectionRangeClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return SelectionRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration for selection range
  /// providers. If this is set to `true` the client supports the new
  /// `SelectionRangeRegistrationOptions` return value for the corresponding
  /// server capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRangeClientCapabilities &&
        other.runtimeType == SelectionRangeClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeOptions.canParse,
    SelectionRangeOptions.fromJson,
  );

  SelectionRangeOptions({
    this.workDoneProgress,
  });
  static SelectionRangeOptions fromJson(Map<String, Object?> json) {
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SelectionRangeOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRangeOptions &&
        other.runtimeType == SelectionRangeOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in selection range requests.
class SelectionRangeParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeParams.canParse,
    SelectionRangeParams.fromJson,
  );

  SelectionRangeParams({
    this.partialResultToken,
    required this.positions,
    required this.textDocument,
    this.workDoneToken,
  });
  static SelectionRangeParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionsJson = json['positions'];
    final positions = (positionsJson as List<Object?>)
        .map((item) => Position.fromJson(item as Map<String, Object?>))
        .toList();
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SelectionRangeParams(
      partialResultToken: partialResultToken,
      positions: positions,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The positions inside the text document.
  final List<Position> positions;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['positions'] = positions.map((item) => item.toJson()).toList();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('positions');
      try {
        if (!obj.containsKey('positions')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final positions = obj['positions'];
        if (positions == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (positions is! List<Object?> ||
            positions.any((item) => !Position.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Position>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRangeParams &&
        other.runtimeType == SelectionRangeParams &&
        partialResultToken == other.partialResultToken &&
        listEqual(
            positions, other.positions, (Position a, Position b) => a == b) &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        lspHashCode(positions),
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeRegistrationOptions
    implements
        SelectionRangeOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeRegistrationOptions.canParse,
    SelectionRangeRegistrationOptions.fromJson,
  );

  SelectionRangeRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static SelectionRangeRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SelectionRangeRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRangeRegistrationOptions &&
        other.runtimeType == SelectionRangeRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A set of predefined token modifiers. This set is not fixed an clients can
/// specify additional token types via the corresponding client capabilities.
///
/// @since 3.16.0
class SemanticTokenModifiers implements ToJsonable {
  const SemanticTokenModifiers(this._value);
  const SemanticTokenModifiers.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  static const abstract = SemanticTokenModifiers('abstract');
  static const async = SemanticTokenModifiers('async');
  static const declaration = SemanticTokenModifiers('declaration');
  static const defaultLibrary = SemanticTokenModifiers('defaultLibrary');
  static const definition = SemanticTokenModifiers('definition');
  static const deprecated = SemanticTokenModifiers('deprecated');
  static const documentation = SemanticTokenModifiers('documentation');
  static const modification = SemanticTokenModifiers('modification');
  static const readonly = SemanticTokenModifiers('readonly');
  static const static = SemanticTokenModifiers('static');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SemanticTokenModifiers && other._value == _value;
}

/// A set of predefined token types. This set is not fixed an clients can
/// specify additional token types via the corresponding client capabilities.
///
/// @since 3.16.0
class SemanticTokenTypes implements ToJsonable {
  const SemanticTokenTypes(this._value);
  const SemanticTokenTypes.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  static const class_ = SemanticTokenTypes('class');
  static const comment = SemanticTokenTypes('comment');

  /// @since 3.17.0
  static const decorator = SemanticTokenTypes('decorator');
  static const enum_ = SemanticTokenTypes('enum');
  static const enumMember = SemanticTokenTypes('enumMember');
  static const event = SemanticTokenTypes('event');
  static const function = SemanticTokenTypes('function');
  static const interface = SemanticTokenTypes('interface');
  static const keyword = SemanticTokenTypes('keyword');
  static const macro = SemanticTokenTypes('macro');
  static const method = SemanticTokenTypes('method');
  static const modifier = SemanticTokenTypes('modifier');
  static const namespace = SemanticTokenTypes('namespace');
  static const number = SemanticTokenTypes('number');
  static const operator = SemanticTokenTypes('operator');
  static const parameter = SemanticTokenTypes('parameter');
  static const property = SemanticTokenTypes('property');
  static const regexp = SemanticTokenTypes('regexp');
  static const string = SemanticTokenTypes('string');
  static const struct = SemanticTokenTypes('struct');

  /// Represents a generic type. Acts as a fallback for types which can't be
  /// mapped to a specific type like class or enum.
  static const type = SemanticTokenTypes('type');
  static const typeParameter = SemanticTokenTypes('typeParameter');
  static const variable = SemanticTokenTypes('variable');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SemanticTokenTypes && other._value == _value;
}

/// @since 3.16.0
class SemanticTokens implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokens.canParse,
    SemanticTokens.fromJson,
  );

  SemanticTokens({
    required this.data,
    this.resultId,
  });
  static SemanticTokens fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>).map((item) => item as int).toList();
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return SemanticTokens(
      data: data,
      resultId: resultId,
    );
  }

  /// The actual tokens.
  final List<int> data;

  /// An optional result id. If provided and clients support delta updating the
  /// client will include the result id in the next semantic token request. A
  /// server can then instead of computing all semantic tokens again simply send
  /// a delta.
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['data'] = data;
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('data');
      try {
        if (!obj.containsKey('data')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final data = obj['data'];
        if (data == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (data is! List<Object?> || data.any((item) => item is! int)) {
          reporter.reportError('must be of type List<int>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokens');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokens &&
        other.runtimeType == SemanticTokens &&
        listEqual(data, other.data, (int a, int b) => a == b) &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilities.canParse,
    SemanticTokensClientCapabilities.fromJson,
  );

  SemanticTokensClientCapabilities({
    this.augmentsSyntaxTokens,
    this.dynamicRegistration,
    required this.formats,
    this.multilineTokenSupport,
    this.overlappingTokenSupport,
    required this.requests,
    this.serverCancelSupport,
    required this.tokenModifiers,
    required this.tokenTypes,
  });
  static SemanticTokensClientCapabilities fromJson(Map<String, Object?> json) {
    final augmentsSyntaxTokensJson = json['augmentsSyntaxTokens'];
    final augmentsSyntaxTokens = augmentsSyntaxTokensJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final formatsJson = json['formats'];
    final formats = (formatsJson as List<Object?>)
        .map((item) => TokenFormat.fromJson(item as String))
        .toList();
    final multilineTokenSupportJson = json['multilineTokenSupport'];
    final multilineTokenSupport = multilineTokenSupportJson as bool?;
    final overlappingTokenSupportJson = json['overlappingTokenSupport'];
    final overlappingTokenSupport = overlappingTokenSupportJson as bool?;
    final requestsJson = json['requests'];
    final requests = SemanticTokensClientCapabilitiesRequests.fromJson(
        requestsJson as Map<String, Object?>);
    final serverCancelSupportJson = json['serverCancelSupport'];
    final serverCancelSupport = serverCancelSupportJson as bool?;
    final tokenModifiersJson = json['tokenModifiers'];
    final tokenModifiers = (tokenModifiersJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    final tokenTypesJson = json['tokenTypes'];
    final tokenTypes = (tokenTypesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return SemanticTokensClientCapabilities(
      augmentsSyntaxTokens: augmentsSyntaxTokens,
      dynamicRegistration: dynamicRegistration,
      formats: formats,
      multilineTokenSupport: multilineTokenSupport,
      overlappingTokenSupport: overlappingTokenSupport,
      requests: requests,
      serverCancelSupport: serverCancelSupport,
      tokenModifiers: tokenModifiers,
      tokenTypes: tokenTypes,
    );
  }

  /// Whether the client uses semantic tokens to augment existing syntax tokens.
  /// If set to `true` client side created syntax tokens and semantic tokens are
  /// both used for colorization. If set to `false` the client only uses the
  /// returned semantic tokens for colorization.
  ///
  /// If the value is `undefined` then the client behavior is not specified.
  ///
  /// @since 3.17.0
  final bool? augmentsSyntaxTokens;

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  /// The token formats the clients supports.
  final List<TokenFormat> formats;

  /// Whether the client supports tokens that can span multiple lines.
  final bool? multilineTokenSupport;

  /// Whether the client supports tokens that can overlap each other.
  final bool? overlappingTokenSupport;

  /// Which requests the client supports and might send to the server depending
  /// on the server's capability. Please note that clients might not show
  /// semantic tokens or degrade some of the user experience if a range or full
  /// request is advertised by the client but not provided by the server. If for
  /// example the client capability `requests.full` and `request.range` are both
  /// set to true but the server only provides a range provider the client might
  /// not render a minimap correctly or might even decide to not show any
  /// semantic tokens at all.
  final SemanticTokensClientCapabilitiesRequests requests;

  /// Whether the client allows the server to actively cancel a semantic token
  /// request, e.g. supports returning LSPErrorCodes.ServerCancelled. If a
  /// server does the client needs to retrigger the request.
  ///
  /// @since 3.17.0
  final bool? serverCancelSupport;

  /// The token modifiers that the client supports.
  final List<String> tokenModifiers;

  /// The token types that the client supports.
  final List<String> tokenTypes;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (augmentsSyntaxTokens != null) {
      result['augmentsSyntaxTokens'] = augmentsSyntaxTokens;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    result['formats'] = formats.map((item) => item.toJson()).toList();
    if (multilineTokenSupport != null) {
      result['multilineTokenSupport'] = multilineTokenSupport;
    }
    if (overlappingTokenSupport != null) {
      result['overlappingTokenSupport'] = overlappingTokenSupport;
    }
    result['requests'] = requests.toJson();
    if (serverCancelSupport != null) {
      result['serverCancelSupport'] = serverCancelSupport;
    }
    result['tokenModifiers'] = tokenModifiers;
    result['tokenTypes'] = tokenTypes;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('augmentsSyntaxTokens');
      try {
        final augmentsSyntaxTokens = obj['augmentsSyntaxTokens'];
        if (augmentsSyntaxTokens != null && augmentsSyntaxTokens is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('formats');
      try {
        if (!obj.containsKey('formats')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final formats = obj['formats'];
        if (formats == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (formats is! List<Object?> ||
            formats.any((item) => !TokenFormat.canParse(item, reporter))) {
          reporter.reportError('must be of type List<TokenFormat>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('multilineTokenSupport');
      try {
        final multilineTokenSupport = obj['multilineTokenSupport'];
        if (multilineTokenSupport != null && multilineTokenSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('overlappingTokenSupport');
      try {
        final overlappingTokenSupport = obj['overlappingTokenSupport'];
        if (overlappingTokenSupport != null &&
            overlappingTokenSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('requests');
      try {
        if (!obj.containsKey('requests')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final requests = obj['requests'];
        if (requests == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SemanticTokensClientCapabilitiesRequests.canParse(
            requests, reporter)) {
          reporter.reportError(
              'must be of type SemanticTokensClientCapabilitiesRequests');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('serverCancelSupport');
      try {
        final serverCancelSupport = obj['serverCancelSupport'];
        if (serverCancelSupport != null && serverCancelSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tokenModifiers');
      try {
        if (!obj.containsKey('tokenModifiers')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tokenModifiers = obj['tokenModifiers'];
        if (tokenModifiers == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tokenModifiers is! List<Object?> ||
            tokenModifiers.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tokenTypes');
      try {
        if (!obj.containsKey('tokenTypes')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tokenTypes = obj['tokenTypes'];
        if (tokenTypes == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tokenTypes is! List<Object?> ||
            tokenTypes.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensClientCapabilities &&
        other.runtimeType == SemanticTokensClientCapabilities &&
        augmentsSyntaxTokens == other.augmentsSyntaxTokens &&
        dynamicRegistration == other.dynamicRegistration &&
        listEqual(
            formats, other.formats, (TokenFormat a, TokenFormat b) => a == b) &&
        multilineTokenSupport == other.multilineTokenSupport &&
        overlappingTokenSupport == other.overlappingTokenSupport &&
        requests == other.requests &&
        serverCancelSupport == other.serverCancelSupport &&
        listEqual(tokenModifiers, other.tokenModifiers,
            (String a, String b) => a == b) &&
        listEqual(tokenTypes, other.tokenTypes, (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        augmentsSyntaxTokens,
        dynamicRegistration,
        lspHashCode(formats),
        multilineTokenSupport,
        overlappingTokenSupport,
        requests,
        serverCancelSupport,
        lspHashCode(tokenModifiers),
        lspHashCode(tokenTypes),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequests implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesRequests.canParse,
    SemanticTokensClientCapabilitiesRequests.fromJson,
  );

  SemanticTokensClientCapabilitiesRequests({
    this.full,
    this.range,
  });
  static SemanticTokensClientCapabilitiesRequests fromJson(
      Map<String, Object?> json) {
    final fullJson = json['full'];
    final full = fullJson == null
        ? null
        : (fullJson is bool
            ? Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>.t1(
                fullJson)
            : (SemanticTokensClientCapabilitiesRequestsFull.canParse(
                    fullJson, nullLspJsonReporter)
                ? Either2<bool,
                        SemanticTokensClientCapabilitiesRequestsFull>.t2(
                    SemanticTokensClientCapabilitiesRequestsFull.fromJson(
                        fullJson as Map<String, Object?>))
                : (throw '''$fullJson was not one of (bool, SemanticTokensClientCapabilitiesRequestsFull)''')));
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : (rangeJson is bool
            ? Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>.t1(
                rangeJson)
            : (SemanticTokensClientCapabilitiesRequestsRange.canParse(
                    rangeJson, nullLspJsonReporter)
                ? Either2<bool,
                        SemanticTokensClientCapabilitiesRequestsRange>.t2(
                    SemanticTokensClientCapabilitiesRequestsRange.fromJson(
                        rangeJson as Map<String, Object?>))
                : (throw '''$rangeJson was not one of (bool, SemanticTokensClientCapabilitiesRequestsRange)''')));
    return SemanticTokensClientCapabilitiesRequests(
      full: full,
      range: range,
    );
  }

  /// The client will send the `textDocument/semanticTokens/full` request if the
  /// server provides a corresponding handler.
  final Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>? full;

  /// The client will send the `textDocument/semanticTokens/range` request if
  /// the server provides a corresponding handler.
  final Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>? range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (full != null) {
      result['full'] = full;
    }
    if (range != null) {
      result['range'] = range;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('full');
      try {
        final full = obj['full'];
        if (full != null &&
            full is! bool &&
            !SemanticTokensClientCapabilitiesRequestsFull.canParse(
                full, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        final range = obj['range'];
        if (range != null &&
            range is! bool &&
            !SemanticTokensClientCapabilitiesRequestsRange.canParse(
                range, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequests');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensClientCapabilitiesRequests &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequests &&
        full == other.full &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        full,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequestsFull implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesRequestsFull.canParse,
    SemanticTokensClientCapabilitiesRequestsFull.fromJson,
  );

  SemanticTokensClientCapabilitiesRequestsFull({
    this.delta,
  });
  static SemanticTokensClientCapabilitiesRequestsFull fromJson(
      Map<String, Object?> json) {
    final deltaJson = json['delta'];
    final delta = deltaJson as bool?;
    return SemanticTokensClientCapabilitiesRequestsFull(
      delta: delta,
    );
  }

  /// The client will send the `textDocument/semanticTokens/full/delta` request
  /// if the server provides a corresponding handler.
  final bool? delta;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (delta != null) {
      result['delta'] = delta;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('delta');
      try {
        final delta = obj['delta'];
        if (delta != null && delta is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequestsFull');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensClientCapabilitiesRequestsFull &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequestsFull &&
        delta == other.delta;
  }

  @override
  int get hashCode => delta.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequestsRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesRequestsRange.canParse,
    SemanticTokensClientCapabilitiesRequestsRange.fromJson,
  );

  static SemanticTokensClientCapabilitiesRequestsRange fromJson(
      Map<String, Object?> json) {
    return SemanticTokensClientCapabilitiesRequestsRange();
  }

  @override
  Map<String, Object?> toJson() => {};

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequestsRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensClientCapabilitiesRequestsRange &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequestsRange;
  }

  @override
  int get hashCode => 42;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensDelta implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensDelta.canParse,
    SemanticTokensDelta.fromJson,
  );

  SemanticTokensDelta({
    required this.edits,
    this.resultId,
  });
  static SemanticTokensDelta fromJson(Map<String, Object?> json) {
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map(
            (item) => SemanticTokensEdit.fromJson(item as Map<String, Object?>))
        .toList();
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return SemanticTokensDelta(
      edits: edits,
      resultId: resultId,
    );
  }

  /// The semantic token edits to transform a previous result into a new result.
  final List<SemanticTokensEdit> edits;
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['edits'] = edits.map((item) => item.toJson()).toList();
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('edits');
      try {
        if (!obj.containsKey('edits')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final edits = obj['edits'];
        if (edits == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (edits is! List<Object?> ||
            edits.any((item) => !SemanticTokensEdit.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SemanticTokensEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensDelta');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensDelta &&
        other.runtimeType == SemanticTokensDelta &&
        listEqual(edits, other.edits,
            (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(edits),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensDeltaParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensDeltaParams.canParse,
    SemanticTokensDeltaParams.fromJson,
  );

  SemanticTokensDeltaParams({
    this.partialResultToken,
    required this.previousResultId,
    required this.textDocument,
    this.workDoneToken,
  });
  static SemanticTokensDeltaParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final previousResultIdJson = json['previousResultId'];
    final previousResultId = previousResultIdJson as String;
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SemanticTokensDeltaParams(
      partialResultToken: partialResultToken,
      previousResultId: previousResultId,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The result id of a previous response. The result Id can either point to a
  /// full response or a delta response depending on what was received last.
  final String previousResultId;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['previousResultId'] = previousResultId;
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('previousResultId');
      try {
        if (!obj.containsKey('previousResultId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final previousResultId = obj['previousResultId'];
        if (previousResultId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (previousResultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensDeltaParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensDeltaParams &&
        other.runtimeType == SemanticTokensDeltaParams &&
        partialResultToken == other.partialResultToken &&
        previousResultId == other.previousResultId &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        previousResultId,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensDeltaPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensDeltaPartialResult.canParse,
    SemanticTokensDeltaPartialResult.fromJson,
  );

  SemanticTokensDeltaPartialResult({
    required this.edits,
  });
  static SemanticTokensDeltaPartialResult fromJson(Map<String, Object?> json) {
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map(
            (item) => SemanticTokensEdit.fromJson(item as Map<String, Object?>))
        .toList();
    return SemanticTokensDeltaPartialResult(
      edits: edits,
    );
  }

  final List<SemanticTokensEdit> edits;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['edits'] = edits.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('edits');
      try {
        if (!obj.containsKey('edits')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final edits = obj['edits'];
        if (edits == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (edits is! List<Object?> ||
            edits.any((item) => !SemanticTokensEdit.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SemanticTokensEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensDeltaPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensDeltaPartialResult &&
        other.runtimeType == SemanticTokensDeltaPartialResult &&
        listEqual(edits, other.edits,
            (SemanticTokensEdit a, SemanticTokensEdit b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(edits);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensEdit.canParse,
    SemanticTokensEdit.fromJson,
  );

  SemanticTokensEdit({
    this.data,
    required this.deleteCount,
    required this.start,
  });
  static SemanticTokensEdit fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>?)?.map((item) => item as int).toList();
    final deleteCountJson = json['deleteCount'];
    final deleteCount = deleteCountJson as int;
    final startJson = json['start'];
    final start = startJson as int;
    return SemanticTokensEdit(
      data: data,
      deleteCount: deleteCount,
      start: start,
    );
  }

  /// The elements to insert.
  final List<int>? data;

  /// The count of elements to remove.
  final int deleteCount;

  /// The start offset of the edit.
  final int start;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    result['deleteCount'] = deleteCount;
    result['start'] = start;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('data');
      try {
        final data = obj['data'];
        if (data != null &&
            (data is! List<Object?> || data.any((item) => item is! int))) {
          reporter.reportError('must be of type List<int>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deleteCount');
      try {
        if (!obj.containsKey('deleteCount')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final deleteCount = obj['deleteCount'];
        if (deleteCount == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (deleteCount is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('start');
      try {
        if (!obj.containsKey('start')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final start = obj['start'];
        if (start == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (start is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensEdit &&
        other.runtimeType == SemanticTokensEdit &&
        listEqual(data, other.data, (int a, int b) => a == b) &&
        deleteCount == other.deleteCount &&
        start == other.start;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        deleteCount,
        start,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensLegend implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensLegend.canParse,
    SemanticTokensLegend.fromJson,
  );

  SemanticTokensLegend({
    required this.tokenModifiers,
    required this.tokenTypes,
  });
  static SemanticTokensLegend fromJson(Map<String, Object?> json) {
    final tokenModifiersJson = json['tokenModifiers'];
    final tokenModifiers = (tokenModifiersJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    final tokenTypesJson = json['tokenTypes'];
    final tokenTypes = (tokenTypesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return SemanticTokensLegend(
      tokenModifiers: tokenModifiers,
      tokenTypes: tokenTypes,
    );
  }

  /// The token modifiers a server uses.
  final List<String> tokenModifiers;

  /// The token types a server uses.
  final List<String> tokenTypes;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['tokenModifiers'] = tokenModifiers;
    result['tokenTypes'] = tokenTypes;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('tokenModifiers');
      try {
        if (!obj.containsKey('tokenModifiers')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tokenModifiers = obj['tokenModifiers'];
        if (tokenModifiers == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tokenModifiers is! List<Object?> ||
            tokenModifiers.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tokenTypes');
      try {
        if (!obj.containsKey('tokenTypes')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tokenTypes = obj['tokenTypes'];
        if (tokenTypes == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tokenTypes is! List<Object?> ||
            tokenTypes.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensLegend');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensLegend &&
        other.runtimeType == SemanticTokensLegend &&
        listEqual(tokenModifiers, other.tokenModifiers,
            (String a, String b) => a == b) &&
        listEqual(tokenTypes, other.tokenTypes, (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(tokenModifiers),
        lspHashCode(tokenTypes),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensOptions.canParse,
    SemanticTokensOptions.fromJson,
  );

  SemanticTokensOptions({
    this.full,
    required this.legend,
    this.range,
    this.workDoneProgress,
  });
  static SemanticTokensOptions fromJson(Map<String, Object?> json) {
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    final fullJson = json['full'];
    final full = fullJson == null
        ? null
        : (fullJson is bool
            ? Either2<bool, SemanticTokensOptionsFull>.t1(fullJson)
            : (SemanticTokensOptionsFull.canParse(fullJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensOptionsFull>.t2(
                    SemanticTokensOptionsFull.fromJson(
                        fullJson as Map<String, Object?>))
                : (throw '''$fullJson was not one of (bool, SemanticTokensOptionsFull)''')));
    final legendJson = json['legend'];
    final legend =
        SemanticTokensLegend.fromJson(legendJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : (rangeJson is bool
            ? Either2<bool, SemanticTokensOptionsRange>.t1(rangeJson)
            : (SemanticTokensOptionsRange.canParse(
                    rangeJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensOptionsRange>.t2(
                    SemanticTokensOptionsRange.fromJson(
                        rangeJson as Map<String, Object?>))
                : (throw '''$rangeJson was not one of (bool, SemanticTokensOptionsRange)''')));
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SemanticTokensOptions(
      full: full,
      legend: legend,
      range: range,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Server supports providing semantic tokens for a full document.
  final Either2<bool, SemanticTokensOptionsFull>? full;

  /// The legend used by the server
  final SemanticTokensLegend legend;

  /// Server supports providing semantic tokens for a specific range of a
  /// document.
  final Either2<bool, SemanticTokensOptionsRange>? range;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (full != null) {
      result['full'] = full;
    }
    result['legend'] = legend.toJson();
    if (range != null) {
      result['range'] = range;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('full');
      try {
        final full = obj['full'];
        if (full != null &&
            full is! bool &&
            !SemanticTokensOptionsFull.canParse(full, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('legend');
      try {
        if (!obj.containsKey('legend')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final legend = obj['legend'];
        if (legend == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SemanticTokensLegend.canParse(legend, reporter)) {
          reporter.reportError('must be of type SemanticTokensLegend');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        final range = obj['range'];
        if (range != null &&
            range is! bool &&
            !SemanticTokensOptionsRange.canParse(range, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensOptions &&
        other.runtimeType == SemanticTokensOptions &&
        full == other.full &&
        legend == other.legend &&
        range == other.range &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        full,
        legend,
        range,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensOptionsFull implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensOptionsFull.canParse,
    SemanticTokensOptionsFull.fromJson,
  );

  SemanticTokensOptionsFull({
    this.delta,
  });
  static SemanticTokensOptionsFull fromJson(Map<String, Object?> json) {
    final deltaJson = json['delta'];
    final delta = deltaJson as bool?;
    return SemanticTokensOptionsFull(
      delta: delta,
    );
  }

  /// The server supports deltas for full documents.
  final bool? delta;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (delta != null) {
      result['delta'] = delta;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('delta');
      try {
        final delta = obj['delta'];
        if (delta != null && delta is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensOptionsFull');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensOptionsFull &&
        other.runtimeType == SemanticTokensOptionsFull &&
        delta == other.delta;
  }

  @override
  int get hashCode => delta.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensOptionsRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensOptionsRange.canParse,
    SemanticTokensOptionsRange.fromJson,
  );

  static SemanticTokensOptionsRange fromJson(Map<String, Object?> json) {
    return SemanticTokensOptionsRange();
  }

  @override
  Map<String, Object?> toJson() => {};

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensOptionsRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensOptionsRange &&
        other.runtimeType == SemanticTokensOptionsRange;
  }

  @override
  int get hashCode => 42;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensParams.canParse,
    SemanticTokensParams.fromJson,
  );

  SemanticTokensParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static SemanticTokensParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SemanticTokensParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensParams &&
        other.runtimeType == SemanticTokensParams &&
        partialResultToken == other.partialResultToken &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensPartialResult.canParse,
    SemanticTokensPartialResult.fromJson,
  );

  SemanticTokensPartialResult({
    required this.data,
  });
  static SemanticTokensPartialResult fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>).map((item) => item as int).toList();
    return SemanticTokensPartialResult(
      data: data,
    );
  }

  final List<int> data;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('data');
      try {
        if (!obj.containsKey('data')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final data = obj['data'];
        if (data == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (data is! List<Object?> || data.any((item) => item is! int)) {
          reporter.reportError('must be of type List<int>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensPartialResult &&
        other.runtimeType == SemanticTokensPartialResult &&
        listEqual(data, other.data, (int a, int b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(data);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensRangeParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensRangeParams.canParse,
    SemanticTokensRangeParams.fromJson,
  );

  SemanticTokensRangeParams({
    this.partialResultToken,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static SemanticTokensRangeParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SemanticTokensRangeParams(
      partialResultToken: partialResultToken,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The range the semantic tokens are requested for.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensRangeParams &&
        other.runtimeType == SemanticTokensRangeParams &&
        partialResultToken == other.partialResultToken &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensRegistrationOptions
    implements
        SemanticTokensOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensRegistrationOptions.canParse,
    SemanticTokensRegistrationOptions.fromJson,
  );

  SemanticTokensRegistrationOptions({
    this.documentSelector,
    this.full,
    this.id,
    required this.legend,
    this.range,
    this.workDoneProgress,
  });
  static SemanticTokensRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final fullJson = json['full'];
    final full = fullJson == null
        ? null
        : (fullJson is bool
            ? Either2<bool, SemanticTokensOptionsFull>.t1(fullJson)
            : (SemanticTokensOptionsFull.canParse(fullJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensOptionsFull>.t2(
                    SemanticTokensOptionsFull.fromJson(
                        fullJson as Map<String, Object?>))
                : (throw '''$fullJson was not one of (bool, SemanticTokensOptionsFull)''')));
    final idJson = json['id'];
    final id = idJson as String?;
    final legendJson = json['legend'];
    final legend =
        SemanticTokensLegend.fromJson(legendJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : (rangeJson is bool
            ? Either2<bool, SemanticTokensOptionsRange>.t1(rangeJson)
            : (SemanticTokensOptionsRange.canParse(
                    rangeJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensOptionsRange>.t2(
                    SemanticTokensOptionsRange.fromJson(
                        rangeJson as Map<String, Object?>))
                : (throw '''$rangeJson was not one of (bool, SemanticTokensOptionsRange)''')));
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SemanticTokensRegistrationOptions(
      documentSelector: documentSelector,
      full: full,
      id: id,
      legend: legend,
      range: range,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// Server supports providing semantic tokens for a full document.
  @override
  final Either2<bool, SemanticTokensOptionsFull>? full;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// The legend used by the server
  @override
  final SemanticTokensLegend legend;

  /// Server supports providing semantic tokens for a specific range of a
  /// document.
  @override
  final Either2<bool, SemanticTokensOptionsRange>? range;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (full != null) {
      result['full'] = full;
    }
    if (id != null) {
      result['id'] = id;
    }
    result['legend'] = legend.toJson();
    if (range != null) {
      result['range'] = range;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('full');
      try {
        final full = obj['full'];
        if (full != null &&
            full is! bool &&
            !SemanticTokensOptionsFull.canParse(full, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('legend');
      try {
        if (!obj.containsKey('legend')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final legend = obj['legend'];
        if (legend == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SemanticTokensLegend.canParse(legend, reporter)) {
          reporter.reportError('must be of type SemanticTokensLegend');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        final range = obj['range'];
        if (range != null &&
            range is! bool &&
            !SemanticTokensOptionsRange.canParse(range, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensRegistrationOptions &&
        other.runtimeType == SemanticTokensRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        full == other.full &&
        id == other.id &&
        legend == other.legend &&
        range == other.range &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        full,
        id,
        legend,
        range,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensWorkspaceClientCapabilities.canParse,
    SemanticTokensWorkspaceClientCapabilities.fromJson,
  );

  SemanticTokensWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static SemanticTokensWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return SemanticTokensWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// semantic tokens currently shown. It should be used with absolute care and
  /// is useful for situation where a server for example detects a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('refreshSupport');
      try {
        final refreshSupport = obj['refreshSupport'];
        if (refreshSupport != null && refreshSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensWorkspaceClientCapabilities &&
        other.runtimeType == SemanticTokensWorkspaceClientCapabilities &&
        refreshSupport == other.refreshSupport;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines the capabilities provided by a language server.
class ServerCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ServerCapabilities.canParse,
    ServerCapabilities.fromJson,
  );

  ServerCapabilities({
    this.callHierarchyProvider,
    this.codeActionProvider,
    this.codeLensProvider,
    this.colorProvider,
    this.completionProvider,
    this.declarationProvider,
    this.definitionProvider,
    this.diagnosticProvider,
    this.documentFormattingProvider,
    this.documentHighlightProvider,
    this.documentLinkProvider,
    this.documentOnTypeFormattingProvider,
    this.documentRangeFormattingProvider,
    this.documentSymbolProvider,
    this.executeCommandProvider,
    this.experimental,
    this.foldingRangeProvider,
    this.hoverProvider,
    this.implementationProvider,
    this.inlayHintProvider,
    this.inlineValueProvider,
    this.linkedEditingRangeProvider,
    this.monikerProvider,
    this.notebookDocumentSync,
    this.positionEncoding,
    this.referencesProvider,
    this.renameProvider,
    this.selectionRangeProvider,
    this.semanticTokensProvider,
    this.signatureHelpProvider,
    this.textDocumentSync,
    this.typeDefinitionProvider,
    this.typeHierarchyProvider,
    this.workspace,
    this.workspaceSymbolProvider,
  });
  static ServerCapabilities fromJson(Map<String, Object?> json) {
    final callHierarchyProviderJson = json['callHierarchyProvider'];
    final callHierarchyProvider = callHierarchyProviderJson == null
        ? null
        : (callHierarchyProviderJson is bool
            ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t1(
                callHierarchyProviderJson)
            : (CallHierarchyOptions.canParse(
                    callHierarchyProviderJson, nullLspJsonReporter)
                ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t2(
                    CallHierarchyOptions.fromJson(
                        callHierarchyProviderJson as Map<String, Object?>))
                : (CallHierarchyRegistrationOptions.canParse(
                        callHierarchyProviderJson, nullLspJsonReporter)
                    ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t3(
                        CallHierarchyRegistrationOptions.fromJson(
                            callHierarchyProviderJson as Map<String, Object?>))
                    : (throw '''$callHierarchyProviderJson was not one of (bool, CallHierarchyOptions, CallHierarchyRegistrationOptions)'''))));
    final codeActionProviderJson = json['codeActionProvider'];
    final codeActionProvider = codeActionProviderJson == null
        ? null
        : (codeActionProviderJson is bool
            ? Either2<bool, CodeActionOptions>.t1(codeActionProviderJson)
            : (CodeActionOptions.canParse(
                    codeActionProviderJson, nullLspJsonReporter)
                ? Either2<bool, CodeActionOptions>.t2(
                    CodeActionOptions.fromJson(
                        codeActionProviderJson as Map<String, Object?>))
                : (throw '''$codeActionProviderJson was not one of (bool, CodeActionOptions)''')));
    final codeLensProviderJson = json['codeLensProvider'];
    final codeLensProvider = codeLensProviderJson != null
        ? CodeLensOptions.fromJson(codeLensProviderJson as Map<String, Object?>)
        : null;
    final colorProviderJson = json['colorProvider'];
    final colorProvider = colorProviderJson == null
        ? null
        : (colorProviderJson is bool
            ? Either3<bool, DocumentColorOptions,
                DocumentColorRegistrationOptions>.t1(colorProviderJson)
            : (DocumentColorOptions.canParse(colorProviderJson, nullLspJsonReporter)
                ? Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>.t2(
                    DocumentColorOptions.fromJson(
                        colorProviderJson as Map<String, Object?>))
                : (DocumentColorRegistrationOptions.canParse(
                        colorProviderJson, nullLspJsonReporter)
                    ? Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>.t3(
                        DocumentColorRegistrationOptions.fromJson(
                            colorProviderJson as Map<String, Object?>))
                    : (throw '''$colorProviderJson was not one of (bool, DocumentColorOptions, DocumentColorRegistrationOptions)'''))));
    final completionProviderJson = json['completionProvider'];
    final completionProvider = completionProviderJson != null
        ? CompletionOptions.fromJson(
            completionProviderJson as Map<String, Object?>)
        : null;
    final declarationProviderJson = json['declarationProvider'];
    final declarationProvider = declarationProviderJson == null
        ? null
        : (declarationProviderJson is bool
            ? Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>.t1(
                declarationProviderJson)
            : (DeclarationOptions.canParse(
                    declarationProviderJson, nullLspJsonReporter)
                ? Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>.t2(
                    DeclarationOptions.fromJson(
                        declarationProviderJson as Map<String, Object?>))
                : (DeclarationRegistrationOptions.canParse(
                        declarationProviderJson, nullLspJsonReporter)
                    ? Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>.t3(
                        DeclarationRegistrationOptions.fromJson(
                            declarationProviderJson as Map<String, Object?>))
                    : (throw '''$declarationProviderJson was not one of (bool, DeclarationOptions, DeclarationRegistrationOptions)'''))));
    final definitionProviderJson = json['definitionProvider'];
    final definitionProvider = definitionProviderJson == null
        ? null
        : (definitionProviderJson is bool
            ? Either2<bool, DefinitionOptions>.t1(definitionProviderJson)
            : (DefinitionOptions.canParse(
                    definitionProviderJson, nullLspJsonReporter)
                ? Either2<bool, DefinitionOptions>.t2(
                    DefinitionOptions.fromJson(
                        definitionProviderJson as Map<String, Object?>))
                : (throw '''$definitionProviderJson was not one of (bool, DefinitionOptions)''')));
    final diagnosticProviderJson = json['diagnosticProvider'];
    final diagnosticProvider = diagnosticProviderJson == null
        ? null
        : (DiagnosticOptions.canParse(
                diagnosticProviderJson, nullLspJsonReporter)
            ? Either2<DiagnosticOptions, DiagnosticRegistrationOptions>.t1(
                DiagnosticOptions.fromJson(
                    diagnosticProviderJson as Map<String, Object?>))
            : (DiagnosticRegistrationOptions.canParse(
                    diagnosticProviderJson, nullLspJsonReporter)
                ? Either2<DiagnosticOptions, DiagnosticRegistrationOptions>.t2(
                    DiagnosticRegistrationOptions.fromJson(
                        diagnosticProviderJson as Map<String, Object?>))
                : (throw '''$diagnosticProviderJson was not one of (DiagnosticOptions, DiagnosticRegistrationOptions)''')));
    final documentFormattingProviderJson = json['documentFormattingProvider'];
    final documentFormattingProvider = documentFormattingProviderJson == null
        ? null
        : (documentFormattingProviderJson is bool
            ? Either2<bool, DocumentFormattingOptions>.t1(
                documentFormattingProviderJson)
            : (DocumentFormattingOptions.canParse(
                    documentFormattingProviderJson, nullLspJsonReporter)
                ? Either2<bool, DocumentFormattingOptions>.t2(
                    DocumentFormattingOptions.fromJson(
                        documentFormattingProviderJson as Map<String, Object?>))
                : (throw '''$documentFormattingProviderJson was not one of (bool, DocumentFormattingOptions)''')));
    final documentHighlightProviderJson = json['documentHighlightProvider'];
    final documentHighlightProvider = documentHighlightProviderJson == null
        ? null
        : (documentHighlightProviderJson is bool
            ? Either2<bool, DocumentHighlightOptions>.t1(
                documentHighlightProviderJson)
            : (DocumentHighlightOptions.canParse(
                    documentHighlightProviderJson, nullLspJsonReporter)
                ? Either2<bool, DocumentHighlightOptions>.t2(
                    DocumentHighlightOptions.fromJson(
                        documentHighlightProviderJson as Map<String, Object?>))
                : (throw '''$documentHighlightProviderJson was not one of (bool, DocumentHighlightOptions)''')));
    final documentLinkProviderJson = json['documentLinkProvider'];
    final documentLinkProvider = documentLinkProviderJson != null
        ? DocumentLinkOptions.fromJson(
            documentLinkProviderJson as Map<String, Object?>)
        : null;
    final documentOnTypeFormattingProviderJson =
        json['documentOnTypeFormattingProvider'];
    final documentOnTypeFormattingProvider =
        documentOnTypeFormattingProviderJson != null
            ? DocumentOnTypeFormattingOptions.fromJson(
                documentOnTypeFormattingProviderJson as Map<String, Object?>)
            : null;
    final documentRangeFormattingProviderJson =
        json['documentRangeFormattingProvider'];
    final documentRangeFormattingProvider = documentRangeFormattingProviderJson ==
            null
        ? null
        : (documentRangeFormattingProviderJson is bool
            ? Either2<bool, DocumentRangeFormattingOptions>.t1(
                documentRangeFormattingProviderJson)
            : (DocumentRangeFormattingOptions.canParse(
                    documentRangeFormattingProviderJson, nullLspJsonReporter)
                ? Either2<bool, DocumentRangeFormattingOptions>.t2(
                    DocumentRangeFormattingOptions.fromJson(
                        documentRangeFormattingProviderJson
                            as Map<String, Object?>))
                : (throw '''$documentRangeFormattingProviderJson was not one of (bool, DocumentRangeFormattingOptions)''')));
    final documentSymbolProviderJson = json['documentSymbolProvider'];
    final documentSymbolProvider = documentSymbolProviderJson == null
        ? null
        : (documentSymbolProviderJson is bool
            ? Either2<bool, DocumentSymbolOptions>.t1(
                documentSymbolProviderJson)
            : (DocumentSymbolOptions.canParse(
                    documentSymbolProviderJson, nullLspJsonReporter)
                ? Either2<bool, DocumentSymbolOptions>.t2(
                    DocumentSymbolOptions.fromJson(
                        documentSymbolProviderJson as Map<String, Object?>))
                : (throw '''$documentSymbolProviderJson was not one of (bool, DocumentSymbolOptions)''')));
    final executeCommandProviderJson = json['executeCommandProvider'];
    final executeCommandProvider = executeCommandProviderJson != null
        ? ExecuteCommandOptions.fromJson(
            executeCommandProviderJson as Map<String, Object?>)
        : null;
    final experimentalJson = json['experimental'];
    final experimental = experimentalJson;
    final foldingRangeProviderJson = json['foldingRangeProvider'];
    final foldingRangeProvider = foldingRangeProviderJson == null
        ? null
        : (foldingRangeProviderJson is bool
            ? Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>.t1(
                foldingRangeProviderJson)
            : (FoldingRangeOptions.canParse(
                    foldingRangeProviderJson, nullLspJsonReporter)
                ? Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>.t2(
                    FoldingRangeOptions.fromJson(
                        foldingRangeProviderJson as Map<String, Object?>))
                : (FoldingRangeRegistrationOptions.canParse(
                        foldingRangeProviderJson, nullLspJsonReporter)
                    ? Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>.t3(
                        FoldingRangeRegistrationOptions.fromJson(
                            foldingRangeProviderJson as Map<String, Object?>))
                    : (throw '''$foldingRangeProviderJson was not one of (bool, FoldingRangeOptions, FoldingRangeRegistrationOptions)'''))));
    final hoverProviderJson = json['hoverProvider'];
    final hoverProvider = hoverProviderJson == null
        ? null
        : (hoverProviderJson is bool
            ? Either2<bool, HoverOptions>.t1(hoverProviderJson)
            : (HoverOptions.canParse(hoverProviderJson, nullLspJsonReporter)
                ? Either2<bool, HoverOptions>.t2(HoverOptions.fromJson(
                    hoverProviderJson as Map<String, Object?>))
                : (throw '''$hoverProviderJson was not one of (bool, HoverOptions)''')));
    final implementationProviderJson = json['implementationProvider'];
    final implementationProvider = implementationProviderJson == null
        ? null
        : (implementationProviderJson is bool
            ? Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>.t1(
                implementationProviderJson)
            : (ImplementationOptions.canParse(
                    implementationProviderJson, nullLspJsonReporter)
                ? Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>.t2(
                    ImplementationOptions.fromJson(
                        implementationProviderJson as Map<String, Object?>))
                : (ImplementationRegistrationOptions.canParse(
                        implementationProviderJson, nullLspJsonReporter)
                    ? Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>.t3(
                        ImplementationRegistrationOptions.fromJson(
                            implementationProviderJson as Map<String, Object?>))
                    : (throw '''$implementationProviderJson was not one of (bool, ImplementationOptions, ImplementationRegistrationOptions)'''))));
    final inlayHintProviderJson = json['inlayHintProvider'];
    final inlayHintProvider = inlayHintProviderJson == null
        ? null
        : (inlayHintProviderJson is bool
            ? Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>.t1(
                inlayHintProviderJson)
            : (InlayHintOptions.canParse(
                    inlayHintProviderJson, nullLspJsonReporter)
                ? Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>.t2(
                    InlayHintOptions.fromJson(
                        inlayHintProviderJson as Map<String, Object?>))
                : (InlayHintRegistrationOptions.canParse(
                        inlayHintProviderJson, nullLspJsonReporter)
                    ? Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>.t3(
                        InlayHintRegistrationOptions.fromJson(
                            inlayHintProviderJson as Map<String, Object?>))
                    : (throw '''$inlayHintProviderJson was not one of (bool, InlayHintOptions, InlayHintRegistrationOptions)'''))));
    final inlineValueProviderJson = json['inlineValueProvider'];
    final inlineValueProvider = inlineValueProviderJson == null
        ? null
        : (inlineValueProviderJson is bool
            ? Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>.t1(
                inlineValueProviderJson)
            : (InlineValueOptions.canParse(
                    inlineValueProviderJson, nullLspJsonReporter)
                ? Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>.t2(
                    InlineValueOptions.fromJson(
                        inlineValueProviderJson as Map<String, Object?>))
                : (InlineValueRegistrationOptions.canParse(
                        inlineValueProviderJson, nullLspJsonReporter)
                    ? Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>.t3(
                        InlineValueRegistrationOptions.fromJson(
                            inlineValueProviderJson as Map<String, Object?>))
                    : (throw '''$inlineValueProviderJson was not one of (bool, InlineValueOptions, InlineValueRegistrationOptions)'''))));
    final linkedEditingRangeProviderJson = json['linkedEditingRangeProvider'];
    final linkedEditingRangeProvider = linkedEditingRangeProviderJson == null
        ? null
        : (linkedEditingRangeProviderJson is bool
            ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t1(
                linkedEditingRangeProviderJson)
            : (LinkedEditingRangeOptions.canParse(
                    linkedEditingRangeProviderJson, nullLspJsonReporter)
                ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t2(
                    LinkedEditingRangeOptions.fromJson(
                        linkedEditingRangeProviderJson as Map<String, Object?>))
                : (LinkedEditingRangeRegistrationOptions.canParse(
                        linkedEditingRangeProviderJson, nullLspJsonReporter)
                    ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t3(
                        LinkedEditingRangeRegistrationOptions.fromJson(
                            linkedEditingRangeProviderJson as Map<String, Object?>))
                    : (throw '''$linkedEditingRangeProviderJson was not one of (bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions)'''))));
    final monikerProviderJson = json['monikerProvider'];
    final monikerProvider = monikerProviderJson == null
        ? null
        : (monikerProviderJson is bool
            ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t1(
                monikerProviderJson)
            : (MonikerOptions.canParse(monikerProviderJson, nullLspJsonReporter)
                ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t2(
                    MonikerOptions.fromJson(
                        monikerProviderJson as Map<String, Object?>))
                : (MonikerRegistrationOptions.canParse(
                        monikerProviderJson, nullLspJsonReporter)
                    ? Either3<bool, MonikerOptions,
                            MonikerRegistrationOptions>.t3(
                        MonikerRegistrationOptions.fromJson(
                            monikerProviderJson as Map<String, Object?>))
                    : (throw '''$monikerProviderJson was not one of (bool, MonikerOptions, MonikerRegistrationOptions)'''))));
    final notebookDocumentSyncJson = json['notebookDocumentSync'];
    final notebookDocumentSync = notebookDocumentSyncJson == null
        ? null
        : (NotebookDocumentSyncOptions.canParse(notebookDocumentSyncJson, nullLspJsonReporter)
            ? Either2<NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions>.t1(
                NotebookDocumentSyncOptions.fromJson(
                    notebookDocumentSyncJson as Map<String, Object?>))
            : (NotebookDocumentSyncRegistrationOptions.canParse(
                    notebookDocumentSyncJson, nullLspJsonReporter)
                ? Either2<NotebookDocumentSyncOptions,
                        NotebookDocumentSyncRegistrationOptions>.t2(
                    NotebookDocumentSyncRegistrationOptions.fromJson(
                        notebookDocumentSyncJson as Map<String, Object?>))
                : (throw '''$notebookDocumentSyncJson was not one of (NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions)''')));
    final positionEncodingJson = json['positionEncoding'];
    final positionEncoding = positionEncodingJson != null
        ? PositionEncodingKind.fromJson(positionEncodingJson as String)
        : null;
    final referencesProviderJson = json['referencesProvider'];
    final referencesProvider = referencesProviderJson == null
        ? null
        : (referencesProviderJson is bool
            ? Either2<bool, ReferenceOptions>.t1(referencesProviderJson)
            : (ReferenceOptions.canParse(
                    referencesProviderJson, nullLspJsonReporter)
                ? Either2<bool, ReferenceOptions>.t2(ReferenceOptions.fromJson(
                    referencesProviderJson as Map<String, Object?>))
                : (throw '''$referencesProviderJson was not one of (bool, ReferenceOptions)''')));
    final renameProviderJson = json['renameProvider'];
    final renameProvider = renameProviderJson == null
        ? null
        : (renameProviderJson is bool
            ? Either2<bool, RenameOptions>.t1(renameProviderJson)
            : (RenameOptions.canParse(renameProviderJson, nullLspJsonReporter)
                ? Either2<bool, RenameOptions>.t2(RenameOptions.fromJson(
                    renameProviderJson as Map<String, Object?>))
                : (throw '''$renameProviderJson was not one of (bool, RenameOptions)''')));
    final selectionRangeProviderJson = json['selectionRangeProvider'];
    final selectionRangeProvider = selectionRangeProviderJson == null
        ? null
        : (selectionRangeProviderJson is bool
            ? Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>.t1(
                selectionRangeProviderJson)
            : (SelectionRangeOptions.canParse(
                    selectionRangeProviderJson, nullLspJsonReporter)
                ? Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>.t2(
                    SelectionRangeOptions.fromJson(
                        selectionRangeProviderJson as Map<String, Object?>))
                : (SelectionRangeRegistrationOptions.canParse(
                        selectionRangeProviderJson, nullLspJsonReporter)
                    ? Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>.t3(
                        SelectionRangeRegistrationOptions.fromJson(
                            selectionRangeProviderJson as Map<String, Object?>))
                    : (throw '''$selectionRangeProviderJson was not one of (bool, SelectionRangeOptions, SelectionRangeRegistrationOptions)'''))));
    final semanticTokensProviderJson = json['semanticTokensProvider'];
    final semanticTokensProvider = semanticTokensProviderJson == null
        ? null
        : (SemanticTokensOptions.canParse(
                semanticTokensProviderJson, nullLspJsonReporter)
            ? Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>.t1(
                SemanticTokensOptions.fromJson(
                    semanticTokensProviderJson as Map<String, Object?>))
            : (SemanticTokensRegistrationOptions.canParse(
                    semanticTokensProviderJson, nullLspJsonReporter)
                ? Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>.t2(
                    SemanticTokensRegistrationOptions.fromJson(
                        semanticTokensProviderJson as Map<String, Object?>))
                : (throw '''$semanticTokensProviderJson was not one of (SemanticTokensOptions, SemanticTokensRegistrationOptions)''')));
    final signatureHelpProviderJson = json['signatureHelpProvider'];
    final signatureHelpProvider = signatureHelpProviderJson != null
        ? SignatureHelpOptions.fromJson(
            signatureHelpProviderJson as Map<String, Object?>)
        : null;
    final textDocumentSyncJson = json['textDocumentSync'];
    final textDocumentSync = textDocumentSyncJson == null
        ? null
        : (TextDocumentSyncKind.canParse(
                textDocumentSyncJson, nullLspJsonReporter)
            ? Either2<TextDocumentSyncKind, TextDocumentSyncOptions>.t1(
                TextDocumentSyncKind.fromJson(textDocumentSyncJson as int))
            : (TextDocumentSyncOptions.canParse(
                    textDocumentSyncJson, nullLspJsonReporter)
                ? Either2<TextDocumentSyncKind, TextDocumentSyncOptions>.t2(
                    TextDocumentSyncOptions.fromJson(
                        textDocumentSyncJson as Map<String, Object?>))
                : (throw '''$textDocumentSyncJson was not one of (TextDocumentSyncKind, TextDocumentSyncOptions)''')));
    final typeDefinitionProviderJson = json['typeDefinitionProvider'];
    final typeDefinitionProvider = typeDefinitionProviderJson == null
        ? null
        : (typeDefinitionProviderJson is bool
            ? Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>.t1(
                typeDefinitionProviderJson)
            : (TypeDefinitionOptions.canParse(
                    typeDefinitionProviderJson, nullLspJsonReporter)
                ? Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>.t2(
                    TypeDefinitionOptions.fromJson(
                        typeDefinitionProviderJson as Map<String, Object?>))
                : (TypeDefinitionRegistrationOptions.canParse(
                        typeDefinitionProviderJson, nullLspJsonReporter)
                    ? Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>.t3(
                        TypeDefinitionRegistrationOptions.fromJson(
                            typeDefinitionProviderJson as Map<String, Object?>))
                    : (throw '''$typeDefinitionProviderJson was not one of (bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions)'''))));
    final typeHierarchyProviderJson = json['typeHierarchyProvider'];
    final typeHierarchyProvider = typeHierarchyProviderJson == null
        ? null
        : (typeHierarchyProviderJson is bool
            ? Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>.t1(
                typeHierarchyProviderJson)
            : (TypeHierarchyOptions.canParse(
                    typeHierarchyProviderJson, nullLspJsonReporter)
                ? Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>.t2(
                    TypeHierarchyOptions.fromJson(
                        typeHierarchyProviderJson as Map<String, Object?>))
                : (TypeHierarchyRegistrationOptions.canParse(
                        typeHierarchyProviderJson, nullLspJsonReporter)
                    ? Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>.t3(
                        TypeHierarchyRegistrationOptions.fromJson(
                            typeHierarchyProviderJson as Map<String, Object?>))
                    : (throw '''$typeHierarchyProviderJson was not one of (bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions)'''))));
    final workspaceJson = json['workspace'];
    final workspace = workspaceJson != null
        ? ServerCapabilitiesWorkspace.fromJson(
            workspaceJson as Map<String, Object?>)
        : null;
    final workspaceSymbolProviderJson = json['workspaceSymbolProvider'];
    final workspaceSymbolProvider = workspaceSymbolProviderJson == null
        ? null
        : (workspaceSymbolProviderJson is bool
            ? Either2<bool, WorkspaceSymbolOptions>.t1(
                workspaceSymbolProviderJson)
            : (WorkspaceSymbolOptions.canParse(
                    workspaceSymbolProviderJson, nullLspJsonReporter)
                ? Either2<bool, WorkspaceSymbolOptions>.t2(
                    WorkspaceSymbolOptions.fromJson(
                        workspaceSymbolProviderJson as Map<String, Object?>))
                : (throw '''$workspaceSymbolProviderJson was not one of (bool, WorkspaceSymbolOptions)''')));
    return ServerCapabilities(
      callHierarchyProvider: callHierarchyProvider,
      codeActionProvider: codeActionProvider,
      codeLensProvider: codeLensProvider,
      colorProvider: colorProvider,
      completionProvider: completionProvider,
      declarationProvider: declarationProvider,
      definitionProvider: definitionProvider,
      diagnosticProvider: diagnosticProvider,
      documentFormattingProvider: documentFormattingProvider,
      documentHighlightProvider: documentHighlightProvider,
      documentLinkProvider: documentLinkProvider,
      documentOnTypeFormattingProvider: documentOnTypeFormattingProvider,
      documentRangeFormattingProvider: documentRangeFormattingProvider,
      documentSymbolProvider: documentSymbolProvider,
      executeCommandProvider: executeCommandProvider,
      experimental: experimental,
      foldingRangeProvider: foldingRangeProvider,
      hoverProvider: hoverProvider,
      implementationProvider: implementationProvider,
      inlayHintProvider: inlayHintProvider,
      inlineValueProvider: inlineValueProvider,
      linkedEditingRangeProvider: linkedEditingRangeProvider,
      monikerProvider: monikerProvider,
      notebookDocumentSync: notebookDocumentSync,
      positionEncoding: positionEncoding,
      referencesProvider: referencesProvider,
      renameProvider: renameProvider,
      selectionRangeProvider: selectionRangeProvider,
      semanticTokensProvider: semanticTokensProvider,
      signatureHelpProvider: signatureHelpProvider,
      textDocumentSync: textDocumentSync,
      typeDefinitionProvider: typeDefinitionProvider,
      typeHierarchyProvider: typeHierarchyProvider,
      workspace: workspace,
      workspaceSymbolProvider: workspaceSymbolProvider,
    );
  }

  /// The server provides call hierarchy support.
  ///
  /// @since 3.16.0
  final Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>?
      callHierarchyProvider;

  /// The server provides code actions. CodeActionOptions may only be specified
  /// if the client states that it supports `codeActionLiteralSupport` in its
  /// initial `initialize` request.
  final Either2<bool, CodeActionOptions>? codeActionProvider;

  /// The server provides code lens.
  final CodeLensOptions? codeLensProvider;

  /// The server provides color provider support.
  final Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>?
      colorProvider;

  /// The server provides completion support.
  final CompletionOptions? completionProvider;

  /// The server provides Goto Declaration support.
  final Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>?
      declarationProvider;

  /// The server provides goto definition support.
  final Either2<bool, DefinitionOptions>? definitionProvider;

  /// The server has support for pull model diagnostics.
  ///
  /// @since 3.17.0
  final Either2<DiagnosticOptions, DiagnosticRegistrationOptions>?
      diagnosticProvider;

  /// The server provides document formatting.
  final Either2<bool, DocumentFormattingOptions>? documentFormattingProvider;

  /// The server provides document highlight support.
  final Either2<bool, DocumentHighlightOptions>? documentHighlightProvider;

  /// The server provides document link support.
  final DocumentLinkOptions? documentLinkProvider;

  /// The server provides document formatting on typing.
  final DocumentOnTypeFormattingOptions? documentOnTypeFormattingProvider;

  /// The server provides document range formatting.
  final Either2<bool, DocumentRangeFormattingOptions>?
      documentRangeFormattingProvider;

  /// The server provides document symbol support.
  final Either2<bool, DocumentSymbolOptions>? documentSymbolProvider;

  /// The server provides execute command support.
  final ExecuteCommandOptions? executeCommandProvider;

  /// Experimental server capabilities.
  final Object? experimental;

  /// The server provides folding provider support.
  final Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>?
      foldingRangeProvider;

  /// The server provides hover support.
  final Either2<bool, HoverOptions>? hoverProvider;

  /// The server provides Goto Implementation support.
  final Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>?
      implementationProvider;

  /// The server provides inlay hints.
  ///
  /// @since 3.17.0
  final Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>?
      inlayHintProvider;

  /// The server provides inline values.
  ///
  /// @since 3.17.0
  final Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>?
      inlineValueProvider;

  /// The server provides linked editing range support.
  ///
  /// @since 3.16.0
  final Either3<bool, LinkedEditingRangeOptions,
      LinkedEditingRangeRegistrationOptions>? linkedEditingRangeProvider;

  /// The server provides moniker support.
  ///
  /// @since 3.16.0
  final Either3<bool, MonikerOptions, MonikerRegistrationOptions>?
      monikerProvider;

  /// Defines how notebook documents are synced.
  ///
  /// @since 3.17.0
  final Either2<NotebookDocumentSyncOptions,
      NotebookDocumentSyncRegistrationOptions>? notebookDocumentSync;

  /// The position encoding the server picked from the encodings offered by the
  /// client via the client capability `general.positionEncodings`.
  ///
  /// If the client didn't provide any position encodings the only valid value
  /// that a server can return is 'utf-16'.
  ///
  /// If omitted it defaults to 'utf-16'.
  ///
  /// @since 3.17.0
  final PositionEncodingKind? positionEncoding;

  /// The server provides find references support.
  final Either2<bool, ReferenceOptions>? referencesProvider;

  /// The server provides rename support. RenameOptions may only be specified if
  /// the client states that it supports `prepareSupport` in its initial
  /// `initialize` request.
  final Either2<bool, RenameOptions>? renameProvider;

  /// The server provides selection range support.
  final Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>?
      selectionRangeProvider;

  /// The server provides semantic tokens support.
  ///
  /// @since 3.16.0
  final Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>?
      semanticTokensProvider;

  /// The server provides signature help support.
  final SignatureHelpOptions? signatureHelpProvider;

  /// Defines how text documents are synced. Is either a detailed structure
  /// defining each notification or for backwards compatibility the
  /// TextDocumentSyncKind number.
  final Either2<TextDocumentSyncKind, TextDocumentSyncOptions>?
      textDocumentSync;

  /// The server provides Goto Type Definition support.
  final Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>?
      typeDefinitionProvider;

  /// The server provides type hierarchy support.
  ///
  /// @since 3.17.0
  final Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>?
      typeHierarchyProvider;

  /// Workspace specific server capabilities.
  final ServerCapabilitiesWorkspace? workspace;

  /// The server provides workspace symbol support.
  final Either2<bool, WorkspaceSymbolOptions>? workspaceSymbolProvider;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (callHierarchyProvider != null) {
      result['callHierarchyProvider'] = callHierarchyProvider;
    }
    if (codeActionProvider != null) {
      result['codeActionProvider'] = codeActionProvider;
    }
    if (codeLensProvider != null) {
      result['codeLensProvider'] = codeLensProvider?.toJson();
    }
    if (colorProvider != null) {
      result['colorProvider'] = colorProvider;
    }
    if (completionProvider != null) {
      result['completionProvider'] = completionProvider?.toJson();
    }
    if (declarationProvider != null) {
      result['declarationProvider'] = declarationProvider;
    }
    if (definitionProvider != null) {
      result['definitionProvider'] = definitionProvider;
    }
    if (diagnosticProvider != null) {
      result['diagnosticProvider'] = diagnosticProvider;
    }
    if (documentFormattingProvider != null) {
      result['documentFormattingProvider'] = documentFormattingProvider;
    }
    if (documentHighlightProvider != null) {
      result['documentHighlightProvider'] = documentHighlightProvider;
    }
    if (documentLinkProvider != null) {
      result['documentLinkProvider'] = documentLinkProvider?.toJson();
    }
    if (documentOnTypeFormattingProvider != null) {
      result['documentOnTypeFormattingProvider'] =
          documentOnTypeFormattingProvider?.toJson();
    }
    if (documentRangeFormattingProvider != null) {
      result['documentRangeFormattingProvider'] =
          documentRangeFormattingProvider;
    }
    if (documentSymbolProvider != null) {
      result['documentSymbolProvider'] = documentSymbolProvider;
    }
    if (executeCommandProvider != null) {
      result['executeCommandProvider'] = executeCommandProvider?.toJson();
    }
    if (experimental != null) {
      result['experimental'] = experimental;
    }
    if (foldingRangeProvider != null) {
      result['foldingRangeProvider'] = foldingRangeProvider;
    }
    if (hoverProvider != null) {
      result['hoverProvider'] = hoverProvider;
    }
    if (implementationProvider != null) {
      result['implementationProvider'] = implementationProvider;
    }
    if (inlayHintProvider != null) {
      result['inlayHintProvider'] = inlayHintProvider;
    }
    if (inlineValueProvider != null) {
      result['inlineValueProvider'] = inlineValueProvider;
    }
    if (linkedEditingRangeProvider != null) {
      result['linkedEditingRangeProvider'] = linkedEditingRangeProvider;
    }
    if (monikerProvider != null) {
      result['monikerProvider'] = monikerProvider;
    }
    if (notebookDocumentSync != null) {
      result['notebookDocumentSync'] = notebookDocumentSync;
    }
    if (positionEncoding != null) {
      result['positionEncoding'] = positionEncoding?.toJson();
    }
    if (referencesProvider != null) {
      result['referencesProvider'] = referencesProvider;
    }
    if (renameProvider != null) {
      result['renameProvider'] = renameProvider;
    }
    if (selectionRangeProvider != null) {
      result['selectionRangeProvider'] = selectionRangeProvider;
    }
    if (semanticTokensProvider != null) {
      result['semanticTokensProvider'] = semanticTokensProvider;
    }
    if (signatureHelpProvider != null) {
      result['signatureHelpProvider'] = signatureHelpProvider?.toJson();
    }
    if (textDocumentSync != null) {
      result['textDocumentSync'] = textDocumentSync;
    }
    if (typeDefinitionProvider != null) {
      result['typeDefinitionProvider'] = typeDefinitionProvider;
    }
    if (typeHierarchyProvider != null) {
      result['typeHierarchyProvider'] = typeHierarchyProvider;
    }
    if (workspace != null) {
      result['workspace'] = workspace?.toJson();
    }
    if (workspaceSymbolProvider != null) {
      result['workspaceSymbolProvider'] = workspaceSymbolProvider;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('callHierarchyProvider');
      try {
        final callHierarchyProvider = obj['callHierarchyProvider'];
        if (callHierarchyProvider != null &&
            callHierarchyProvider is! bool &&
            !CallHierarchyOptions.canParse(callHierarchyProvider, reporter) &&
            !CallHierarchyRegistrationOptions.canParse(
                callHierarchyProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeActionProvider');
      try {
        final codeActionProvider = obj['codeActionProvider'];
        if (codeActionProvider != null &&
            codeActionProvider is! bool &&
            !CodeActionOptions.canParse(codeActionProvider, reporter)) {
          reporter
              .reportError('must be of type Either2<bool, CodeActionOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeLensProvider');
      try {
        final codeLensProvider = obj['codeLensProvider'];
        if (codeLensProvider != null &&
            !CodeLensOptions.canParse(codeLensProvider, reporter)) {
          reporter.reportError('must be of type CodeLensOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('colorProvider');
      try {
        final colorProvider = obj['colorProvider'];
        if (colorProvider != null &&
            colorProvider is! bool &&
            !DocumentColorOptions.canParse(colorProvider, reporter) &&
            !DocumentColorRegistrationOptions.canParse(
                colorProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completionProvider');
      try {
        final completionProvider = obj['completionProvider'];
        if (completionProvider != null &&
            !CompletionOptions.canParse(completionProvider, reporter)) {
          reporter.reportError('must be of type CompletionOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('declarationProvider');
      try {
        final declarationProvider = obj['declarationProvider'];
        if (declarationProvider != null &&
            declarationProvider is! bool &&
            !DeclarationOptions.canParse(declarationProvider, reporter) &&
            !DeclarationRegistrationOptions.canParse(
                declarationProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('definitionProvider');
      try {
        final definitionProvider = obj['definitionProvider'];
        if (definitionProvider != null &&
            definitionProvider is! bool &&
            !DefinitionOptions.canParse(definitionProvider, reporter)) {
          reporter
              .reportError('must be of type Either2<bool, DefinitionOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('diagnosticProvider');
      try {
        final diagnosticProvider = obj['diagnosticProvider'];
        if (diagnosticProvider != null &&
            !DiagnosticOptions.canParse(diagnosticProvider, reporter) &&
            !DiagnosticRegistrationOptions.canParse(
                diagnosticProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<DiagnosticOptions, DiagnosticRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentFormattingProvider');
      try {
        final documentFormattingProvider = obj['documentFormattingProvider'];
        if (documentFormattingProvider != null &&
            documentFormattingProvider is! bool &&
            !DocumentFormattingOptions.canParse(
                documentFormattingProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentFormattingOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentHighlightProvider');
      try {
        final documentHighlightProvider = obj['documentHighlightProvider'];
        if (documentHighlightProvider != null &&
            documentHighlightProvider is! bool &&
            !DocumentHighlightOptions.canParse(
                documentHighlightProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentHighlightOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentLinkProvider');
      try {
        final documentLinkProvider = obj['documentLinkProvider'];
        if (documentLinkProvider != null &&
            !DocumentLinkOptions.canParse(documentLinkProvider, reporter)) {
          reporter.reportError('must be of type DocumentLinkOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentOnTypeFormattingProvider');
      try {
        final documentOnTypeFormattingProvider =
            obj['documentOnTypeFormattingProvider'];
        if (documentOnTypeFormattingProvider != null &&
            !DocumentOnTypeFormattingOptions.canParse(
                documentOnTypeFormattingProvider, reporter)) {
          reporter
              .reportError('must be of type DocumentOnTypeFormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentRangeFormattingProvider');
      try {
        final documentRangeFormattingProvider =
            obj['documentRangeFormattingProvider'];
        if (documentRangeFormattingProvider != null &&
            documentRangeFormattingProvider is! bool &&
            !DocumentRangeFormattingOptions.canParse(
                documentRangeFormattingProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentRangeFormattingOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSymbolProvider');
      try {
        final documentSymbolProvider = obj['documentSymbolProvider'];
        if (documentSymbolProvider != null &&
            documentSymbolProvider is! bool &&
            !DocumentSymbolOptions.canParse(documentSymbolProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentSymbolOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executeCommandProvider');
      try {
        final executeCommandProvider = obj['executeCommandProvider'];
        if (executeCommandProvider != null &&
            !ExecuteCommandOptions.canParse(executeCommandProvider, reporter)) {
          reporter.reportError('must be of type ExecuteCommandOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRangeProvider');
      try {
        final foldingRangeProvider = obj['foldingRangeProvider'];
        if (foldingRangeProvider != null &&
            foldingRangeProvider is! bool &&
            !FoldingRangeOptions.canParse(foldingRangeProvider, reporter) &&
            !FoldingRangeRegistrationOptions.canParse(
                foldingRangeProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('hoverProvider');
      try {
        final hoverProvider = obj['hoverProvider'];
        if (hoverProvider != null &&
            hoverProvider is! bool &&
            !HoverOptions.canParse(hoverProvider, reporter)) {
          reporter.reportError('must be of type Either2<bool, HoverOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('implementationProvider');
      try {
        final implementationProvider = obj['implementationProvider'];
        if (implementationProvider != null &&
            implementationProvider is! bool &&
            !ImplementationOptions.canParse(implementationProvider, reporter) &&
            !ImplementationRegistrationOptions.canParse(
                implementationProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlayHintProvider');
      try {
        final inlayHintProvider = obj['inlayHintProvider'];
        if (inlayHintProvider != null &&
            inlayHintProvider is! bool &&
            !InlayHintOptions.canParse(inlayHintProvider, reporter) &&
            !InlayHintRegistrationOptions.canParse(
                inlayHintProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlineValueProvider');
      try {
        final inlineValueProvider = obj['inlineValueProvider'];
        if (inlineValueProvider != null &&
            inlineValueProvider is! bool &&
            !InlineValueOptions.canParse(inlineValueProvider, reporter) &&
            !InlineValueRegistrationOptions.canParse(
                inlineValueProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkedEditingRangeProvider');
      try {
        final linkedEditingRangeProvider = obj['linkedEditingRangeProvider'];
        if (linkedEditingRangeProvider != null &&
            linkedEditingRangeProvider is! bool &&
            !LinkedEditingRangeOptions.canParse(
                linkedEditingRangeProvider, reporter) &&
            !LinkedEditingRangeRegistrationOptions.canParse(
                linkedEditingRangeProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('monikerProvider');
      try {
        final monikerProvider = obj['monikerProvider'];
        if (monikerProvider != null &&
            monikerProvider is! bool &&
            !MonikerOptions.canParse(monikerProvider, reporter) &&
            !MonikerRegistrationOptions.canParse(monikerProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, MonikerOptions, MonikerRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookDocumentSync');
      try {
        final notebookDocumentSync = obj['notebookDocumentSync'];
        if (notebookDocumentSync != null &&
            !NotebookDocumentSyncOptions.canParse(
                notebookDocumentSync, reporter) &&
            !NotebookDocumentSyncRegistrationOptions.canParse(
                notebookDocumentSync, reporter)) {
          reporter.reportError(
              'must be of type Either2<NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('positionEncoding');
      try {
        final positionEncoding = obj['positionEncoding'];
        if (positionEncoding != null &&
            !PositionEncodingKind.canParse(positionEncoding, reporter)) {
          reporter.reportError('must be of type PositionEncodingKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('referencesProvider');
      try {
        final referencesProvider = obj['referencesProvider'];
        if (referencesProvider != null &&
            referencesProvider is! bool &&
            !ReferenceOptions.canParse(referencesProvider, reporter)) {
          reporter
              .reportError('must be of type Either2<bool, ReferenceOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('renameProvider');
      try {
        final renameProvider = obj['renameProvider'];
        if (renameProvider != null &&
            renameProvider is! bool &&
            !RenameOptions.canParse(renameProvider, reporter)) {
          reporter.reportError('must be of type Either2<bool, RenameOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRangeProvider');
      try {
        final selectionRangeProvider = obj['selectionRangeProvider'];
        if (selectionRangeProvider != null &&
            selectionRangeProvider is! bool &&
            !SelectionRangeOptions.canParse(selectionRangeProvider, reporter) &&
            !SelectionRangeRegistrationOptions.canParse(
                selectionRangeProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('semanticTokensProvider');
      try {
        final semanticTokensProvider = obj['semanticTokensProvider'];
        if (semanticTokensProvider != null &&
            !SemanticTokensOptions.canParse(semanticTokensProvider, reporter) &&
            !SemanticTokensRegistrationOptions.canParse(
                semanticTokensProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatureHelpProvider');
      try {
        final signatureHelpProvider = obj['signatureHelpProvider'];
        if (signatureHelpProvider != null &&
            !SignatureHelpOptions.canParse(signatureHelpProvider, reporter)) {
          reporter.reportError('must be of type SignatureHelpOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocumentSync');
      try {
        final textDocumentSync = obj['textDocumentSync'];
        if (textDocumentSync != null &&
            !TextDocumentSyncKind.canParse(textDocumentSync, reporter) &&
            !TextDocumentSyncOptions.canParse(textDocumentSync, reporter)) {
          reporter.reportError(
              'must be of type Either2<TextDocumentSyncKind, TextDocumentSyncOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeDefinitionProvider');
      try {
        final typeDefinitionProvider = obj['typeDefinitionProvider'];
        if (typeDefinitionProvider != null &&
            typeDefinitionProvider is! bool &&
            !TypeDefinitionOptions.canParse(typeDefinitionProvider, reporter) &&
            !TypeDefinitionRegistrationOptions.canParse(
                typeDefinitionProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeHierarchyProvider');
      try {
        final typeHierarchyProvider = obj['typeHierarchyProvider'];
        if (typeHierarchyProvider != null &&
            typeHierarchyProvider is! bool &&
            !TypeHierarchyOptions.canParse(typeHierarchyProvider, reporter) &&
            !TypeHierarchyRegistrationOptions.canParse(
                typeHierarchyProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspace');
      try {
        final workspace = obj['workspace'];
        if (workspace != null &&
            !ServerCapabilitiesWorkspace.canParse(workspace, reporter)) {
          reporter.reportError('must be of type ServerCapabilitiesWorkspace');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceSymbolProvider');
      try {
        final workspaceSymbolProvider = obj['workspaceSymbolProvider'];
        if (workspaceSymbolProvider != null &&
            workspaceSymbolProvider is! bool &&
            !WorkspaceSymbolOptions.canParse(
                workspaceSymbolProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, WorkspaceSymbolOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ServerCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ServerCapabilities &&
        other.runtimeType == ServerCapabilities &&
        callHierarchyProvider == other.callHierarchyProvider &&
        codeActionProvider == other.codeActionProvider &&
        codeLensProvider == other.codeLensProvider &&
        colorProvider == other.colorProvider &&
        completionProvider == other.completionProvider &&
        declarationProvider == other.declarationProvider &&
        definitionProvider == other.definitionProvider &&
        diagnosticProvider == other.diagnosticProvider &&
        documentFormattingProvider == other.documentFormattingProvider &&
        documentHighlightProvider == other.documentHighlightProvider &&
        documentLinkProvider == other.documentLinkProvider &&
        documentOnTypeFormattingProvider ==
            other.documentOnTypeFormattingProvider &&
        documentRangeFormattingProvider ==
            other.documentRangeFormattingProvider &&
        documentSymbolProvider == other.documentSymbolProvider &&
        executeCommandProvider == other.executeCommandProvider &&
        experimental == other.experimental &&
        foldingRangeProvider == other.foldingRangeProvider &&
        hoverProvider == other.hoverProvider &&
        implementationProvider == other.implementationProvider &&
        inlayHintProvider == other.inlayHintProvider &&
        inlineValueProvider == other.inlineValueProvider &&
        linkedEditingRangeProvider == other.linkedEditingRangeProvider &&
        monikerProvider == other.monikerProvider &&
        notebookDocumentSync == other.notebookDocumentSync &&
        positionEncoding == other.positionEncoding &&
        referencesProvider == other.referencesProvider &&
        renameProvider == other.renameProvider &&
        selectionRangeProvider == other.selectionRangeProvider &&
        semanticTokensProvider == other.semanticTokensProvider &&
        signatureHelpProvider == other.signatureHelpProvider &&
        textDocumentSync == other.textDocumentSync &&
        typeDefinitionProvider == other.typeDefinitionProvider &&
        typeHierarchyProvider == other.typeHierarchyProvider &&
        workspace == other.workspace &&
        workspaceSymbolProvider == other.workspaceSymbolProvider;
  }

  @override
  int get hashCode => Object.hashAll([
        callHierarchyProvider,
        codeActionProvider,
        codeLensProvider,
        colorProvider,
        completionProvider,
        declarationProvider,
        definitionProvider,
        diagnosticProvider,
        documentFormattingProvider,
        documentHighlightProvider,
        documentLinkProvider,
        documentOnTypeFormattingProvider,
        documentRangeFormattingProvider,
        documentSymbolProvider,
        executeCommandProvider,
        experimental,
        foldingRangeProvider,
        hoverProvider,
        implementationProvider,
        inlayHintProvider,
        inlineValueProvider,
        linkedEditingRangeProvider,
        monikerProvider,
        notebookDocumentSync,
        positionEncoding,
        referencesProvider,
        renameProvider,
        selectionRangeProvider,
        semanticTokensProvider,
        signatureHelpProvider,
        textDocumentSync,
        typeDefinitionProvider,
        typeHierarchyProvider,
        workspace,
        workspaceSymbolProvider,
      ]);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ServerCapabilitiesWorkspace implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ServerCapabilitiesWorkspace.canParse,
    ServerCapabilitiesWorkspace.fromJson,
  );

  ServerCapabilitiesWorkspace({
    this.fileOperations,
    this.workspaceFolders,
  });
  static ServerCapabilitiesWorkspace fromJson(Map<String, Object?> json) {
    final fileOperationsJson = json['fileOperations'];
    final fileOperations = fileOperationsJson != null
        ? FileOperationOptions.fromJson(
            fileOperationsJson as Map<String, Object?>)
        : null;
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = workspaceFoldersJson != null
        ? WorkspaceFoldersServerCapabilities.fromJson(
            workspaceFoldersJson as Map<String, Object?>)
        : null;
    return ServerCapabilitiesWorkspace(
      fileOperations: fileOperations,
      workspaceFolders: workspaceFolders,
    );
  }

  /// The server is interested in notifications/requests for operations on
  /// files.
  ///
  /// @since 3.16.0
  final FileOperationOptions? fileOperations;

  /// The server supports workspace folder.
  ///
  /// @since 3.6.0
  final WorkspaceFoldersServerCapabilities? workspaceFolders;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (fileOperations != null) {
      result['fileOperations'] = fileOperations?.toJson();
    }
    if (workspaceFolders != null) {
      result['workspaceFolders'] = workspaceFolders?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('fileOperations');
      try {
        final fileOperations = obj['fileOperations'];
        if (fileOperations != null &&
            !FileOperationOptions.canParse(fileOperations, reporter)) {
          reporter.reportError('must be of type FileOperationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceFolders');
      try {
        final workspaceFolders = obj['workspaceFolders'];
        if (workspaceFolders != null &&
            !WorkspaceFoldersServerCapabilities.canParse(
                workspaceFolders, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceFoldersServerCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ServerCapabilitiesWorkspace');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ServerCapabilitiesWorkspace &&
        other.runtimeType == ServerCapabilitiesWorkspace &&
        fileOperations == other.fileOperations &&
        workspaceFolders == other.workspaceFolders;
  }

  @override
  int get hashCode => Object.hash(
        fileOperations,
        workspaceFolders,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SetTraceParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SetTraceParams.canParse,
    SetTraceParams.fromJson,
  );

  SetTraceParams({
    required this.value,
  });
  static SetTraceParams fromJson(Map<String, Object?> json) {
    final valueJson = json['value'];
    final value = TraceValues.fromJson(valueJson as String);
    return SetTraceParams(
      value: value,
    );
  }

  final TraceValues value;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final value = obj['value'];
        if (value == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TraceValues.canParse(value, reporter)) {
          reporter.reportError('must be of type TraceValues');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SetTraceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SetTraceParams &&
        other.runtimeType == SetTraceParams &&
        value == other.value;
  }

  @override
  int get hashCode => value.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities for the showDocument request.
///
/// @since 3.16.0
class ShowDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowDocumentClientCapabilities.canParse,
    ShowDocumentClientCapabilities.fromJson,
  );

  ShowDocumentClientCapabilities({
    required this.support,
  });
  static ShowDocumentClientCapabilities fromJson(Map<String, Object?> json) {
    final supportJson = json['support'];
    final support = supportJson as bool;
    return ShowDocumentClientCapabilities(
      support: support,
    );
  }

  /// The client has support for the showDocument request.
  final bool support;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('support');
      try {
        if (!obj.containsKey('support')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final support = obj['support'];
        if (support == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (support is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowDocumentClientCapabilities &&
        other.runtimeType == ShowDocumentClientCapabilities &&
        support == other.support;
  }

  @override
  int get hashCode => support.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Params to show a document.
///
/// @since 3.16.0
class ShowDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowDocumentParams.canParse,
    ShowDocumentParams.fromJson,
  );

  ShowDocumentParams({
    this.external,
    this.selection,
    this.takeFocus,
    required this.uri,
  });
  static ShowDocumentParams fromJson(Map<String, Object?> json) {
    final externalJson = json['external'];
    final external = externalJson as bool?;
    final selectionJson = json['selection'];
    final selection = selectionJson != null
        ? Range.fromJson(selectionJson as Map<String, Object?>)
        : null;
    final takeFocusJson = json['takeFocus'];
    final takeFocus = takeFocusJson as bool?;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return ShowDocumentParams(
      external: external,
      selection: selection,
      takeFocus: takeFocus,
      uri: uri,
    );
  }

  /// Indicates to show the resource in an external program. To show for example
  /// `https://code.visualstudio.com/` in the default WEB browser set `external`
  /// to `true`.
  final bool? external;

  /// An optional selection range if the document is a text document. Clients
  /// might ignore the property if an external program is started or the file is
  /// not a text file.
  final Range? selection;

  /// An optional property to indicate whether the editor showing the document
  /// should take focus or not. Clients might ignore this property if an
  /// external program is started.
  final bool? takeFocus;

  /// The document uri to show.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (external != null) {
      result['external'] = external;
    }
    if (selection != null) {
      result['selection'] = selection?.toJson();
    }
    if (takeFocus != null) {
      result['takeFocus'] = takeFocus;
    }
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('external');
      try {
        final external = obj['external'];
        if (external != null && external is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selection');
      try {
        final selection = obj['selection'];
        if (selection != null && !Range.canParse(selection, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('takeFocus');
      try {
        final takeFocus = obj['takeFocus'];
        if (takeFocus != null && takeFocus is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowDocumentParams &&
        other.runtimeType == ShowDocumentParams &&
        external == other.external &&
        selection == other.selection &&
        takeFocus == other.takeFocus &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        external,
        selection,
        takeFocus,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result of a showDocument request.
///
/// @since 3.16.0
class ShowDocumentResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowDocumentResult.canParse,
    ShowDocumentResult.fromJson,
  );

  ShowDocumentResult({
    required this.success,
  });
  static ShowDocumentResult fromJson(Map<String, Object?> json) {
    final successJson = json['success'];
    final success = successJson as bool;
    return ShowDocumentResult(
      success: success,
    );
  }

  /// A boolean indicating if the show was successful.
  final bool success;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('success');
      try {
        if (!obj.containsKey('success')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final success = obj['success'];
        if (success == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (success is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowDocumentResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowDocumentResult &&
        other.runtimeType == ShowDocumentResult &&
        success == other.success;
  }

  @override
  int get hashCode => success.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a notification message.
class ShowMessageParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageParams.canParse,
    ShowMessageParams.fromJson,
  );

  ShowMessageParams({
    required this.message,
    required this.type,
  });
  static ShowMessageParams fromJson(Map<String, Object?> json) {
    final messageJson = json['message'];
    final message = messageJson as String;
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    return ShowMessageParams(
      message: message,
      type: type,
    );
  }

  /// The actual message.
  final String message;

  /// The message type. See {@link MessageType}
  final MessageType type;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['message'] = message;
    result['type'] = type.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final type = obj['type'];
        if (type == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MessageType.canParse(type, reporter)) {
          reporter.reportError('must be of type MessageType');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowMessageParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowMessageParams &&
        other.runtimeType == ShowMessageParams &&
        message == other.message &&
        type == other.type;
  }

  @override
  int get hashCode => Object.hash(
        message,
        type,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Show message request client capabilities
class ShowMessageRequestClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageRequestClientCapabilities.canParse,
    ShowMessageRequestClientCapabilities.fromJson,
  );

  ShowMessageRequestClientCapabilities({
    this.messageActionItem,
  });
  static ShowMessageRequestClientCapabilities fromJson(
      Map<String, Object?> json) {
    final messageActionItemJson = json['messageActionItem'];
    final messageActionItem = messageActionItemJson != null
        ? ShowMessageRequestClientCapabilitiesMessageActionItem.fromJson(
            messageActionItemJson as Map<String, Object?>)
        : null;
    return ShowMessageRequestClientCapabilities(
      messageActionItem: messageActionItem,
    );
  }

  /// Capabilities specific to the `MessageActionItem` type.
  final ShowMessageRequestClientCapabilitiesMessageActionItem?
      messageActionItem;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (messageActionItem != null) {
      result['messageActionItem'] = messageActionItem?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('messageActionItem');
      try {
        final messageActionItem = obj['messageActionItem'];
        if (messageActionItem != null &&
            !ShowMessageRequestClientCapabilitiesMessageActionItem.canParse(
                messageActionItem, reporter)) {
          reporter.reportError(
              'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type ShowMessageRequestClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowMessageRequestClientCapabilities &&
        other.runtimeType == ShowMessageRequestClientCapabilities &&
        messageActionItem == other.messageActionItem;
  }

  @override
  int get hashCode => messageActionItem.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ShowMessageRequestClientCapabilitiesMessageActionItem
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageRequestClientCapabilitiesMessageActionItem.canParse,
    ShowMessageRequestClientCapabilitiesMessageActionItem.fromJson,
  );

  ShowMessageRequestClientCapabilitiesMessageActionItem({
    this.additionalPropertiesSupport,
  });
  static ShowMessageRequestClientCapabilitiesMessageActionItem fromJson(
      Map<String, Object?> json) {
    final additionalPropertiesSupportJson = json['additionalPropertiesSupport'];
    final additionalPropertiesSupport =
        additionalPropertiesSupportJson as bool?;
    return ShowMessageRequestClientCapabilitiesMessageActionItem(
      additionalPropertiesSupport: additionalPropertiesSupport,
    );
  }

  /// Whether the client supports additional attributes which are preserved and
  /// send back to the server in the request's response.
  final bool? additionalPropertiesSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (additionalPropertiesSupport != null) {
      result['additionalPropertiesSupport'] = additionalPropertiesSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('additionalPropertiesSupport');
      try {
        final additionalPropertiesSupport = obj['additionalPropertiesSupport'];
        if (additionalPropertiesSupport != null &&
            additionalPropertiesSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowMessageRequestClientCapabilitiesMessageActionItem &&
        other.runtimeType ==
            ShowMessageRequestClientCapabilitiesMessageActionItem &&
        additionalPropertiesSupport == other.additionalPropertiesSupport;
  }

  @override
  int get hashCode => additionalPropertiesSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ShowMessageRequestParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageRequestParams.canParse,
    ShowMessageRequestParams.fromJson,
  );

  ShowMessageRequestParams({
    this.actions,
    required this.message,
    required this.type,
  });
  static ShowMessageRequestParams fromJson(Map<String, Object?> json) {
    final actionsJson = json['actions'];
    final actions = (actionsJson as List<Object?>?)
        ?.map(
            (item) => MessageActionItem.fromJson(item as Map<String, Object?>))
        .toList();
    final messageJson = json['message'];
    final message = messageJson as String;
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    return ShowMessageRequestParams(
      actions: actions,
      message: message,
      type: type,
    );
  }

  /// The message action items to present.
  final List<MessageActionItem>? actions;

  /// The actual message.
  final String message;

  /// The message type. See {@link MessageType}
  final MessageType type;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (actions != null) {
      result['actions'] = actions?.map((item) => item.toJson()).toList();
    }
    result['message'] = message;
    result['type'] = type.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('actions');
      try {
        final actions = obj['actions'];
        if (actions != null &&
            (actions is! List<Object?> ||
                actions.any(
                    (item) => !MessageActionItem.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<MessageActionItem>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final type = obj['type'];
        if (type == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MessageType.canParse(type, reporter)) {
          reporter.reportError('must be of type MessageType');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowMessageRequestParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowMessageRequestParams &&
        other.runtimeType == ShowMessageRequestParams &&
        listEqual(actions, other.actions,
            (MessageActionItem a, MessageActionItem b) => a == b) &&
        message == other.message &&
        type == other.type;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(actions),
        message,
        type,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Signature help represents the signature of something callable. There can be
/// multiple signature but only one active and only one active parameter.
class SignatureHelp implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelp.canParse,
    SignatureHelp.fromJson,
  );

  SignatureHelp({
    this.activeParameter,
    this.activeSignature,
    required this.signatures,
  });
  static SignatureHelp fromJson(Map<String, Object?> json) {
    final activeParameterJson = json['activeParameter'];
    final activeParameter = activeParameterJson as int?;
    final activeSignatureJson = json['activeSignature'];
    final activeSignature = activeSignatureJson as int?;
    final signaturesJson = json['signatures'];
    final signatures = (signaturesJson as List<Object?>)
        .map((item) =>
            SignatureInformation.fromJson(item as Map<String, Object?>))
        .toList();
    return SignatureHelp(
      activeParameter: activeParameter,
      activeSignature: activeSignature,
      signatures: signatures,
    );
  }

  /// The active parameter of the active signature. If omitted or the value lies
  /// outside the range of `signatures[activeSignature].parameters` defaults to
  /// 0 if the active signature has parameters. If the active signature has no
  /// parameters it is ignored. In future version of the protocol this property
  /// might become mandatory to better express the active parameter if the
  /// active signature does have any.
  final int? activeParameter;

  /// The active signature. If omitted or the value lies outside the range of
  /// `signatures` the value defaults to zero or is ignored if the
  /// `SignatureHelp` has no signatures.
  ///
  /// Whenever possible implementors should make an active decision about the
  /// active signature and shouldn't rely on a default value.
  ///
  /// In future version of the protocol this property might become mandatory to
  /// better express this.
  final int? activeSignature;

  /// One or more signatures.
  final List<SignatureInformation> signatures;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeParameter != null) {
      result['activeParameter'] = activeParameter;
    }
    if (activeSignature != null) {
      result['activeSignature'] = activeSignature;
    }
    result['signatures'] = signatures.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('activeParameter');
      try {
        final activeParameter = obj['activeParameter'];
        if (activeParameter != null && activeParameter is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('activeSignature');
      try {
        final activeSignature = obj['activeSignature'];
        if (activeSignature != null && activeSignature is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatures');
      try {
        if (!obj.containsKey('signatures')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final signatures = obj['signatures'];
        if (signatures == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (signatures is! List<Object?> ||
            signatures.any(
                (item) => !SignatureInformation.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SignatureInformation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelp');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelp &&
        other.runtimeType == SignatureHelp &&
        activeParameter == other.activeParameter &&
        activeSignature == other.activeSignature &&
        listEqual(signatures, other.signatures,
            (SignatureInformation a, SignatureInformation b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        activeParameter,
        activeSignature,
        lspHashCode(signatures),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client Capabilities for a SignatureHelpRequest.
class SignatureHelpClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpClientCapabilities.canParse,
    SignatureHelpClientCapabilities.fromJson,
  );

  SignatureHelpClientCapabilities({
    this.contextSupport,
    this.dynamicRegistration,
    this.signatureInformation,
  });
  static SignatureHelpClientCapabilities fromJson(Map<String, Object?> json) {
    final contextSupportJson = json['contextSupport'];
    final contextSupport = contextSupportJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final signatureInformationJson = json['signatureInformation'];
    final signatureInformation = signatureInformationJson != null
        ? SignatureHelpClientCapabilitiesSignatureInformation.fromJson(
            signatureInformationJson as Map<String, Object?>)
        : null;
    return SignatureHelpClientCapabilities(
      contextSupport: contextSupport,
      dynamicRegistration: dynamicRegistration,
      signatureInformation: signatureInformation,
    );
  }

  /// The client supports to send additional context information for a
  /// `textDocument/signatureHelp` request. A client that opts into
  /// contextSupport will also support the `retriggerCharacters` on
  /// `SignatureHelpOptions`.
  ///
  /// @since 3.15.0
  final bool? contextSupport;

  /// Whether signature help supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports the following `SignatureInformation` specific
  /// properties.
  final SignatureHelpClientCapabilitiesSignatureInformation?
      signatureInformation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (contextSupport != null) {
      result['contextSupport'] = contextSupport;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (signatureInformation != null) {
      result['signatureInformation'] = signatureInformation?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('contextSupport');
      try {
        final contextSupport = obj['contextSupport'];
        if (contextSupport != null && contextSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatureInformation');
      try {
        final signatureInformation = obj['signatureInformation'];
        if (signatureInformation != null &&
            !SignatureHelpClientCapabilitiesSignatureInformation.canParse(
                signatureInformation, reporter)) {
          reporter.reportError(
              'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpClientCapabilities &&
        other.runtimeType == SignatureHelpClientCapabilities &&
        contextSupport == other.contextSupport &&
        dynamicRegistration == other.dynamicRegistration &&
        signatureInformation == other.signatureInformation;
  }

  @override
  int get hashCode => Object.hash(
        contextSupport,
        dynamicRegistration,
        signatureInformation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpClientCapabilitiesSignatureInformation
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpClientCapabilitiesSignatureInformation.canParse,
    SignatureHelpClientCapabilitiesSignatureInformation.fromJson,
  );

  SignatureHelpClientCapabilitiesSignatureInformation({
    this.activeParameterSupport,
    this.documentationFormat,
    this.parameterInformation,
  });
  static SignatureHelpClientCapabilitiesSignatureInformation fromJson(
      Map<String, Object?> json) {
    final activeParameterSupportJson = json['activeParameterSupport'];
    final activeParameterSupport = activeParameterSupportJson as bool?;
    final documentationFormatJson = json['documentationFormat'];
    final documentationFormat = (documentationFormatJson as List<Object?>?)
        ?.map((item) => MarkupKind.fromJson(item as String))
        .toList();
    final parameterInformationJson = json['parameterInformation'];
    final parameterInformation = parameterInformationJson != null
        ? SignatureInformationParameterInformation.fromJson(
            parameterInformationJson as Map<String, Object?>)
        : null;
    return SignatureHelpClientCapabilitiesSignatureInformation(
      activeParameterSupport: activeParameterSupport,
      documentationFormat: documentationFormat,
      parameterInformation: parameterInformation,
    );
  }

  /// The client supports the `activeParameter` property on
  /// `SignatureInformation` literal.
  ///
  /// @since 3.16.0
  final bool? activeParameterSupport;

  /// Client supports the following content formats for the documentation
  /// property. The order describes the preferred format of the client.
  final List<MarkupKind>? documentationFormat;

  /// Client capabilities specific to parameter information.
  final SignatureInformationParameterInformation? parameterInformation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeParameterSupport != null) {
      result['activeParameterSupport'] = activeParameterSupport;
    }
    if (documentationFormat != null) {
      result['documentationFormat'] =
          documentationFormat?.map((item) => item.toJson()).toList();
    }
    if (parameterInformation != null) {
      result['parameterInformation'] = parameterInformation?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('activeParameterSupport');
      try {
        final activeParameterSupport = obj['activeParameterSupport'];
        if (activeParameterSupport != null && activeParameterSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentationFormat');
      try {
        final documentationFormat = obj['documentationFormat'];
        if (documentationFormat != null &&
            (documentationFormat is! List<Object?> ||
                documentationFormat
                    .any((item) => !MarkupKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<MarkupKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('parameterInformation');
      try {
        final parameterInformation = obj['parameterInformation'];
        if (parameterInformation != null &&
            !SignatureInformationParameterInformation.canParse(
                parameterInformation, reporter)) {
          reporter.reportError(
              'must be of type SignatureInformationParameterInformation');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpClientCapabilitiesSignatureInformation &&
        other.runtimeType ==
            SignatureHelpClientCapabilitiesSignatureInformation &&
        activeParameterSupport == other.activeParameterSupport &&
        listEqual(documentationFormat, other.documentationFormat,
            (MarkupKind a, MarkupKind b) => a == b) &&
        parameterInformation == other.parameterInformation;
  }

  @override
  int get hashCode => Object.hash(
        activeParameterSupport,
        lspHashCode(documentationFormat),
        parameterInformation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Additional information about the context in which a signature help request
/// was triggered.
///
/// @since 3.15.0
class SignatureHelpContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpContext.canParse,
    SignatureHelpContext.fromJson,
  );

  SignatureHelpContext({
    this.activeSignatureHelp,
    required this.isRetrigger,
    this.triggerCharacter,
    required this.triggerKind,
  });
  static SignatureHelpContext fromJson(Map<String, Object?> json) {
    final activeSignatureHelpJson = json['activeSignatureHelp'];
    final activeSignatureHelp = activeSignatureHelpJson != null
        ? SignatureHelp.fromJson(
            activeSignatureHelpJson as Map<String, Object?>)
        : null;
    final isRetriggerJson = json['isRetrigger'];
    final isRetrigger = isRetriggerJson as bool;
    final triggerCharacterJson = json['triggerCharacter'];
    final triggerCharacter = triggerCharacterJson as String?;
    final triggerKindJson = json['triggerKind'];
    final triggerKind =
        SignatureHelpTriggerKind.fromJson(triggerKindJson as int);
    return SignatureHelpContext(
      activeSignatureHelp: activeSignatureHelp,
      isRetrigger: isRetrigger,
      triggerCharacter: triggerCharacter,
      triggerKind: triggerKind,
    );
  }

  /// The currently active `SignatureHelp`.
  ///
  /// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field
  /// updated based on the user navigating through available signatures.
  final SignatureHelp? activeSignatureHelp;

  /// `true` if signature help was already showing when it was triggered.
  ///
  /// Retriggers occurs when the signature help is already active and can be
  /// caused by actions such as typing a trigger character, a cursor move, or
  /// document content changes.
  final bool isRetrigger;

  /// Character that caused signature help to be triggered.
  ///
  /// This is undefined when `triggerKind !==
  /// SignatureHelpTriggerKind.TriggerCharacter`
  final String? triggerCharacter;

  /// Action that caused signature help to be triggered.
  final SignatureHelpTriggerKind triggerKind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeSignatureHelp != null) {
      result['activeSignatureHelp'] = activeSignatureHelp?.toJson();
    }
    result['isRetrigger'] = isRetrigger;
    if (triggerCharacter != null) {
      result['triggerCharacter'] = triggerCharacter;
    }
    result['triggerKind'] = triggerKind.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('activeSignatureHelp');
      try {
        final activeSignatureHelp = obj['activeSignatureHelp'];
        if (activeSignatureHelp != null &&
            !SignatureHelp.canParse(activeSignatureHelp, reporter)) {
          reporter.reportError('must be of type SignatureHelp');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('isRetrigger');
      try {
        if (!obj.containsKey('isRetrigger')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final isRetrigger = obj['isRetrigger'];
        if (isRetrigger == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (isRetrigger is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacter');
      try {
        final triggerCharacter = obj['triggerCharacter'];
        if (triggerCharacter != null && triggerCharacter is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerKind');
      try {
        if (!obj.containsKey('triggerKind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final triggerKind = obj['triggerKind'];
        if (triggerKind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SignatureHelpTriggerKind.canParse(triggerKind, reporter)) {
          reporter.reportError('must be of type SignatureHelpTriggerKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpContext &&
        other.runtimeType == SignatureHelpContext &&
        activeSignatureHelp == other.activeSignatureHelp &&
        isRetrigger == other.isRetrigger &&
        triggerCharacter == other.triggerCharacter &&
        triggerKind == other.triggerKind;
  }

  @override
  int get hashCode => Object.hash(
        activeSignatureHelp,
        isRetrigger,
        triggerCharacter,
        triggerKind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Server Capabilities for a SignatureHelpRequest.
class SignatureHelpOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpOptions.canParse,
    SignatureHelpOptions.fromJson,
  );

  SignatureHelpOptions({
    this.retriggerCharacters,
    this.triggerCharacters,
    this.workDoneProgress,
  });
  static SignatureHelpOptions fromJson(Map<String, Object?> json) {
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    final retriggerCharactersJson = json['retriggerCharacters'];
    final retriggerCharacters = (retriggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SignatureHelpOptions(
      retriggerCharacters: retriggerCharacters,
      triggerCharacters: triggerCharacters,
      workDoneProgress: workDoneProgress,
    );
  }

  /// List of characters that re-trigger signature help.
  ///
  /// These trigger characters are only active when signature help is already
  /// showing. All trigger characters are also counted as re-trigger characters.
  ///
  /// @since 3.15.0
  final List<String>? retriggerCharacters;

  /// List of characters that trigger signature help automatically.
  final List<String>? triggerCharacters;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (retriggerCharacters != null) {
      result['retriggerCharacters'] = retriggerCharacters;
    }
    if (triggerCharacters != null) {
      result['triggerCharacters'] = triggerCharacters;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('retriggerCharacters');
      try {
        final retriggerCharacters = obj['retriggerCharacters'];
        if (retriggerCharacters != null &&
            (retriggerCharacters is! List<Object?> ||
                retriggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacters');
      try {
        final triggerCharacters = obj['triggerCharacters'];
        if (triggerCharacters != null &&
            (triggerCharacters is! List<Object?> ||
                triggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpOptions &&
        other.runtimeType == SignatureHelpOptions &&
        listEqual(retriggerCharacters, other.retriggerCharacters,
            (String a, String b) => a == b) &&
        listEqual(triggerCharacters, other.triggerCharacters,
            (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(retriggerCharacters),
        lspHashCode(triggerCharacters),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a SignatureHelpRequest.
class SignatureHelpParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpParams.canParse,
    SignatureHelpParams.fromJson,
  );

  SignatureHelpParams({
    this.context,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static SignatureHelpParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context = contextJson != null
        ? SignatureHelpContext.fromJson(contextJson as Map<String, Object?>)
        : null;
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SignatureHelpParams(
      context: context,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The signature help context. This is only available if the client specifies
  /// to send this using the client capability
  /// `textDocument.signatureHelp.contextSupport === true`
  ///
  /// @since 3.15.0
  final SignatureHelpContext? context;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (context != null) {
      result['context'] = context?.toJson();
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('context');
      try {
        final context = obj['context'];
        if (context != null &&
            !SignatureHelpContext.canParse(context, reporter)) {
          reporter.reportError('must be of type SignatureHelpContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpParams &&
        other.runtimeType == SignatureHelpParams &&
        context == other.context &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        context,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a SignatureHelpRequest.
class SignatureHelpRegistrationOptions
    implements
        SignatureHelpOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpRegistrationOptions.canParse,
    SignatureHelpRegistrationOptions.fromJson,
  );

  SignatureHelpRegistrationOptions({
    this.documentSelector,
    this.retriggerCharacters,
    this.triggerCharacters,
    this.workDoneProgress,
  });
  static SignatureHelpRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final retriggerCharactersJson = json['retriggerCharacters'];
    final retriggerCharacters = (retriggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SignatureHelpRegistrationOptions(
      documentSelector: documentSelector,
      retriggerCharacters: retriggerCharacters,
      triggerCharacters: triggerCharacters,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// List of characters that re-trigger signature help.
  ///
  /// These trigger characters are only active when signature help is already
  /// showing. All trigger characters are also counted as re-trigger characters.
  ///
  /// @since 3.15.0
  @override
  final List<String>? retriggerCharacters;

  /// List of characters that trigger signature help automatically.
  @override
  final List<String>? triggerCharacters;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (retriggerCharacters != null) {
      result['retriggerCharacters'] = retriggerCharacters;
    }
    if (triggerCharacters != null) {
      result['triggerCharacters'] = triggerCharacters;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('retriggerCharacters');
      try {
        final retriggerCharacters = obj['retriggerCharacters'];
        if (retriggerCharacters != null &&
            (retriggerCharacters is! List<Object?> ||
                retriggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacters');
      try {
        final triggerCharacters = obj['triggerCharacters'];
        if (triggerCharacters != null &&
            (triggerCharacters is! List<Object?> ||
                triggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpRegistrationOptions &&
        other.runtimeType == SignatureHelpRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        listEqual(retriggerCharacters, other.retriggerCharacters,
            (String a, String b) => a == b) &&
        listEqual(triggerCharacters, other.triggerCharacters,
            (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        lspHashCode(retriggerCharacters),
        lspHashCode(triggerCharacters),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// How a signature help was triggered.
///
/// @since 3.15.0
class SignatureHelpTriggerKind implements ToJsonable {
  const SignatureHelpTriggerKind(this._value);
  const SignatureHelpTriggerKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Signature help was triggered by the cursor moving or by the document
  /// content changing.
  static const ContentChange = SignatureHelpTriggerKind(3);

  /// Signature help was invoked manually by the user or by a command.
  static const Invoked = SignatureHelpTriggerKind(1);

  /// Signature help was triggered by a trigger character.
  static const TriggerCharacter = SignatureHelpTriggerKind(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SignatureHelpTriggerKind && other._value == _value;
}

/// Represents the signature of something callable. A signature can have a
/// label, like a function-name, a doc-comment, and a set of parameters.
class SignatureInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureInformation.canParse,
    SignatureInformation.fromJson,
  );

  SignatureInformation({
    this.activeParameter,
    this.documentation,
    required this.label,
    this.parameters,
  });
  static SignatureInformation fromJson(Map<String, Object?> json) {
    final activeParameterJson = json['activeParameter'];
    final activeParameter = activeParameterJson as int?;
    final documentationJson = json['documentation'];
    final documentation = documentationJson == null
        ? null
        : (MarkupContent.canParse(documentationJson, nullLspJsonReporter)
            ? Either2<MarkupContent, String>.t1(MarkupContent.fromJson(
                documentationJson as Map<String, Object?>))
            : (documentationJson is String
                ? Either2<MarkupContent, String>.t2(documentationJson)
                : (throw '''$documentationJson was not one of (MarkupContent, String)''')));
    final labelJson = json['label'];
    final label = labelJson as String;
    final parametersJson = json['parameters'];
    final parameters = (parametersJson as List<Object?>?)
        ?.map((item) =>
            ParameterInformation.fromJson(item as Map<String, Object?>))
        .toList();
    return SignatureInformation(
      activeParameter: activeParameter,
      documentation: documentation,
      label: label,
      parameters: parameters,
    );
  }

  /// The index of the active parameter.
  ///
  /// If provided, this is used in place of `SignatureHelp.activeParameter`.
  ///
  /// @since 3.16.0
  final int? activeParameter;

  /// The human-readable doc-comment of this signature. Will be shown in the UI
  /// but can be omitted.
  final Either2<MarkupContent, String>? documentation;

  /// The label of this signature. Will be shown in the UI.
  final String label;

  /// The parameters of this signature.
  final List<ParameterInformation>? parameters;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeParameter != null) {
      result['activeParameter'] = activeParameter;
    }
    if (documentation != null) {
      result['documentation'] = documentation;
    }
    result['label'] = label;
    if (parameters != null) {
      result['parameters'] = parameters?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('activeParameter');
      try {
        final activeParameter = obj['activeParameter'];
        if (activeParameter != null && activeParameter is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentation');
      try {
        final documentation = obj['documentation'];
        if (documentation != null &&
            !MarkupContent.canParse(documentation, reporter) &&
            documentation is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final label = obj['label'];
        if (label == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('parameters');
      try {
        final parameters = obj['parameters'];
        if (parameters != null &&
            (parameters is! List<Object?> ||
                parameters.any((item) =>
                    !ParameterInformation.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<ParameterInformation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureInformation &&
        other.runtimeType == SignatureInformation &&
        activeParameter == other.activeParameter &&
        documentation == other.documentation &&
        label == other.label &&
        listEqual(parameters, other.parameters,
            (ParameterInformation a, ParameterInformation b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        activeParameter,
        documentation,
        label,
        lspHashCode(parameters),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureInformationParameterInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureInformationParameterInformation.canParse,
    SignatureInformationParameterInformation.fromJson,
  );

  SignatureInformationParameterInformation({
    this.labelOffsetSupport,
  });
  static SignatureInformationParameterInformation fromJson(
      Map<String, Object?> json) {
    final labelOffsetSupportJson = json['labelOffsetSupport'];
    final labelOffsetSupport = labelOffsetSupportJson as bool?;
    return SignatureInformationParameterInformation(
      labelOffsetSupport: labelOffsetSupport,
    );
  }

  /// The client supports processing label offsets instead of a simple label
  /// string.
  ///
  /// @since 3.14.0
  final bool? labelOffsetSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (labelOffsetSupport != null) {
      result['labelOffsetSupport'] = labelOffsetSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('labelOffsetSupport');
      try {
        final labelOffsetSupport = obj['labelOffsetSupport'];
        if (labelOffsetSupport != null && labelOffsetSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SignatureInformationParameterInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureInformationParameterInformation &&
        other.runtimeType == SignatureInformationParameterInformation &&
        labelOffsetSupport == other.labelOffsetSupport;
  }

  @override
  int get hashCode => labelOffsetSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Static registration options to be returned in the initialize request.
class StaticRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    StaticRegistrationOptions.canParse,
    StaticRegistrationOptions.fromJson,
  );

  StaticRegistrationOptions({
    this.id,
  });
  static StaticRegistrationOptions fromJson(Map<String, Object?> json) {
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (DiagnosticRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    if (NotebookDocumentSyncRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return NotebookDocumentSyncRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    final idJson = json['id'];
    final id = idJson as String?;
    return StaticRegistrationOptions(
      id: id,
    );
  }

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  final String? id;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (id != null) {
      result['id'] = id;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type StaticRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is StaticRegistrationOptions &&
        other.runtimeType == StaticRegistrationOptions &&
        id == other.id;
  }

  @override
  int get hashCode => id.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents information about programming constructs like variables, classes,
/// interfaces etc.
class SymbolInformation implements BaseSymbolInformation, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SymbolInformation.canParse,
    SymbolInformation.fromJson,
  );

  SymbolInformation({
    this.containerName,
    this.deprecated,
    required this.kind,
    required this.location,
    required this.name,
    this.tags,
  });
  static SymbolInformation fromJson(Map<String, Object?> json) {
    final containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    final deprecatedJson = json['deprecated'];
    final deprecated = deprecatedJson as bool?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final locationJson = json['location'];
    final location = Location.fromJson(locationJson as Map<String, Object?>);
    final nameJson = json['name'];
    final name = nameJson as String;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return SymbolInformation(
      containerName: containerName,
      deprecated: deprecated,
      kind: kind,
      location: location,
      name: name,
      tags: tags,
    );
  }

  /// The name of the symbol containing this symbol. This information is for
  /// user interface purposes (e.g. to render a qualifier in the user interface
  /// if necessary). It can't be used to re-infer a hierarchy for the document
  /// symbols.
  @override
  final String? containerName;

  /// Indicates if this symbol is deprecated.
  ///
  /// @deprecated Use tags instead
  final bool? deprecated;

  /// The kind of this symbol.
  @override
  final SymbolKind kind;

  /// The location of this symbol. The location's range is used by a tool to
  /// reveal the location in the editor. If the symbol is selected in the tool
  /// the range's start information is used to position the cursor. So the range
  /// usually spans more than the actual symbol's name and does normally include
  /// things like visibility modifiers.
  ///
  /// The range doesn't have to denote a node range in the sense of an abstract
  /// syntax tree. It can therefore not be used to re-construct a hierarchy of
  /// the symbols.
  final Location location;

  /// The name of this symbol.
  @override
  final String name;

  /// Tags for this symbol.
  ///
  /// @since 3.16.0
  @override
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (containerName != null) {
      result['containerName'] = containerName;
    }
    if (deprecated != null) {
      result['deprecated'] = deprecated;
    }
    result['kind'] = kind.toJson();
    result['location'] = location.toJson();
    result['name'] = name;
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('containerName');
      try {
        final containerName = obj['containerName'];
        if (containerName != null && containerName is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deprecated');
      try {
        final deprecated = obj['deprecated'];
        if (deprecated != null && deprecated is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('location');
      try {
        if (!obj.containsKey('location')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final location = obj['location'];
        if (location == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Location.canParse(location, reporter)) {
          reporter.reportError('must be of type Location');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SymbolInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SymbolInformation &&
        other.runtimeType == SymbolInformation &&
        containerName == other.containerName &&
        deprecated == other.deprecated &&
        kind == other.kind &&
        location == other.location &&
        name == other.name &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        containerName,
        deprecated,
        kind,
        location,
        name,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A symbol kind.
class SymbolKind implements ToJsonable {
  const SymbolKind(this._value);
  const SymbolKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  static const Array = SymbolKind(18);
  static const Boolean = SymbolKind(17);
  static const Class = SymbolKind(5);
  static const Constant = SymbolKind(14);
  static const Constructor = SymbolKind(9);
  static const Enum = SymbolKind(10);
  static const EnumMember = SymbolKind(22);
  static const Event = SymbolKind(24);
  static const Field = SymbolKind(8);
  static const File = SymbolKind(1);
  static const Function = SymbolKind(12);
  static const Interface = SymbolKind(11);
  static const Key = SymbolKind(20);
  static const Method = SymbolKind(6);
  static const Module = SymbolKind(2);
  static const Namespace = SymbolKind(3);
  static const Null = SymbolKind(21);
  static const Number = SymbolKind(16);
  static const Obj = SymbolKind(19);
  static const Operator = SymbolKind(25);
  static const Package = SymbolKind(4);
  static const Property = SymbolKind(7);
  static const Str = SymbolKind(15);
  static const Struct = SymbolKind(23);
  static const TypeParameter = SymbolKind(26);
  static const Variable = SymbolKind(13);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SymbolKind && other._value == _value;
}

/// Symbol tags are extra annotations that tweak the rendering of a symbol.
///
/// @since 3.16
class SymbolTag implements ToJsonable {
  const SymbolTag(this._value);
  const SymbolTag.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Render a symbol as obsolete, usually using a strike-out.
  static const Deprecated = SymbolTag(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SymbolTag && other._value == _value;
}

/// Describe options to be used when registered for text document change events.
class TextDocumentChangeRegistrationOptions
    implements TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentChangeRegistrationOptions.canParse,
    TextDocumentChangeRegistrationOptions.fromJson,
  );

  TextDocumentChangeRegistrationOptions({
    this.documentSelector,
    required this.syncKind,
  });
  static TextDocumentChangeRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final syncKindJson = json['syncKind'];
    final syncKind = TextDocumentSyncKind.fromJson(syncKindJson as int);
    return TextDocumentChangeRegistrationOptions(
      documentSelector: documentSelector,
      syncKind: syncKind,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// How documents are synced to the server.
  final TextDocumentSyncKind syncKind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    result['syncKind'] = syncKind.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('syncKind');
      try {
        if (!obj.containsKey('syncKind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final syncKind = obj['syncKind'];
        if (syncKind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentSyncKind.canParse(syncKind, reporter)) {
          reporter.reportError('must be of type TextDocumentSyncKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type TextDocumentChangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentChangeRegistrationOptions &&
        other.runtimeType == TextDocumentChangeRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        syncKind == other.syncKind;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        syncKind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Text document specific client capabilities.
class TextDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentClientCapabilities.canParse,
    TextDocumentClientCapabilities.fromJson,
  );

  TextDocumentClientCapabilities({
    this.callHierarchy,
    this.codeAction,
    this.codeLens,
    this.colorProvider,
    this.completion,
    this.declaration,
    this.definition,
    this.diagnostic,
    this.documentHighlight,
    this.documentLink,
    this.documentSymbol,
    this.foldingRange,
    this.formatting,
    this.hover,
    this.implementation,
    this.inlayHint,
    this.inlineValue,
    this.linkedEditingRange,
    this.moniker,
    this.onTypeFormatting,
    this.publishDiagnostics,
    this.rangeFormatting,
    this.references,
    this.rename,
    this.selectionRange,
    this.semanticTokens,
    this.signatureHelp,
    this.synchronization,
    this.typeDefinition,
    this.typeHierarchy,
  });
  static TextDocumentClientCapabilities fromJson(Map<String, Object?> json) {
    final callHierarchyJson = json['callHierarchy'];
    final callHierarchy = callHierarchyJson != null
        ? CallHierarchyClientCapabilities.fromJson(
            callHierarchyJson as Map<String, Object?>)
        : null;
    final codeActionJson = json['codeAction'];
    final codeAction = codeActionJson != null
        ? CodeActionClientCapabilities.fromJson(
            codeActionJson as Map<String, Object?>)
        : null;
    final codeLensJson = json['codeLens'];
    final codeLens = codeLensJson != null
        ? CodeLensClientCapabilities.fromJson(
            codeLensJson as Map<String, Object?>)
        : null;
    final colorProviderJson = json['colorProvider'];
    final colorProvider = colorProviderJson != null
        ? DocumentColorClientCapabilities.fromJson(
            colorProviderJson as Map<String, Object?>)
        : null;
    final completionJson = json['completion'];
    final completion = completionJson != null
        ? CompletionClientCapabilities.fromJson(
            completionJson as Map<String, Object?>)
        : null;
    final declarationJson = json['declaration'];
    final declaration = declarationJson != null
        ? DeclarationClientCapabilities.fromJson(
            declarationJson as Map<String, Object?>)
        : null;
    final definitionJson = json['definition'];
    final definition = definitionJson != null
        ? DefinitionClientCapabilities.fromJson(
            definitionJson as Map<String, Object?>)
        : null;
    final diagnosticJson = json['diagnostic'];
    final diagnostic = diagnosticJson != null
        ? DiagnosticClientCapabilities.fromJson(
            diagnosticJson as Map<String, Object?>)
        : null;
    final documentHighlightJson = json['documentHighlight'];
    final documentHighlight = documentHighlightJson != null
        ? DocumentHighlightClientCapabilities.fromJson(
            documentHighlightJson as Map<String, Object?>)
        : null;
    final documentLinkJson = json['documentLink'];
    final documentLink = documentLinkJson != null
        ? DocumentLinkClientCapabilities.fromJson(
            documentLinkJson as Map<String, Object?>)
        : null;
    final documentSymbolJson = json['documentSymbol'];
    final documentSymbol = documentSymbolJson != null
        ? DocumentSymbolClientCapabilities.fromJson(
            documentSymbolJson as Map<String, Object?>)
        : null;
    final foldingRangeJson = json['foldingRange'];
    final foldingRange = foldingRangeJson != null
        ? FoldingRangeClientCapabilities.fromJson(
            foldingRangeJson as Map<String, Object?>)
        : null;
    final formattingJson = json['formatting'];
    final formatting = formattingJson != null
        ? DocumentFormattingClientCapabilities.fromJson(
            formattingJson as Map<String, Object?>)
        : null;
    final hoverJson = json['hover'];
    final hover = hoverJson != null
        ? HoverClientCapabilities.fromJson(hoverJson as Map<String, Object?>)
        : null;
    final implementationJson = json['implementation'];
    final implementation = implementationJson != null
        ? ImplementationClientCapabilities.fromJson(
            implementationJson as Map<String, Object?>)
        : null;
    final inlayHintJson = json['inlayHint'];
    final inlayHint = inlayHintJson != null
        ? InlayHintClientCapabilities.fromJson(
            inlayHintJson as Map<String, Object?>)
        : null;
    final inlineValueJson = json['inlineValue'];
    final inlineValue = inlineValueJson != null
        ? InlineValueClientCapabilities.fromJson(
            inlineValueJson as Map<String, Object?>)
        : null;
    final linkedEditingRangeJson = json['linkedEditingRange'];
    final linkedEditingRange = linkedEditingRangeJson != null
        ? LinkedEditingRangeClientCapabilities.fromJson(
            linkedEditingRangeJson as Map<String, Object?>)
        : null;
    final monikerJson = json['moniker'];
    final moniker = monikerJson != null
        ? MonikerClientCapabilities.fromJson(
            monikerJson as Map<String, Object?>)
        : null;
    final onTypeFormattingJson = json['onTypeFormatting'];
    final onTypeFormatting = onTypeFormattingJson != null
        ? DocumentOnTypeFormattingClientCapabilities.fromJson(
            onTypeFormattingJson as Map<String, Object?>)
        : null;
    final publishDiagnosticsJson = json['publishDiagnostics'];
    final publishDiagnostics = publishDiagnosticsJson != null
        ? PublishDiagnosticsClientCapabilities.fromJson(
            publishDiagnosticsJson as Map<String, Object?>)
        : null;
    final rangeFormattingJson = json['rangeFormatting'];
    final rangeFormatting = rangeFormattingJson != null
        ? DocumentRangeFormattingClientCapabilities.fromJson(
            rangeFormattingJson as Map<String, Object?>)
        : null;
    final referencesJson = json['references'];
    final references = referencesJson != null
        ? ReferenceClientCapabilities.fromJson(
            referencesJson as Map<String, Object?>)
        : null;
    final renameJson = json['rename'];
    final rename = renameJson != null
        ? RenameClientCapabilities.fromJson(renameJson as Map<String, Object?>)
        : null;
    final selectionRangeJson = json['selectionRange'];
    final selectionRange = selectionRangeJson != null
        ? SelectionRangeClientCapabilities.fromJson(
            selectionRangeJson as Map<String, Object?>)
        : null;
    final semanticTokensJson = json['semanticTokens'];
    final semanticTokens = semanticTokensJson != null
        ? SemanticTokensClientCapabilities.fromJson(
            semanticTokensJson as Map<String, Object?>)
        : null;
    final signatureHelpJson = json['signatureHelp'];
    final signatureHelp = signatureHelpJson != null
        ? SignatureHelpClientCapabilities.fromJson(
            signatureHelpJson as Map<String, Object?>)
        : null;
    final synchronizationJson = json['synchronization'];
    final synchronization = synchronizationJson != null
        ? TextDocumentSyncClientCapabilities.fromJson(
            synchronizationJson as Map<String, Object?>)
        : null;
    final typeDefinitionJson = json['typeDefinition'];
    final typeDefinition = typeDefinitionJson != null
        ? TypeDefinitionClientCapabilities.fromJson(
            typeDefinitionJson as Map<String, Object?>)
        : null;
    final typeHierarchyJson = json['typeHierarchy'];
    final typeHierarchy = typeHierarchyJson != null
        ? TypeHierarchyClientCapabilities.fromJson(
            typeHierarchyJson as Map<String, Object?>)
        : null;
    return TextDocumentClientCapabilities(
      callHierarchy: callHierarchy,
      codeAction: codeAction,
      codeLens: codeLens,
      colorProvider: colorProvider,
      completion: completion,
      declaration: declaration,
      definition: definition,
      diagnostic: diagnostic,
      documentHighlight: documentHighlight,
      documentLink: documentLink,
      documentSymbol: documentSymbol,
      foldingRange: foldingRange,
      formatting: formatting,
      hover: hover,
      implementation: implementation,
      inlayHint: inlayHint,
      inlineValue: inlineValue,
      linkedEditingRange: linkedEditingRange,
      moniker: moniker,
      onTypeFormatting: onTypeFormatting,
      publishDiagnostics: publishDiagnostics,
      rangeFormatting: rangeFormatting,
      references: references,
      rename: rename,
      selectionRange: selectionRange,
      semanticTokens: semanticTokens,
      signatureHelp: signatureHelp,
      synchronization: synchronization,
      typeDefinition: typeDefinition,
      typeHierarchy: typeHierarchy,
    );
  }

  /// Capabilities specific to the various call hierarchy requests.
  ///
  /// @since 3.16.0
  final CallHierarchyClientCapabilities? callHierarchy;

  /// Capabilities specific to the `textDocument/codeAction` request.
  final CodeActionClientCapabilities? codeAction;

  /// Capabilities specific to the `textDocument/codeLens` request.
  final CodeLensClientCapabilities? codeLens;

  /// Capabilities specific to the `textDocument/documentColor` and the
  /// `textDocument/colorPresentation` request.
  ///
  /// @since 3.6.0
  final DocumentColorClientCapabilities? colorProvider;

  /// Capabilities specific to the `textDocument/completion` request.
  final CompletionClientCapabilities? completion;

  /// Capabilities specific to the `textDocument/declaration` request.
  ///
  /// @since 3.14.0
  final DeclarationClientCapabilities? declaration;

  /// Capabilities specific to the `textDocument/definition` request.
  final DefinitionClientCapabilities? definition;

  /// Capabilities specific to the diagnostic pull model.
  ///
  /// @since 3.17.0
  final DiagnosticClientCapabilities? diagnostic;

  /// Capabilities specific to the `textDocument/documentHighlight` request.
  final DocumentHighlightClientCapabilities? documentHighlight;

  /// Capabilities specific to the `textDocument/documentLink` request.
  final DocumentLinkClientCapabilities? documentLink;

  /// Capabilities specific to the `textDocument/documentSymbol` request.
  final DocumentSymbolClientCapabilities? documentSymbol;

  /// Capabilities specific to the `textDocument/foldingRange` request.
  ///
  /// @since 3.10.0
  final FoldingRangeClientCapabilities? foldingRange;

  /// Capabilities specific to the `textDocument/formatting` request.
  final DocumentFormattingClientCapabilities? formatting;

  /// Capabilities specific to the `textDocument/hover` request.
  final HoverClientCapabilities? hover;

  /// Capabilities specific to the `textDocument/implementation` request.
  ///
  /// @since 3.6.0
  final ImplementationClientCapabilities? implementation;

  /// Capabilities specific to the `textDocument/inlayHint` request.
  ///
  /// @since 3.17.0
  final InlayHintClientCapabilities? inlayHint;

  /// Capabilities specific to the `textDocument/inlineValue` request.
  ///
  /// @since 3.17.0
  final InlineValueClientCapabilities? inlineValue;

  /// Capabilities specific to the `textDocument/linkedEditingRange` request.
  ///
  /// @since 3.16.0
  final LinkedEditingRangeClientCapabilities? linkedEditingRange;

  /// Client capabilities specific to the `textDocument/moniker` request.
  ///
  /// @since 3.16.0
  final MonikerClientCapabilities? moniker;

  /// Capabilities specific to the `textDocument/onTypeFormatting` request.
  final DocumentOnTypeFormattingClientCapabilities? onTypeFormatting;

  /// Capabilities specific to the `textDocument/publishDiagnostics`
  /// notification.
  final PublishDiagnosticsClientCapabilities? publishDiagnostics;

  /// Capabilities specific to the `textDocument/rangeFormatting` request.
  final DocumentRangeFormattingClientCapabilities? rangeFormatting;

  /// Capabilities specific to the `textDocument/references` request.
  final ReferenceClientCapabilities? references;

  /// Capabilities specific to the `textDocument/rename` request.
  final RenameClientCapabilities? rename;

  /// Capabilities specific to the `textDocument/selectionRange` request.
  ///
  /// @since 3.15.0
  final SelectionRangeClientCapabilities? selectionRange;

  /// Capabilities specific to the various semantic token request.
  ///
  /// @since 3.16.0
  final SemanticTokensClientCapabilities? semanticTokens;

  /// Capabilities specific to the `textDocument/signatureHelp` request.
  final SignatureHelpClientCapabilities? signatureHelp;

  /// Defines which synchronization capabilities the client supports.
  final TextDocumentSyncClientCapabilities? synchronization;

  /// Capabilities specific to the `textDocument/typeDefinition` request.
  ///
  /// @since 3.6.0
  final TypeDefinitionClientCapabilities? typeDefinition;

  /// Capabilities specific to the various type hierarchy requests.
  ///
  /// @since 3.17.0
  final TypeHierarchyClientCapabilities? typeHierarchy;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (callHierarchy != null) {
      result['callHierarchy'] = callHierarchy?.toJson();
    }
    if (codeAction != null) {
      result['codeAction'] = codeAction?.toJson();
    }
    if (codeLens != null) {
      result['codeLens'] = codeLens?.toJson();
    }
    if (colorProvider != null) {
      result['colorProvider'] = colorProvider?.toJson();
    }
    if (completion != null) {
      result['completion'] = completion?.toJson();
    }
    if (declaration != null) {
      result['declaration'] = declaration?.toJson();
    }
    if (definition != null) {
      result['definition'] = definition?.toJson();
    }
    if (diagnostic != null) {
      result['diagnostic'] = diagnostic?.toJson();
    }
    if (documentHighlight != null) {
      result['documentHighlight'] = documentHighlight?.toJson();
    }
    if (documentLink != null) {
      result['documentLink'] = documentLink?.toJson();
    }
    if (documentSymbol != null) {
      result['documentSymbol'] = documentSymbol?.toJson();
    }
    if (foldingRange != null) {
      result['foldingRange'] = foldingRange?.toJson();
    }
    if (formatting != null) {
      result['formatting'] = formatting?.toJson();
    }
    if (hover != null) {
      result['hover'] = hover?.toJson();
    }
    if (implementation != null) {
      result['implementation'] = implementation?.toJson();
    }
    if (inlayHint != null) {
      result['inlayHint'] = inlayHint?.toJson();
    }
    if (inlineValue != null) {
      result['inlineValue'] = inlineValue?.toJson();
    }
    if (linkedEditingRange != null) {
      result['linkedEditingRange'] = linkedEditingRange?.toJson();
    }
    if (moniker != null) {
      result['moniker'] = moniker?.toJson();
    }
    if (onTypeFormatting != null) {
      result['onTypeFormatting'] = onTypeFormatting?.toJson();
    }
    if (publishDiagnostics != null) {
      result['publishDiagnostics'] = publishDiagnostics?.toJson();
    }
    if (rangeFormatting != null) {
      result['rangeFormatting'] = rangeFormatting?.toJson();
    }
    if (references != null) {
      result['references'] = references?.toJson();
    }
    if (rename != null) {
      result['rename'] = rename?.toJson();
    }
    if (selectionRange != null) {
      result['selectionRange'] = selectionRange?.toJson();
    }
    if (semanticTokens != null) {
      result['semanticTokens'] = semanticTokens?.toJson();
    }
    if (signatureHelp != null) {
      result['signatureHelp'] = signatureHelp?.toJson();
    }
    if (synchronization != null) {
      result['synchronization'] = synchronization?.toJson();
    }
    if (typeDefinition != null) {
      result['typeDefinition'] = typeDefinition?.toJson();
    }
    if (typeHierarchy != null) {
      result['typeHierarchy'] = typeHierarchy?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('callHierarchy');
      try {
        final callHierarchy = obj['callHierarchy'];
        if (callHierarchy != null &&
            !CallHierarchyClientCapabilities.canParse(
                callHierarchy, reporter)) {
          reporter
              .reportError('must be of type CallHierarchyClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeAction');
      try {
        final codeAction = obj['codeAction'];
        if (codeAction != null &&
            !CodeActionClientCapabilities.canParse(codeAction, reporter)) {
          reporter.reportError('must be of type CodeActionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeLens');
      try {
        final codeLens = obj['codeLens'];
        if (codeLens != null &&
            !CodeLensClientCapabilities.canParse(codeLens, reporter)) {
          reporter.reportError('must be of type CodeLensClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('colorProvider');
      try {
        final colorProvider = obj['colorProvider'];
        if (colorProvider != null &&
            !DocumentColorClientCapabilities.canParse(
                colorProvider, reporter)) {
          reporter
              .reportError('must be of type DocumentColorClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completion');
      try {
        final completion = obj['completion'];
        if (completion != null &&
            !CompletionClientCapabilities.canParse(completion, reporter)) {
          reporter.reportError('must be of type CompletionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('declaration');
      try {
        final declaration = obj['declaration'];
        if (declaration != null &&
            !DeclarationClientCapabilities.canParse(declaration, reporter)) {
          reporter.reportError('must be of type DeclarationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('definition');
      try {
        final definition = obj['definition'];
        if (definition != null &&
            !DefinitionClientCapabilities.canParse(definition, reporter)) {
          reporter.reportError('must be of type DefinitionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('diagnostic');
      try {
        final diagnostic = obj['diagnostic'];
        if (diagnostic != null &&
            !DiagnosticClientCapabilities.canParse(diagnostic, reporter)) {
          reporter.reportError('must be of type DiagnosticClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentHighlight');
      try {
        final documentHighlight = obj['documentHighlight'];
        if (documentHighlight != null &&
            !DocumentHighlightClientCapabilities.canParse(
                documentHighlight, reporter)) {
          reporter.reportError(
              'must be of type DocumentHighlightClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentLink');
      try {
        final documentLink = obj['documentLink'];
        if (documentLink != null &&
            !DocumentLinkClientCapabilities.canParse(documentLink, reporter)) {
          reporter
              .reportError('must be of type DocumentLinkClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSymbol');
      try {
        final documentSymbol = obj['documentSymbol'];
        if (documentSymbol != null &&
            !DocumentSymbolClientCapabilities.canParse(
                documentSymbol, reporter)) {
          reporter
              .reportError('must be of type DocumentSymbolClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRange');
      try {
        final foldingRange = obj['foldingRange'];
        if (foldingRange != null &&
            !FoldingRangeClientCapabilities.canParse(foldingRange, reporter)) {
          reporter
              .reportError('must be of type FoldingRangeClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('formatting');
      try {
        final formatting = obj['formatting'];
        if (formatting != null &&
            !DocumentFormattingClientCapabilities.canParse(
                formatting, reporter)) {
          reporter.reportError(
              'must be of type DocumentFormattingClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('hover');
      try {
        final hover = obj['hover'];
        if (hover != null &&
            !HoverClientCapabilities.canParse(hover, reporter)) {
          reporter.reportError('must be of type HoverClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('implementation');
      try {
        final implementation = obj['implementation'];
        if (implementation != null &&
            !ImplementationClientCapabilities.canParse(
                implementation, reporter)) {
          reporter
              .reportError('must be of type ImplementationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlayHint');
      try {
        final inlayHint = obj['inlayHint'];
        if (inlayHint != null &&
            !InlayHintClientCapabilities.canParse(inlayHint, reporter)) {
          reporter.reportError('must be of type InlayHintClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlineValue');
      try {
        final inlineValue = obj['inlineValue'];
        if (inlineValue != null &&
            !InlineValueClientCapabilities.canParse(inlineValue, reporter)) {
          reporter.reportError('must be of type InlineValueClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkedEditingRange');
      try {
        final linkedEditingRange = obj['linkedEditingRange'];
        if (linkedEditingRange != null &&
            !LinkedEditingRangeClientCapabilities.canParse(
                linkedEditingRange, reporter)) {
          reporter.reportError(
              'must be of type LinkedEditingRangeClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('moniker');
      try {
        final moniker = obj['moniker'];
        if (moniker != null &&
            !MonikerClientCapabilities.canParse(moniker, reporter)) {
          reporter.reportError('must be of type MonikerClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('onTypeFormatting');
      try {
        final onTypeFormatting = obj['onTypeFormatting'];
        if (onTypeFormatting != null &&
            !DocumentOnTypeFormattingClientCapabilities.canParse(
                onTypeFormatting, reporter)) {
          reporter.reportError(
              'must be of type DocumentOnTypeFormattingClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('publishDiagnostics');
      try {
        final publishDiagnostics = obj['publishDiagnostics'];
        if (publishDiagnostics != null &&
            !PublishDiagnosticsClientCapabilities.canParse(
                publishDiagnostics, reporter)) {
          reporter.reportError(
              'must be of type PublishDiagnosticsClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rangeFormatting');
      try {
        final rangeFormatting = obj['rangeFormatting'];
        if (rangeFormatting != null &&
            !DocumentRangeFormattingClientCapabilities.canParse(
                rangeFormatting, reporter)) {
          reporter.reportError(
              'must be of type DocumentRangeFormattingClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('references');
      try {
        final references = obj['references'];
        if (references != null &&
            !ReferenceClientCapabilities.canParse(references, reporter)) {
          reporter.reportError('must be of type ReferenceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rename');
      try {
        final rename = obj['rename'];
        if (rename != null &&
            !RenameClientCapabilities.canParse(rename, reporter)) {
          reporter.reportError('must be of type RenameClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRange');
      try {
        final selectionRange = obj['selectionRange'];
        if (selectionRange != null &&
            !SelectionRangeClientCapabilities.canParse(
                selectionRange, reporter)) {
          reporter
              .reportError('must be of type SelectionRangeClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('semanticTokens');
      try {
        final semanticTokens = obj['semanticTokens'];
        if (semanticTokens != null &&
            !SemanticTokensClientCapabilities.canParse(
                semanticTokens, reporter)) {
          reporter
              .reportError('must be of type SemanticTokensClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatureHelp');
      try {
        final signatureHelp = obj['signatureHelp'];
        if (signatureHelp != null &&
            !SignatureHelpClientCapabilities.canParse(
                signatureHelp, reporter)) {
          reporter
              .reportError('must be of type SignatureHelpClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('synchronization');
      try {
        final synchronization = obj['synchronization'];
        if (synchronization != null &&
            !TextDocumentSyncClientCapabilities.canParse(
                synchronization, reporter)) {
          reporter.reportError(
              'must be of type TextDocumentSyncClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeDefinition');
      try {
        final typeDefinition = obj['typeDefinition'];
        if (typeDefinition != null &&
            !TypeDefinitionClientCapabilities.canParse(
                typeDefinition, reporter)) {
          reporter
              .reportError('must be of type TypeDefinitionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeHierarchy');
      try {
        final typeHierarchy = obj['typeHierarchy'];
        if (typeHierarchy != null &&
            !TypeHierarchyClientCapabilities.canParse(
                typeHierarchy, reporter)) {
          reporter
              .reportError('must be of type TypeHierarchyClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentClientCapabilities &&
        other.runtimeType == TextDocumentClientCapabilities &&
        callHierarchy == other.callHierarchy &&
        codeAction == other.codeAction &&
        codeLens == other.codeLens &&
        colorProvider == other.colorProvider &&
        completion == other.completion &&
        declaration == other.declaration &&
        definition == other.definition &&
        diagnostic == other.diagnostic &&
        documentHighlight == other.documentHighlight &&
        documentLink == other.documentLink &&
        documentSymbol == other.documentSymbol &&
        foldingRange == other.foldingRange &&
        formatting == other.formatting &&
        hover == other.hover &&
        implementation == other.implementation &&
        inlayHint == other.inlayHint &&
        inlineValue == other.inlineValue &&
        linkedEditingRange == other.linkedEditingRange &&
        moniker == other.moniker &&
        onTypeFormatting == other.onTypeFormatting &&
        publishDiagnostics == other.publishDiagnostics &&
        rangeFormatting == other.rangeFormatting &&
        references == other.references &&
        rename == other.rename &&
        selectionRange == other.selectionRange &&
        semanticTokens == other.semanticTokens &&
        signatureHelp == other.signatureHelp &&
        synchronization == other.synchronization &&
        typeDefinition == other.typeDefinition &&
        typeHierarchy == other.typeHierarchy;
  }

  @override
  int get hashCode => Object.hashAll([
        callHierarchy,
        codeAction,
        codeLens,
        colorProvider,
        completion,
        declaration,
        definition,
        diagnostic,
        documentHighlight,
        documentLink,
        documentSymbol,
        foldingRange,
        formatting,
        hover,
        implementation,
        inlayHint,
        inlineValue,
        linkedEditingRange,
        moniker,
        onTypeFormatting,
        publishDiagnostics,
        rangeFormatting,
        references,
        rename,
        selectionRange,
        semanticTokens,
        signatureHelp,
        synchronization,
        typeDefinition,
        typeHierarchy,
      ]);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentContentChangeEvent1 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentContentChangeEvent1.canParse,
    TextDocumentContentChangeEvent1.fromJson,
  );

  TextDocumentContentChangeEvent1({
    required this.range,
    this.rangeLength,
    required this.text,
  });
  static TextDocumentContentChangeEvent1 fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final rangeLengthJson = json['rangeLength'];
    final rangeLength = rangeLengthJson as int?;
    final textJson = json['text'];
    final text = textJson as String;
    return TextDocumentContentChangeEvent1(
      range: range,
      rangeLength: rangeLength,
      text: text,
    );
  }

  /// The range of the document that changed.
  final Range range;

  /// The optional length of the range that got replaced.
  ///
  /// @deprecated use range instead.
  final int? rangeLength;

  /// The new text for the provided range.
  final String text;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    if (rangeLength != null) {
      result['rangeLength'] = rangeLength;
    }
    result['text'] = text;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rangeLength');
      try {
        final rangeLength = obj['rangeLength'];
        if (rangeLength != null && rangeLength is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final text = obj['text'];
        if (text == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (text is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentContentChangeEvent1');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentContentChangeEvent1 &&
        other.runtimeType == TextDocumentContentChangeEvent1 &&
        range == other.range &&
        rangeLength == other.rangeLength &&
        text == other.text;
  }

  @override
  int get hashCode => Object.hash(
        range,
        rangeLength,
        text,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentContentChangeEvent2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentContentChangeEvent2.canParse,
    TextDocumentContentChangeEvent2.fromJson,
  );

  TextDocumentContentChangeEvent2({
    required this.text,
  });
  static TextDocumentContentChangeEvent2 fromJson(Map<String, Object?> json) {
    final textJson = json['text'];
    final text = textJson as String;
    return TextDocumentContentChangeEvent2(
      text: text,
    );
  }

  /// The new text of the whole document.
  final String text;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final text = obj['text'];
        if (text == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (text is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentContentChangeEvent2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentContentChangeEvent2 &&
        other.runtimeType == TextDocumentContentChangeEvent2 &&
        text == other.text;
  }

  @override
  int get hashCode => text.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Describes textual changes on a text document. A TextDocumentEdit describes
/// all changes on a document version Si and after they are applied move the
/// document to version Si+1. So the creator of a TextDocumentEdit doesn't need
/// to sort the array of edits or do any kind of ordering. However the edits
/// must be non overlapping.
class TextDocumentEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentEdit.canParse,
    TextDocumentEdit.fromJson,
  );

  TextDocumentEdit({
    required this.edits,
    required this.textDocument,
  });
  static TextDocumentEdit fromJson(Map<String, Object?> json) {
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map((item) => AnnotatedTextEdit.canParse(item, nullLspJsonReporter)
            ? Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>.t1(
                AnnotatedTextEdit.fromJson(item as Map<String, Object?>))
            : (SnippetTextEdit.canParse(item, nullLspJsonReporter)
                ? Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>.t2(
                    SnippetTextEdit.fromJson(item as Map<String, Object?>))
                : (TextEdit.canParse(item, nullLspJsonReporter)
                    ? Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>.t3(
                        TextEdit.fromJson(item as Map<String, Object?>))
                    : (throw '''$item was not one of (AnnotatedTextEdit, SnippetTextEdit, TextEdit)'''))))
        .toList();
    final textDocumentJson = json['textDocument'];
    final textDocument = OptionalVersionedTextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return TextDocumentEdit(
      edits: edits,
      textDocument: textDocument,
    );
  }

  /// The edits to be applied.
  ///
  /// @since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a
  /// client capability.
  final List<Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>> edits;

  /// The text document to change.
  final OptionalVersionedTextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['edits'] = edits;
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('edits');
      try {
        if (!obj.containsKey('edits')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final edits = obj['edits'];
        if (edits == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (edits is! List<Object?> ||
            edits.any((item) =>
                !AnnotatedTextEdit.canParse(item, reporter) &&
                !SnippetTextEdit.canParse(item, reporter) &&
                !TextEdit.canParse(item, reporter))) {
          reporter.reportError(
              'must be of type List<Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!OptionalVersionedTextDocumentIdentifier.canParse(
            textDocument, reporter)) {
          reporter.reportError(
              'must be of type OptionalVersionedTextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentEdit &&
        other.runtimeType == TextDocumentEdit &&
        listEqual(
            edits,
            other.edits,
            (Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit> a,
                    Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit> b) =>
                a == b) &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(edits),
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentFilter1 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentFilter1.canParse,
    TextDocumentFilter1.fromJson,
  );

  TextDocumentFilter1({
    required this.language,
    this.pattern,
    this.scheme,
  });
  static TextDocumentFilter1 fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return TextDocumentFilter1(
      language: language,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// A language id, like `typescript`. */
  final String language;

  /// A glob pattern, like `*.{ts,js}`. */
  final String? pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['language'] = language;
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        if (!obj.containsKey('language')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final language = obj['language'];
        if (language == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        final pattern = obj['pattern'];
        if (pattern != null && pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentFilter1');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentFilter1 &&
        other.runtimeType == TextDocumentFilter1 &&
        language == other.language &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        language,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentFilter3 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentFilter3.canParse,
    TextDocumentFilter3.fromJson,
  );

  TextDocumentFilter3({
    this.language,
    required this.pattern,
    this.scheme,
  });
  static TextDocumentFilter3 fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return TextDocumentFilter3(
      language: language,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// A language id, like `typescript`. */
  final String? language;

  /// A glob pattern, like `*.{ts,js}`. */
  final String pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (language != null) {
      result['language'] = language;
    }
    result['pattern'] = pattern;
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        final language = obj['language'];
        if (language != null && language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        if (!obj.containsKey('pattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final pattern = obj['pattern'];
        if (pattern == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentFilter3');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentFilter3 &&
        other.runtimeType == TextDocumentFilter3 &&
        language == other.language &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        language,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentFilterWithScheme implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentFilterWithScheme.canParse,
    TextDocumentFilterWithScheme.fromJson,
  );

  TextDocumentFilterWithScheme({
    this.language,
    this.pattern,
    required this.scheme,
  });
  static TextDocumentFilterWithScheme fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    return TextDocumentFilterWithScheme(
      language: language,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// A language id, like `typescript`. */
  final String? language;

  /// A glob pattern, like `*.{ts,js}`. */
  final String? pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (language != null) {
      result['language'] = language;
    }
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    result['scheme'] = scheme;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        final language = obj['language'];
        if (language != null && language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        final pattern = obj['pattern'];
        if (pattern != null && pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        if (!obj.containsKey('scheme')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final scheme = obj['scheme'];
        if (scheme == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentFilterWithScheme');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentFilterWithScheme &&
        other.runtimeType == TextDocumentFilterWithScheme &&
        language == other.language &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        language,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A literal to identify a text document in the client.
class TextDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentIdentifier.canParse,
    TextDocumentIdentifier.fromJson,
  );

  TextDocumentIdentifier({
    required this.uri,
  });
  static TextDocumentIdentifier fromJson(Map<String, Object?> json) {
    if (VersionedTextDocumentIdentifier.canParse(json, nullLspJsonReporter)) {
      return VersionedTextDocumentIdentifier.fromJson(json);
    }
    if (OptionalVersionedTextDocumentIdentifier.canParse(
        json, nullLspJsonReporter)) {
      return OptionalVersionedTextDocumentIdentifier.fromJson(json);
    }
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return TextDocumentIdentifier(
      uri: uri,
    );
  }

  /// The text document's uri.
  final String uri;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentIdentifier &&
        other.runtimeType == TextDocumentIdentifier &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An item to transfer a text document from the client to the server.
class TextDocumentItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentItem.canParse,
    TextDocumentItem.fromJson,
  );

  TextDocumentItem({
    required this.languageId,
    required this.text,
    required this.uri,
    required this.version,
  });
  static TextDocumentItem fromJson(Map<String, Object?> json) {
    final languageIdJson = json['languageId'];
    final languageId = languageIdJson as String;
    final textJson = json['text'];
    final text = textJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return TextDocumentItem(
      languageId: languageId,
      text: text,
      uri: uri,
      version: version,
    );
  }

  /// The text document's language identifier.
  final String languageId;

  /// The content of the opened text document.
  final String text;

  /// The text document's uri.
  final String uri;

  /// The version number of this document (it will increase after each change,
  /// including undo/redo).
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['languageId'] = languageId;
    result['text'] = text;
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('languageId');
      try {
        if (!obj.containsKey('languageId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final languageId = obj['languageId'];
        if (languageId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (languageId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final text = obj['text'];
        if (text == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (text is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentItem &&
        other.runtimeType == TextDocumentItem &&
        languageId == other.languageId &&
        text == other.text &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        languageId,
        text,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in requests to pass a text document and a position
/// inside that document.
class TextDocumentPositionParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentPositionParams.canParse,
    TextDocumentPositionParams.fromJson,
  );

  TextDocumentPositionParams({
    required this.position,
    required this.textDocument,
  });
  static TextDocumentPositionParams fromJson(Map<String, Object?> json) {
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
      return PrepareRenameParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (TypeHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyPrepareParams.fromJson(json);
    }
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return TextDocumentPositionParams(
      position: position,
      textDocument: textDocument,
    );
  }

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentPositionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentPositionParams &&
        other.runtimeType == TextDocumentPositionParams &&
        position == other.position &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// General text document registration options.
class TextDocumentRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentRegistrationOptions.canParse,
    TextDocumentRegistrationOptions.fromJson,
  );

  TextDocumentRegistrationOptions({
    this.documentSelector,
  });
  static TextDocumentRegistrationOptions fromJson(Map<String, Object?> json) {
    if (TextDocumentChangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentChangeRegistrationOptions.fromJson(json);
    }
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (CodeActionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionRegistrationOptions.fromJson(json);
    }
    if (CodeLensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensRegistrationOptions.fromJson(json);
    }
    if (CompletionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionRegistrationOptions.fromJson(json);
    }
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (DefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionRegistrationOptions.fromJson(json);
    }
    if (DiagnosticRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (DocumentFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentHighlightRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentHighlightRegistrationOptions.fromJson(json);
    }
    if (DocumentLinkRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkRegistrationOptions.fromJson(json);
    }
    if (DocumentOnTypeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentRangeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentRangeFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.fromJson(json);
    }
    if (ReferenceRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceRegistrationOptions.fromJson(json);
    }
    if (RenameRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return RenameRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    if (TextDocumentSaveRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentSaveRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    return TextDocumentRegistrationOptions(
      documentSelector: documentSelector,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<TextDocumentFilterWithScheme>? documentSelector;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentRegistrationOptions &&
        other.runtimeType == TextDocumentRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b);
  }

  @override
  int get hashCode => lspHashCode(documentSelector);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents reasons why a text document is saved.
class TextDocumentSaveReason implements ToJsonable {
  const TextDocumentSaveReason(this._value);
  const TextDocumentSaveReason.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Automatic after a delay.
  static const AfterDelay = TextDocumentSaveReason(2);

  /// When the editor lost focus.
  static const FocusOut = TextDocumentSaveReason(3);

  /// Manually triggered, e.g. by the user pressing save, by starting debugging,
  /// or by an API call.
  static const Manual = TextDocumentSaveReason(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TextDocumentSaveReason && other._value == _value;
}

/// Save registration options.
class TextDocumentSaveRegistrationOptions
    implements SaveOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentSaveRegistrationOptions.canParse,
    TextDocumentSaveRegistrationOptions.fromJson,
  );

  TextDocumentSaveRegistrationOptions({
    this.documentSelector,
    this.includeText,
  });
  static TextDocumentSaveRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final includeTextJson = json['includeText'];
    final includeText = includeTextJson as bool?;
    return TextDocumentSaveRegistrationOptions(
      documentSelector: documentSelector,
      includeText: includeText,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The client is supposed to include the content on save.
  @override
  final bool? includeText;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (includeText != null) {
      result['includeText'] = includeText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('includeText');
      try {
        final includeText = obj['includeText'];
        if (includeText != null && includeText is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type TextDocumentSaveRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentSaveRegistrationOptions &&
        other.runtimeType == TextDocumentSaveRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        includeText == other.includeText;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        includeText,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentSyncClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentSyncClientCapabilities.canParse,
    TextDocumentSyncClientCapabilities.fromJson,
  );

  TextDocumentSyncClientCapabilities({
    this.didSave,
    this.dynamicRegistration,
    this.willSave,
    this.willSaveWaitUntil,
  });
  static TextDocumentSyncClientCapabilities fromJson(
      Map<String, Object?> json) {
    final didSaveJson = json['didSave'];
    final didSave = didSaveJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final willSaveJson = json['willSave'];
    final willSave = willSaveJson as bool?;
    final willSaveWaitUntilJson = json['willSaveWaitUntil'];
    final willSaveWaitUntil = willSaveWaitUntilJson as bool?;
    return TextDocumentSyncClientCapabilities(
      didSave: didSave,
      dynamicRegistration: dynamicRegistration,
      willSave: willSave,
      willSaveWaitUntil: willSaveWaitUntil,
    );
  }

  /// The client supports did save notifications.
  final bool? didSave;

  /// Whether text document synchronization supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports sending will save notifications.
  final bool? willSave;

  /// The client supports sending a will save request and waits for a response
  /// providing text edits which will be applied to the document before it is
  /// saved.
  final bool? willSaveWaitUntil;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (didSave != null) {
      result['didSave'] = didSave;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (willSave != null) {
      result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('didSave');
      try {
        final didSave = obj['didSave'];
        if (didSave != null && didSave is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSave');
      try {
        final willSave = obj['willSave'];
        if (willSave != null && willSave is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSaveWaitUntil');
      try {
        final willSaveWaitUntil = obj['willSaveWaitUntil'];
        if (willSaveWaitUntil != null && willSaveWaitUntil is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type TextDocumentSyncClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentSyncClientCapabilities &&
        other.runtimeType == TextDocumentSyncClientCapabilities &&
        didSave == other.didSave &&
        dynamicRegistration == other.dynamicRegistration &&
        willSave == other.willSave &&
        willSaveWaitUntil == other.willSaveWaitUntil;
  }

  @override
  int get hashCode => Object.hash(
        didSave,
        dynamicRegistration,
        willSave,
        willSaveWaitUntil,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines how the host (editor) should sync document changes to the language
/// server.
class TextDocumentSyncKind implements ToJsonable {
  const TextDocumentSyncKind(this._value);
  const TextDocumentSyncKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Documents are synced by always sending the full content of the document.
  static const Full = TextDocumentSyncKind(1);

  /// Documents are synced by sending the full content on open. After that only
  /// incremental updates to the document are send.
  static const Incremental = TextDocumentSyncKind(2);

  /// Documents should not be synced at all.
  static const None = TextDocumentSyncKind(0);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TextDocumentSyncKind && other._value == _value;
}

class TextDocumentSyncOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentSyncOptions.canParse,
    TextDocumentSyncOptions.fromJson,
  );

  TextDocumentSyncOptions({
    this.change,
    this.openClose,
    this.save,
    this.willSave,
    this.willSaveWaitUntil,
  });
  static TextDocumentSyncOptions fromJson(Map<String, Object?> json) {
    final changeJson = json['change'];
    final change = changeJson != null
        ? TextDocumentSyncKind.fromJson(changeJson as int)
        : null;
    final openCloseJson = json['openClose'];
    final openClose = openCloseJson as bool?;
    final saveJson = json['save'];
    final save = saveJson == null
        ? null
        : (saveJson is bool
            ? Either2<bool, SaveOptions>.t1(saveJson)
            : (SaveOptions.canParse(saveJson, nullLspJsonReporter)
                ? Either2<bool, SaveOptions>.t2(
                    SaveOptions.fromJson(saveJson as Map<String, Object?>))
                : (throw '''$saveJson was not one of (bool, SaveOptions)''')));
    final willSaveJson = json['willSave'];
    final willSave = willSaveJson as bool?;
    final willSaveWaitUntilJson = json['willSaveWaitUntil'];
    final willSaveWaitUntil = willSaveWaitUntilJson as bool?;
    return TextDocumentSyncOptions(
      change: change,
      openClose: openClose,
      save: save,
      willSave: willSave,
      willSaveWaitUntil: willSaveWaitUntil,
    );
  }

  /// Change notifications are sent to the server. See
  /// TextDocumentSyncKind.None, TextDocumentSyncKind.Full and
  /// TextDocumentSyncKind.Incremental. If omitted it defaults to
  /// TextDocumentSyncKind.None.
  final TextDocumentSyncKind? change;

  /// Open and close notifications are sent to the server. If omitted open close
  /// notification should not be sent.
  final bool? openClose;

  /// If present save notifications are sent to the server. If omitted the
  /// notification should not be sent.
  final Either2<bool, SaveOptions>? save;

  /// If present will save notifications are sent to the server. If omitted the
  /// notification should not be sent.
  final bool? willSave;

  /// If present will save wait until requests are sent to the server. If
  /// omitted the request should not be sent.
  final bool? willSaveWaitUntil;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (change != null) {
      result['change'] = change?.toJson();
    }
    if (openClose != null) {
      result['openClose'] = openClose;
    }
    if (save != null) {
      result['save'] = save;
    }
    if (willSave != null) {
      result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('change');
      try {
        final change = obj['change'];
        if (change != null &&
            !TextDocumentSyncKind.canParse(change, reporter)) {
          reporter.reportError('must be of type TextDocumentSyncKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('openClose');
      try {
        final openClose = obj['openClose'];
        if (openClose != null && openClose is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('save');
      try {
        final save = obj['save'];
        if (save != null &&
            save is! bool &&
            !SaveOptions.canParse(save, reporter)) {
          reporter.reportError('must be of type Either2<bool, SaveOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSave');
      try {
        final willSave = obj['willSave'];
        if (willSave != null && willSave is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSaveWaitUntil');
      try {
        final willSaveWaitUntil = obj['willSaveWaitUntil'];
        if (willSaveWaitUntil != null && willSaveWaitUntil is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentSyncOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentSyncOptions &&
        other.runtimeType == TextDocumentSyncOptions &&
        change == other.change &&
        openClose == other.openClose &&
        save == other.save &&
        willSave == other.willSave &&
        willSaveWaitUntil == other.willSaveWaitUntil;
  }

  @override
  int get hashCode => Object.hash(
        change,
        openClose,
        save,
        willSave,
        willSaveWaitUntil,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A text edit applicable to a text document.
class TextEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextEdit.canParse,
    TextEdit.fromJson,
  );

  TextEdit({
    required this.newText,
    required this.range,
  });
  static TextEdit fromJson(Map<String, Object?> json) {
    if (AnnotatedTextEdit.canParse(json, nullLspJsonReporter)) {
      return AnnotatedTextEdit.fromJson(json);
    }
    if (SnippetTextEdit.canParse(json, nullLspJsonReporter)) {
      return SnippetTextEdit.fromJson(json);
    }
    final newTextJson = json['newText'];
    final newText = newTextJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return TextEdit(
      newText: newText,
      range: range,
    );
  }

  /// The string to be inserted. For delete operations use an empty string.
  final String newText;

  /// The range of the text document to be manipulated. To insert text into a
  /// document create a range where start === end.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['newText'] = newText;
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('newText');
      try {
        if (!obj.containsKey('newText')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newText = obj['newText'];
        if (newText == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextEdit &&
        other.runtimeType == TextEdit &&
        newText == other.newText &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        newText,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TokenFormat implements ToJsonable {
  const TokenFormat(this._value);
  const TokenFormat.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  static const Relative = TokenFormat('relative');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TokenFormat && other._value == _value;
}

class TraceValues implements ToJsonable {
  const TraceValues(this._value);
  const TraceValues.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// Trace messages only.
  static const Messages = TraceValues('messages');

  /// Turn tracing off.
  static const Off = TraceValues('off');

  /// Verbose message tracing.
  static const Verbose = TraceValues('verbose');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TraceValues && other._value == _value;
}

/// Since 3.6.0
class TypeDefinitionClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionClientCapabilities.canParse,
    TypeDefinitionClientCapabilities.fromJson,
  );

  TypeDefinitionClientCapabilities({
    this.dynamicRegistration,
    this.linkSupport,
  });
  static TypeDefinitionClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final linkSupportJson = json['linkSupport'];
    final linkSupport = linkSupportJson as bool?;
    return TypeDefinitionClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      linkSupport: linkSupport,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `TypeDefinitionRegistrationOptions`
  /// return value for the corresponding server capability as well.
  final bool? dynamicRegistration;

  /// The client supports additional metadata in the form of definition links.
  ///
  /// Since 3.14.0
  final bool? linkSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (linkSupport != null) {
      result['linkSupport'] = linkSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        final linkSupport = obj['linkSupport'];
        if (linkSupport != null && linkSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeDefinitionClientCapabilities &&
        other.runtimeType == TypeDefinitionClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        linkSupport == other.linkSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        linkSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeDefinitionOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionOptions.canParse,
    TypeDefinitionOptions.fromJson,
  );

  TypeDefinitionOptions({
    this.workDoneProgress,
  });
  static TypeDefinitionOptions fromJson(Map<String, Object?> json) {
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeDefinitionOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeDefinitionOptions &&
        other.runtimeType == TypeDefinitionOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeDefinitionParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionParams.canParse,
    TypeDefinitionParams.fromJson,
  );

  TypeDefinitionParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static TypeDefinitionParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return TypeDefinitionParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeDefinitionParams &&
        other.runtimeType == TypeDefinitionParams &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeDefinitionRegistrationOptions
    implements
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        TypeDefinitionOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionRegistrationOptions.canParse,
    TypeDefinitionRegistrationOptions.fromJson,
  );

  TypeDefinitionRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static TypeDefinitionRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeDefinitionRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeDefinitionRegistrationOptions &&
        other.runtimeType == TypeDefinitionRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.17.0
class TypeHierarchyClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyClientCapabilities.canParse,
    TypeHierarchyClientCapabilities.fromJson,
  );

  TypeHierarchyClientCapabilities({
    this.dynamicRegistration,
  });
  static TypeHierarchyClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return TypeHierarchyClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyClientCapabilities &&
        other.runtimeType == TypeHierarchyClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.17.0
class TypeHierarchyItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyItem.canParse,
    TypeHierarchyItem.fromJson,
  );

  TypeHierarchyItem({
    this.data,
    this.detail,
    required this.kind,
    required this.name,
    required this.range,
    required this.selectionRange,
    this.tags,
    required this.uri,
  });
  static TypeHierarchyItem fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final nameJson = json['name'];
    final name = nameJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final selectionRangeJson = json['selectionRange'];
    final selectionRange =
        Range.fromJson(selectionRangeJson as Map<String, Object?>);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return TypeHierarchyItem(
      data: data,
      detail: detail,
      kind: kind,
      name: name,
      range: range,
      selectionRange: selectionRange,
      tags: tags,
      uri: uri,
    );
  }

  /// A data entry field that is preserved between a type hierarchy prepare and
  /// supertypes or subtypes requests. It could also be used to identify the
  /// type hierarchy in the server, helping improve the performance on resolving
  /// supertypes and subtypes.
  final Object? data;

  /// More detail for this item, e.g. the signature of a function.
  final String? detail;

  /// The kind of this item.
  final SymbolKind kind;

  /// The name of this item.
  final String name;

  /// The range enclosing this symbol not including leading/trailing whitespace
  /// but everything else, e.g. comments and code.
  final Range range;

  /// The range that should be selected and revealed when this symbol is being
  /// picked, e.g. the name of a function. Must be contained by the `range`.
  final Range selectionRange;

  /// Tags for this item.
  final List<SymbolTag>? tags;

  /// The resource identifier of this item.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    if (detail != null) {
      result['detail'] = detail;
    }
    result['kind'] = kind.toJson();
    result['name'] = name;
    result['range'] = range.toJson();
    result['selectionRange'] = selectionRange.toJson();
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('detail');
      try {
        final detail = obj['detail'];
        if (detail != null && detail is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRange');
      try {
        if (!obj.containsKey('selectionRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final selectionRange = obj['selectionRange'];
        if (selectionRange == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(selectionRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyItem &&
        other.runtimeType == TypeHierarchyItem &&
        data == other.data &&
        detail == other.detail &&
        kind == other.kind &&
        name == other.name &&
        range == other.range &&
        selectionRange == other.selectionRange &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        data,
        detail,
        kind,
        name,
        range,
        selectionRange,
        lspHashCode(tags),
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Type hierarchy options used during static registration.
///
/// @since 3.17.0
class TypeHierarchyOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyOptions.canParse,
    TypeHierarchyOptions.fromJson,
  );

  TypeHierarchyOptions({
    this.workDoneProgress,
  });
  static TypeHierarchyOptions fromJson(Map<String, Object?> json) {
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeHierarchyOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyOptions &&
        other.runtimeType == TypeHierarchyOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameter of a `textDocument/prepareTypeHierarchy` request.
///
/// @since 3.17.0
class TypeHierarchyPrepareParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyPrepareParams.canParse,
    TypeHierarchyPrepareParams.fromJson,
  );

  TypeHierarchyPrepareParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static TypeHierarchyPrepareParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return TypeHierarchyPrepareParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyPrepareParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyPrepareParams &&
        other.runtimeType == TypeHierarchyPrepareParams &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Type hierarchy options used during static or dynamic registration.
///
/// @since 3.17.0
class TypeHierarchyRegistrationOptions
    implements
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        TypeHierarchyOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyRegistrationOptions.canParse,
    TypeHierarchyRegistrationOptions.fromJson,
  );

  TypeHierarchyRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static TypeHierarchyRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeHierarchyRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyRegistrationOptions &&
        other.runtimeType == TypeHierarchyRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameter of a `typeHierarchy/subtypes` request.
///
/// @since 3.17.0
class TypeHierarchySubtypesParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchySubtypesParams.canParse,
    TypeHierarchySubtypesParams.fromJson,
  );

  TypeHierarchySubtypesParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static TypeHierarchySubtypesParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = TypeHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return TypeHierarchySubtypesParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final TypeHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['item'] = item.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('item');
      try {
        if (!obj.containsKey('item')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final item = obj['item'];
        if (item == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TypeHierarchyItem.canParse(item, reporter)) {
          reporter.reportError('must be of type TypeHierarchyItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchySubtypesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchySubtypesParams &&
        other.runtimeType == TypeHierarchySubtypesParams &&
        item == other.item &&
        partialResultToken == other.partialResultToken &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        item,
        partialResultToken,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameter of a `typeHierarchy/supertypes` request.
///
/// @since 3.17.0
class TypeHierarchySupertypesParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchySupertypesParams.canParse,
    TypeHierarchySupertypesParams.fromJson,
  );

  TypeHierarchySupertypesParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static TypeHierarchySupertypesParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = TypeHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return TypeHierarchySupertypesParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final TypeHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['item'] = item.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('item');
      try {
        if (!obj.containsKey('item')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final item = obj['item'];
        if (item == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TypeHierarchyItem.canParse(item, reporter)) {
          reporter.reportError('must be of type TypeHierarchyItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchySupertypesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchySupertypesParams &&
        other.runtimeType == TypeHierarchySupertypesParams &&
        item == other.item &&
        partialResultToken == other.partialResultToken &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        item,
        partialResultToken,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A diagnostic report indicating that the last returned report is still
/// accurate.
///
/// @since 3.17.0
class UnchangedDocumentDiagnosticReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    UnchangedDocumentDiagnosticReport.canParse,
    UnchangedDocumentDiagnosticReport.fromJson,
  );

  UnchangedDocumentDiagnosticReport({
    this.kind = 'unchanged',
    required this.resultId,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static UnchangedDocumentDiagnosticReport fromJson(Map<String, Object?> json) {
    if (WorkspaceUnchangedDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceUnchangedDocumentDiagnosticReport.fromJson(json);
    }
    if (RelatedUnchangedDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return RelatedUnchangedDocumentDiagnosticReport.fromJson(json);
    }
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    return UnchangedDocumentDiagnosticReport(
      kind: kind,
      resultId: resultId,
    );
  }

  /// A document diagnostic report indicating no changes to the last result. A
  /// server can only return `unchanged` if result ids are provided.
  final String kind;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  final String resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    result['resultId'] = resultId;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'unchanged') {
          reporter.reportError('must be the literal \'unchanged\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        if (!obj.containsKey('resultId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final resultId = obj['resultId'];
        if (resultId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type UnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is UnchangedDocumentDiagnosticReport &&
        other.runtimeType == UnchangedDocumentDiagnosticReport &&
        kind == other.kind &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Moniker uniqueness level to define scope of the moniker.
///
/// @since 3.16.0
class UniquenessLevel implements ToJsonable {
  const UniquenessLevel(this._value);
  const UniquenessLevel.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// The moniker is only unique inside a document
  static const document = UniquenessLevel('document');

  /// The moniker is globally unique
  static const global = UniquenessLevel('global');

  /// The moniker is unique inside the group to which a project belongs
  static const group = UniquenessLevel('group');

  /// The moniker is unique inside a project for which a dump got created
  static const project = UniquenessLevel('project');

  /// The moniker is unique inside the moniker scheme.
  static const scheme = UniquenessLevel('scheme');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is UniquenessLevel && other._value == _value;
}

/// General parameters to unregister a request or notification.
class Unregistration implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Unregistration.canParse,
    Unregistration.fromJson,
  );

  Unregistration({
    required this.id,
    required this.method,
  });
  static Unregistration fromJson(Map<String, Object?> json) {
    final idJson = json['id'];
    final id = idJson as String;
    final methodJson = json['method'];
    final method = methodJson as String;
    return Unregistration(
      id: id,
      method: method,
    );
  }

  /// The id used to unregister the request or notification. Usually an id
  /// provided during the register request.
  final String id;

  /// The method to unregister for.
  final String method;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['id'] = id;
    result['method'] = method;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final id = obj['id'];
        if (id == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('method');
      try {
        if (!obj.containsKey('method')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final method = obj['method'];
        if (method == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (method is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Unregistration');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Unregistration &&
        other.runtimeType == Unregistration &&
        id == other.id &&
        method == other.method;
  }

  @override
  int get hashCode => Object.hash(
        id,
        method,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class UnregistrationParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    UnregistrationParams.canParse,
    UnregistrationParams.fromJson,
  );

  UnregistrationParams({
    required this.unregisterations,
  });
  static UnregistrationParams fromJson(Map<String, Object?> json) {
    final unregisterationsJson = json['unregisterations'];
    final unregisterations = (unregisterationsJson as List<Object?>)
        .map((item) => Unregistration.fromJson(item as Map<String, Object?>))
        .toList();
    return UnregistrationParams(
      unregisterations: unregisterations,
    );
  }

  final List<Unregistration> unregisterations;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['unregisterations'] =
        unregisterations.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('unregisterations');
      try {
        if (!obj.containsKey('unregisterations')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final unregisterations = obj['unregisterations'];
        if (unregisterations == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (unregisterations is! List<Object?> ||
            unregisterations
                .any((item) => !Unregistration.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Unregistration>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type UnregistrationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is UnregistrationParams &&
        other.runtimeType == UnregistrationParams &&
        listEqual(unregisterations, other.unregisterations,
            (Unregistration a, Unregistration b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(unregisterations);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A versioned notebook document identifier.
///
/// @since 3.17.0
class VersionedNotebookDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    VersionedNotebookDocumentIdentifier.canParse,
    VersionedNotebookDocumentIdentifier.fromJson,
  );

  VersionedNotebookDocumentIdentifier({
    required this.uri,
    required this.version,
  });
  static VersionedNotebookDocumentIdentifier fromJson(
      Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return VersionedNotebookDocumentIdentifier(
      uri: uri,
      version: version,
    );
  }

  /// The notebook document's uri.
  final String uri;

  /// The version number of this notebook document.
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type VersionedNotebookDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is VersionedNotebookDocumentIdentifier &&
        other.runtimeType == VersionedNotebookDocumentIdentifier &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A text document identifier to denote a specific version of a text document.
class VersionedTextDocumentIdentifier
    implements TextDocumentIdentifier, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    VersionedTextDocumentIdentifier.canParse,
    VersionedTextDocumentIdentifier.fromJson,
  );

  VersionedTextDocumentIdentifier({
    required this.uri,
    required this.version,
  });
  static VersionedTextDocumentIdentifier fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return VersionedTextDocumentIdentifier(
      uri: uri,
      version: version,
    );
  }

  /// The text document's uri.
  @override
  final String uri;

  /// The version number of this document.
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type VersionedTextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is VersionedTextDocumentIdentifier &&
        other.runtimeType == VersionedTextDocumentIdentifier &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WatchKind implements ToJsonable {
  const WatchKind(this._value);
  const WatchKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Interested in change events
  static const Change = WatchKind(2);

  /// Interested in create events.
  static const Create = WatchKind(1);

  /// Interested in delete events
  static const Delete = WatchKind(4);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is WatchKind && other._value == _value;
}

/// The parameters sent in a will save text document notification.
class WillSaveTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WillSaveTextDocumentParams.canParse,
    WillSaveTextDocumentParams.fromJson,
  );

  WillSaveTextDocumentParams({
    required this.reason,
    required this.textDocument,
  });
  static WillSaveTextDocumentParams fromJson(Map<String, Object?> json) {
    final reasonJson = json['reason'];
    final reason = TextDocumentSaveReason.fromJson(reasonJson as int);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return WillSaveTextDocumentParams(
      reason: reason,
      textDocument: textDocument,
    );
  }

  /// The 'TextDocumentSaveReason'.
  final TextDocumentSaveReason reason;

  /// The document that will be saved.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['reason'] = reason.toJson();
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('reason');
      try {
        if (!obj.containsKey('reason')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final reason = obj['reason'];
        if (reason == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentSaveReason.canParse(reason, reporter)) {
          reporter.reportError('must be of type TextDocumentSaveReason');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WillSaveTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WillSaveTextDocumentParams &&
        other.runtimeType == WillSaveTextDocumentParams &&
        reason == other.reason &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        reason,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WindowClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WindowClientCapabilities.canParse,
    WindowClientCapabilities.fromJson,
  );

  WindowClientCapabilities({
    this.showDocument,
    this.showMessage,
    this.workDoneProgress,
  });
  static WindowClientCapabilities fromJson(Map<String, Object?> json) {
    final showDocumentJson = json['showDocument'];
    final showDocument = showDocumentJson != null
        ? ShowDocumentClientCapabilities.fromJson(
            showDocumentJson as Map<String, Object?>)
        : null;
    final showMessageJson = json['showMessage'];
    final showMessage = showMessageJson != null
        ? ShowMessageRequestClientCapabilities.fromJson(
            showMessageJson as Map<String, Object?>)
        : null;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WindowClientCapabilities(
      showDocument: showDocument,
      showMessage: showMessage,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Capabilities specific to the showDocument request.
  ///
  /// @since 3.16.0
  final ShowDocumentClientCapabilities? showDocument;

  /// Capabilities specific to the showMessage request.
  ///
  /// @since 3.16.0
  final ShowMessageRequestClientCapabilities? showMessage;

  /// It indicates whether the client supports server initiated progress using
  /// the `window/workDoneProgress/create` request.
  ///
  /// The capability also controls Whether client supports handling of progress
  /// notifications. If set servers are allowed to report a `workDoneProgress`
  /// property in the request specific server capabilities.
  ///
  /// @since 3.15.0
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (showDocument != null) {
      result['showDocument'] = showDocument?.toJson();
    }
    if (showMessage != null) {
      result['showMessage'] = showMessage?.toJson();
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('showDocument');
      try {
        final showDocument = obj['showDocument'];
        if (showDocument != null &&
            !ShowDocumentClientCapabilities.canParse(showDocument, reporter)) {
          reporter
              .reportError('must be of type ShowDocumentClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('showMessage');
      try {
        final showMessage = obj['showMessage'];
        if (showMessage != null &&
            !ShowMessageRequestClientCapabilities.canParse(
                showMessage, reporter)) {
          reporter.reportError(
              'must be of type ShowMessageRequestClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WindowClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WindowClientCapabilities &&
        other.runtimeType == WindowClientCapabilities &&
        showDocument == other.showDocument &&
        showMessage == other.showMessage &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        showDocument,
        showMessage,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressBegin implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressBegin.canParse,
    WorkDoneProgressBegin.fromJson,
  );

  WorkDoneProgressBegin({
    this.cancellable,
    this.kind = 'begin',
    this.message,
    this.percentage,
    required this.title,
  }) {
    if (kind != 'begin') {
      throw 'kind may only be the literal \'begin\'';
    }
  }
  static WorkDoneProgressBegin fromJson(Map<String, Object?> json) {
    final cancellableJson = json['cancellable'];
    final cancellable = cancellableJson as bool?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final messageJson = json['message'];
    final message = messageJson as String?;
    final percentageJson = json['percentage'];
    final percentage = percentageJson as int?;
    final titleJson = json['title'];
    final title = titleJson as String;
    return WorkDoneProgressBegin(
      cancellable: cancellable,
      kind: kind,
      message: message,
      percentage: percentage,
      title: title,
    );
  }

  /// Controls if a cancel button should show to allow the user to cancel the
  /// long running operation. Clients that don't support cancellation are
  /// allowed to ignore the setting.
  final bool? cancellable;
  final String kind;

  /// Optional, more detailed associated progress message. Contains
  /// complementary information to the `title`.
  ///
  /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". If
  /// unset, the previous progress message (if any) is still valid.
  final String? message;

  /// Optional progress percentage to display (value 100 is considered 100%). If
  /// not provided infinite progress is assumed and clients are allowed to
  /// ignore the `percentage` value in subsequent in report notifications.
  ///
  /// The value should be steadily rising. Clients are free to ignore values
  /// that are not following this rule. The value range is [0, 100].
  final int? percentage;

  /// Mandatory title of the progress operation. Used to briefly inform about
  /// the kind of operation being performed.
  ///
  /// Examples: "Indexing" or "Linking dependencies".
  final String title;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cancellable != null) {
      result['cancellable'] = cancellable;
    }
    result['kind'] = kind;
    if (message != null) {
      result['message'] = message;
    }
    if (percentage != null) {
      result['percentage'] = percentage;
    }
    result['title'] = title;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cancellable');
      try {
        final cancellable = obj['cancellable'];
        if (cancellable != null && cancellable is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'begin') {
          reporter.reportError('must be the literal \'begin\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        final message = obj['message'];
        if (message != null && message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('percentage');
      try {
        final percentage = obj['percentage'];
        if (percentage != null && percentage is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('title');
      try {
        if (!obj.containsKey('title')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final title = obj['title'];
        if (title == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (title is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressBegin');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressBegin &&
        other.runtimeType == WorkDoneProgressBegin &&
        cancellable == other.cancellable &&
        kind == other.kind &&
        message == other.message &&
        percentage == other.percentage &&
        title == other.title;
  }

  @override
  int get hashCode => Object.hash(
        cancellable,
        kind,
        message,
        percentage,
        title,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressCancelParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressCancelParams.canParse,
    WorkDoneProgressCancelParams.fromJson,
  );

  WorkDoneProgressCancelParams({
    required this.token,
  });
  static WorkDoneProgressCancelParams fromJson(Map<String, Object?> json) {
    final tokenJson = json['token'];
    final token = tokenJson is int
        ? Either2<int, String>.t1(tokenJson)
        : (tokenJson is String
            ? Either2<int, String>.t2(tokenJson)
            : (throw '''$tokenJson was not one of (int, String)'''));
    return WorkDoneProgressCancelParams(
      token: token,
    );
  }

  /// The token to be used to report progress.
  final Either2<int, String> token;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('token');
      try {
        if (!obj.containsKey('token')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final token = obj['token'];
        if (token == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (token is! int && token is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressCancelParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressCancelParams &&
        other.runtimeType == WorkDoneProgressCancelParams &&
        token == other.token;
  }

  @override
  int get hashCode => token.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressCreateParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressCreateParams.canParse,
    WorkDoneProgressCreateParams.fromJson,
  );

  WorkDoneProgressCreateParams({
    required this.token,
  });
  static WorkDoneProgressCreateParams fromJson(Map<String, Object?> json) {
    final tokenJson = json['token'];
    final token = tokenJson is int
        ? Either2<int, String>.t1(tokenJson)
        : (tokenJson is String
            ? Either2<int, String>.t2(tokenJson)
            : (throw '''$tokenJson was not one of (int, String)'''));
    return WorkDoneProgressCreateParams(
      token: token,
    );
  }

  /// The token to be used to report progress.
  final Either2<int, String> token;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('token');
      try {
        if (!obj.containsKey('token')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final token = obj['token'];
        if (token == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (token is! int && token is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressCreateParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressCreateParams &&
        other.runtimeType == WorkDoneProgressCreateParams &&
        token == other.token;
  }

  @override
  int get hashCode => token.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressEnd implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressEnd.canParse,
    WorkDoneProgressEnd.fromJson,
  );

  WorkDoneProgressEnd({
    this.kind = 'end',
    this.message,
  }) {
    if (kind != 'end') {
      throw 'kind may only be the literal \'end\'';
    }
  }
  static WorkDoneProgressEnd fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final messageJson = json['message'];
    final message = messageJson as String?;
    return WorkDoneProgressEnd(
      kind: kind,
      message: message,
    );
  }

  final String kind;

  /// Optional, a final message indicating to for example indicate the outcome
  /// of the operation.
  final String? message;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    if (message != null) {
      result['message'] = message;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'end') {
          reporter.reportError('must be the literal \'end\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        final message = obj['message'];
        if (message != null && message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressEnd');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressEnd &&
        other.runtimeType == WorkDoneProgressEnd &&
        kind == other.kind &&
        message == other.message;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        message,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressOptions.canParse,
    WorkDoneProgressOptions.fromJson,
  );

  WorkDoneProgressOptions({
    this.workDoneProgress,
  });
  static WorkDoneProgressOptions fromJson(Map<String, Object?> json) {
    if (DiagnosticOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticOptions.fromJson(json);
    }
    if (SemanticTokensOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensOptions.fromJson(json);
    }
    if (ExecuteCommandOptions.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandOptions.fromJson(json);
    }
    if (CompletionOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionOptions.fromJson(json);
    }
    if (CodeActionOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionOptions.fromJson(json);
    }
    if (SignatureHelpOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpOptions.fromJson(json);
    }
    if (CodeLensOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensOptions.fromJson(json);
    }
    if (DocumentLinkOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkOptions.fromJson(json);
    }
    if (DocumentSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolOptions.fromJson(json);
    }
    if (InlayHintOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintOptions.fromJson(json);
    }
    if (RenameOptions.canParse(json, nullLspJsonReporter)) {
      return RenameOptions.fromJson(json);
    }
    if (WorkspaceSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolOptions.fromJson(json);
    }
    if (CallHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOptions.fromJson(json);
    }
    if (DeclarationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationOptions.fromJson(json);
    }
    if (DefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionOptions.fromJson(json);
    }
    if (DocumentColorOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorOptions.fromJson(json);
    }
    if (DocumentFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingOptions.fromJson(json);
    }
    if (DocumentHighlightOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightOptions.fromJson(json);
    }
    if (DocumentRangeFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingOptions.fromJson(json);
    }
    if (FoldingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeOptions.fromJson(json);
    }
    if (HoverOptions.canParse(json, nullLspJsonReporter)) {
      return HoverOptions.fromJson(json);
    }
    if (ImplementationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationOptions.fromJson(json);
    }
    if (InlineValueOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueOptions.fromJson(json);
    }
    if (LinkedEditingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeOptions.fromJson(json);
    }
    if (MonikerOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerOptions.fromJson(json);
    }
    if (ReferenceOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceOptions.fromJson(json);
    }
    if (SelectionRangeOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeOptions.fromJson(json);
    }
    if (TypeDefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionOptions.fromJson(json);
    }
    if (TypeHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkDoneProgressOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressOptions &&
        other.runtimeType == WorkDoneProgressOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressParams.canParse,
    WorkDoneProgressParams.fromJson,
  );

  WorkDoneProgressParams({
    this.workDoneToken,
  });
  static WorkDoneProgressParams fromJson(Map<String, Object?> json) {
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (DocumentRangeFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingParams.fromJson(json);
    }
    if (InlineValueParams.canParse(json, nullLspJsonReporter)) {
      return InlineValueParams.fromJson(json);
    }
    if (RenameParams.canParse(json, nullLspJsonReporter)) {
      return RenameParams.fromJson(json);
    }
    if (DocumentFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingParams.fromJson(json);
    }
    if (InlayHintParams.canParse(json, nullLspJsonReporter)) {
      return InlayHintParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (InitializeParams.canParse(json, nullLspJsonReporter)) {
      return InitializeParams.fromJson(json);
    }
    if (DocumentDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return DocumentDiagnosticParams.fromJson(json);
    }
    if (ExecuteCommandParams.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandParams.fromJson(json);
    }
    if (WorkspaceDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceDiagnosticParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (TypeHierarchySubtypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySubtypesParams.fromJson(json);
    }
    if (TypeHierarchySupertypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySupertypesParams.fromJson(json);
    }
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
      return PrepareRenameParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (TypeHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyPrepareParams.fromJson(json);
    }
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return WorkDoneProgressParams(
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report work done progress.
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressParams &&
        other.runtimeType == WorkDoneProgressParams &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => workDoneToken.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressReport.canParse,
    WorkDoneProgressReport.fromJson,
  );

  WorkDoneProgressReport({
    this.cancellable,
    this.kind = 'report',
    this.message,
    this.percentage,
  }) {
    if (kind != 'report') {
      throw 'kind may only be the literal \'report\'';
    }
  }
  static WorkDoneProgressReport fromJson(Map<String, Object?> json) {
    final cancellableJson = json['cancellable'];
    final cancellable = cancellableJson as bool?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final messageJson = json['message'];
    final message = messageJson as String?;
    final percentageJson = json['percentage'];
    final percentage = percentageJson as int?;
    return WorkDoneProgressReport(
      cancellable: cancellable,
      kind: kind,
      message: message,
      percentage: percentage,
    );
  }

  /// Controls enablement state of a cancel button.
  ///
  /// Clients that don't support cancellation or don't support controlling the
  /// button's enablement state are allowed to ignore the property.
  final bool? cancellable;
  final String kind;

  /// Optional, more detailed associated progress message. Contains
  /// complementary information to the `title`.
  ///
  /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". If
  /// unset, the previous progress message (if any) is still valid.
  final String? message;

  /// Optional progress percentage to display (value 100 is considered 100%). If
  /// not provided infinite progress is assumed and clients are allowed to
  /// ignore the `percentage` value in subsequent in report notifications.
  ///
  /// The value should be steadily rising. Clients are free to ignore values
  /// that are not following this rule. The value range is [0, 100]
  final int? percentage;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cancellable != null) {
      result['cancellable'] = cancellable;
    }
    result['kind'] = kind;
    if (message != null) {
      result['message'] = message;
    }
    if (percentage != null) {
      result['percentage'] = percentage;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cancellable');
      try {
        final cancellable = obj['cancellable'];
        if (cancellable != null && cancellable is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'report') {
          reporter.reportError('must be the literal \'report\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        final message = obj['message'];
        if (message != null && message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('percentage');
      try {
        final percentage = obj['percentage'];
        if (percentage != null && percentage is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressReport &&
        other.runtimeType == WorkDoneProgressReport &&
        cancellable == other.cancellable &&
        kind == other.kind &&
        message == other.message &&
        percentage == other.percentage;
  }

  @override
  int get hashCode => Object.hash(
        cancellable,
        kind,
        message,
        percentage,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Workspace specific client capabilities.
class WorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceClientCapabilities.canParse,
    WorkspaceClientCapabilities.fromJson,
  );

  WorkspaceClientCapabilities({
    this.applyEdit,
    this.codeLens,
    this.configuration,
    this.diagnostics,
    this.didChangeConfiguration,
    this.didChangeWatchedFiles,
    this.executeCommand,
    this.fileOperations,
    this.inlayHint,
    this.inlineValue,
    this.semanticTokens,
    this.symbol,
    this.workspaceEdit,
    this.workspaceFolders,
  });
  static WorkspaceClientCapabilities fromJson(Map<String, Object?> json) {
    final applyEditJson = json['applyEdit'];
    final applyEdit = applyEditJson as bool?;
    final codeLensJson = json['codeLens'];
    final codeLens = codeLensJson != null
        ? CodeLensWorkspaceClientCapabilities.fromJson(
            codeLensJson as Map<String, Object?>)
        : null;
    final configurationJson = json['configuration'];
    final configuration = configurationJson as bool?;
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = diagnosticsJson != null
        ? DiagnosticWorkspaceClientCapabilities.fromJson(
            diagnosticsJson as Map<String, Object?>)
        : null;
    final didChangeConfigurationJson = json['didChangeConfiguration'];
    final didChangeConfiguration = didChangeConfigurationJson != null
        ? DidChangeConfigurationClientCapabilities.fromJson(
            didChangeConfigurationJson as Map<String, Object?>)
        : null;
    final didChangeWatchedFilesJson = json['didChangeWatchedFiles'];
    final didChangeWatchedFiles = didChangeWatchedFilesJson != null
        ? DidChangeWatchedFilesClientCapabilities.fromJson(
            didChangeWatchedFilesJson as Map<String, Object?>)
        : null;
    final executeCommandJson = json['executeCommand'];
    final executeCommand = executeCommandJson != null
        ? ExecuteCommandClientCapabilities.fromJson(
            executeCommandJson as Map<String, Object?>)
        : null;
    final fileOperationsJson = json['fileOperations'];
    final fileOperations = fileOperationsJson != null
        ? FileOperationClientCapabilities.fromJson(
            fileOperationsJson as Map<String, Object?>)
        : null;
    final inlayHintJson = json['inlayHint'];
    final inlayHint = inlayHintJson != null
        ? InlayHintWorkspaceClientCapabilities.fromJson(
            inlayHintJson as Map<String, Object?>)
        : null;
    final inlineValueJson = json['inlineValue'];
    final inlineValue = inlineValueJson != null
        ? InlineValueWorkspaceClientCapabilities.fromJson(
            inlineValueJson as Map<String, Object?>)
        : null;
    final semanticTokensJson = json['semanticTokens'];
    final semanticTokens = semanticTokensJson != null
        ? SemanticTokensWorkspaceClientCapabilities.fromJson(
            semanticTokensJson as Map<String, Object?>)
        : null;
    final symbolJson = json['symbol'];
    final symbol = symbolJson != null
        ? WorkspaceSymbolClientCapabilities.fromJson(
            symbolJson as Map<String, Object?>)
        : null;
    final workspaceEditJson = json['workspaceEdit'];
    final workspaceEdit = workspaceEditJson != null
        ? WorkspaceEditClientCapabilities.fromJson(
            workspaceEditJson as Map<String, Object?>)
        : null;
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = workspaceFoldersJson as bool?;
    return WorkspaceClientCapabilities(
      applyEdit: applyEdit,
      codeLens: codeLens,
      configuration: configuration,
      diagnostics: diagnostics,
      didChangeConfiguration: didChangeConfiguration,
      didChangeWatchedFiles: didChangeWatchedFiles,
      executeCommand: executeCommand,
      fileOperations: fileOperations,
      inlayHint: inlayHint,
      inlineValue: inlineValue,
      semanticTokens: semanticTokens,
      symbol: symbol,
      workspaceEdit: workspaceEdit,
      workspaceFolders: workspaceFolders,
    );
  }

  /// The client supports applying batch edits to the workspace by supporting
  /// the request
  /// 'workspace/applyEdit'
  final bool? applyEdit;

  /// Capabilities specific to the code lens requests scoped to the workspace.
  ///
  /// @since 3.16.0.
  final CodeLensWorkspaceClientCapabilities? codeLens;

  /// The client supports `workspace/configuration` requests.
  ///
  /// @since 3.6.0
  final bool? configuration;

  /// Capabilities specific to the diagnostic requests scoped to the workspace.
  ///
  /// @since 3.17.0.
  final DiagnosticWorkspaceClientCapabilities? diagnostics;

  /// Capabilities specific to the `workspace/didChangeConfiguration`
  /// notification.
  final DidChangeConfigurationClientCapabilities? didChangeConfiguration;

  /// Capabilities specific to the `workspace/didChangeWatchedFiles`
  /// notification.
  final DidChangeWatchedFilesClientCapabilities? didChangeWatchedFiles;

  /// Capabilities specific to the `workspace/executeCommand` request.
  final ExecuteCommandClientCapabilities? executeCommand;

  /// The client has support for file notifications/requests for user operations
  /// on files.
  ///
  /// Since 3.16.0
  final FileOperationClientCapabilities? fileOperations;

  /// Capabilities specific to the inlay hint requests scoped to the workspace.
  ///
  /// @since 3.17.0.
  final InlayHintWorkspaceClientCapabilities? inlayHint;

  /// Capabilities specific to the inline values requests scoped to the
  /// workspace.
  ///
  /// @since 3.17.0.
  final InlineValueWorkspaceClientCapabilities? inlineValue;

  /// Capabilities specific to the semantic token requests scoped to the
  /// workspace.
  ///
  /// @since 3.16.0.
  final SemanticTokensWorkspaceClientCapabilities? semanticTokens;

  /// Capabilities specific to the `workspace/symbol` request.
  final WorkspaceSymbolClientCapabilities? symbol;

  /// Capabilities specific to `WorkspaceEdit`s.
  final WorkspaceEditClientCapabilities? workspaceEdit;

  /// The client has support for workspace folders.
  ///
  /// @since 3.6.0
  final bool? workspaceFolders;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (applyEdit != null) {
      result['applyEdit'] = applyEdit;
    }
    if (codeLens != null) {
      result['codeLens'] = codeLens?.toJson();
    }
    if (configuration != null) {
      result['configuration'] = configuration;
    }
    if (diagnostics != null) {
      result['diagnostics'] = diagnostics?.toJson();
    }
    if (didChangeConfiguration != null) {
      result['didChangeConfiguration'] = didChangeConfiguration?.toJson();
    }
    if (didChangeWatchedFiles != null) {
      result['didChangeWatchedFiles'] = didChangeWatchedFiles?.toJson();
    }
    if (executeCommand != null) {
      result['executeCommand'] = executeCommand?.toJson();
    }
    if (fileOperations != null) {
      result['fileOperations'] = fileOperations?.toJson();
    }
    if (inlayHint != null) {
      result['inlayHint'] = inlayHint?.toJson();
    }
    if (inlineValue != null) {
      result['inlineValue'] = inlineValue?.toJson();
    }
    if (semanticTokens != null) {
      result['semanticTokens'] = semanticTokens?.toJson();
    }
    if (symbol != null) {
      result['symbol'] = symbol?.toJson();
    }
    if (workspaceEdit != null) {
      result['workspaceEdit'] = workspaceEdit?.toJson();
    }
    if (workspaceFolders != null) {
      result['workspaceFolders'] = workspaceFolders;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('applyEdit');
      try {
        final applyEdit = obj['applyEdit'];
        if (applyEdit != null && applyEdit is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeLens');
      try {
        final codeLens = obj['codeLens'];
        if (codeLens != null &&
            !CodeLensWorkspaceClientCapabilities.canParse(codeLens, reporter)) {
          reporter.reportError(
              'must be of type CodeLensWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('configuration');
      try {
        final configuration = obj['configuration'];
        if (configuration != null && configuration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('diagnostics');
      try {
        final diagnostics = obj['diagnostics'];
        if (diagnostics != null &&
            !DiagnosticWorkspaceClientCapabilities.canParse(
                diagnostics, reporter)) {
          reporter.reportError(
              'must be of type DiagnosticWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didChangeConfiguration');
      try {
        final didChangeConfiguration = obj['didChangeConfiguration'];
        if (didChangeConfiguration != null &&
            !DidChangeConfigurationClientCapabilities.canParse(
                didChangeConfiguration, reporter)) {
          reporter.reportError(
              'must be of type DidChangeConfigurationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didChangeWatchedFiles');
      try {
        final didChangeWatchedFiles = obj['didChangeWatchedFiles'];
        if (didChangeWatchedFiles != null &&
            !DidChangeWatchedFilesClientCapabilities.canParse(
                didChangeWatchedFiles, reporter)) {
          reporter.reportError(
              'must be of type DidChangeWatchedFilesClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executeCommand');
      try {
        final executeCommand = obj['executeCommand'];
        if (executeCommand != null &&
            !ExecuteCommandClientCapabilities.canParse(
                executeCommand, reporter)) {
          reporter
              .reportError('must be of type ExecuteCommandClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('fileOperations');
      try {
        final fileOperations = obj['fileOperations'];
        if (fileOperations != null &&
            !FileOperationClientCapabilities.canParse(
                fileOperations, reporter)) {
          reporter
              .reportError('must be of type FileOperationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlayHint');
      try {
        final inlayHint = obj['inlayHint'];
        if (inlayHint != null &&
            !InlayHintWorkspaceClientCapabilities.canParse(
                inlayHint, reporter)) {
          reporter.reportError(
              'must be of type InlayHintWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlineValue');
      try {
        final inlineValue = obj['inlineValue'];
        if (inlineValue != null &&
            !InlineValueWorkspaceClientCapabilities.canParse(
                inlineValue, reporter)) {
          reporter.reportError(
              'must be of type InlineValueWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('semanticTokens');
      try {
        final semanticTokens = obj['semanticTokens'];
        if (semanticTokens != null &&
            !SemanticTokensWorkspaceClientCapabilities.canParse(
                semanticTokens, reporter)) {
          reporter.reportError(
              'must be of type SemanticTokensWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('symbol');
      try {
        final symbol = obj['symbol'];
        if (symbol != null &&
            !WorkspaceSymbolClientCapabilities.canParse(symbol, reporter)) {
          reporter
              .reportError('must be of type WorkspaceSymbolClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceEdit');
      try {
        final workspaceEdit = obj['workspaceEdit'];
        if (workspaceEdit != null &&
            !WorkspaceEditClientCapabilities.canParse(
                workspaceEdit, reporter)) {
          reporter
              .reportError('must be of type WorkspaceEditClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceFolders');
      try {
        final workspaceFolders = obj['workspaceFolders'];
        if (workspaceFolders != null && workspaceFolders is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceClientCapabilities &&
        other.runtimeType == WorkspaceClientCapabilities &&
        applyEdit == other.applyEdit &&
        codeLens == other.codeLens &&
        configuration == other.configuration &&
        diagnostics == other.diagnostics &&
        didChangeConfiguration == other.didChangeConfiguration &&
        didChangeWatchedFiles == other.didChangeWatchedFiles &&
        executeCommand == other.executeCommand &&
        fileOperations == other.fileOperations &&
        inlayHint == other.inlayHint &&
        inlineValue == other.inlineValue &&
        semanticTokens == other.semanticTokens &&
        symbol == other.symbol &&
        workspaceEdit == other.workspaceEdit &&
        workspaceFolders == other.workspaceFolders;
  }

  @override
  int get hashCode => Object.hash(
        applyEdit,
        codeLens,
        configuration,
        diagnostics,
        didChangeConfiguration,
        didChangeWatchedFiles,
        executeCommand,
        fileOperations,
        inlayHint,
        inlineValue,
        semanticTokens,
        symbol,
        workspaceEdit,
        workspaceFolders,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters of the workspace diagnostic request.
///
/// @since 3.17.0
class WorkspaceDiagnosticParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceDiagnosticParams.canParse,
    WorkspaceDiagnosticParams.fromJson,
  );

  WorkspaceDiagnosticParams({
    this.identifier,
    this.partialResultToken,
    required this.previousResultIds,
    this.workDoneToken,
  });
  static WorkspaceDiagnosticParams fromJson(Map<String, Object?> json) {
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String?;
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final previousResultIdsJson = json['previousResultIds'];
    final previousResultIds = (previousResultIdsJson as List<Object?>)
        .map((item) => PreviousResultId.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return WorkspaceDiagnosticParams(
      identifier: identifier,
      partialResultToken: partialResultToken,
      previousResultIds: previousResultIds,
      workDoneToken: workDoneToken,
    );
  }

  /// The additional identifier provided during registration.
  final String? identifier;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The currently known diagnostic reports with their previous result ids.
  final List<PreviousResultId> previousResultIds;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (identifier != null) {
      result['identifier'] = identifier;
    }
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['previousResultIds'] =
        previousResultIds.map((item) => item.toJson()).toList();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('identifier');
      try {
        final identifier = obj['identifier'];
        if (identifier != null && identifier is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('previousResultIds');
      try {
        if (!obj.containsKey('previousResultIds')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final previousResultIds = obj['previousResultIds'];
        if (previousResultIds == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (previousResultIds is! List<Object?> ||
            previousResultIds
                .any((item) => !PreviousResultId.canParse(item, reporter))) {
          reporter.reportError('must be of type List<PreviousResultId>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceDiagnosticParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceDiagnosticParams &&
        other.runtimeType == WorkspaceDiagnosticParams &&
        identifier == other.identifier &&
        partialResultToken == other.partialResultToken &&
        listEqual(previousResultIds, other.previousResultIds,
            (PreviousResultId a, PreviousResultId b) => a == b) &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        identifier,
        partialResultToken,
        lspHashCode(previousResultIds),
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A workspace diagnostic report.
///
/// @since 3.17.0
class WorkspaceDiagnosticReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceDiagnosticReport.canParse,
    WorkspaceDiagnosticReport.fromJson,
  );

  WorkspaceDiagnosticReport({
    required this.items,
  });
  static WorkspaceDiagnosticReport fromJson(Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => WorkspaceFullDocumentDiagnosticReport.canParse(
                item, nullLspJsonReporter)
            ? Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>.t1(
                WorkspaceFullDocumentDiagnosticReport.fromJson(
                    item as Map<String, Object?>))
            : (WorkspaceUnchangedDocumentDiagnosticReport.canParse(
                    item, nullLspJsonReporter)
                ? Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>.t2(
                    WorkspaceUnchangedDocumentDiagnosticReport.fromJson(
                        item as Map<String, Object?>))
                : (throw '''$item was not one of (WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport)''')))
        .toList();
    return WorkspaceDiagnosticReport(
      items: items,
    );
  }

  final List<
      Either2<WorkspaceFullDocumentDiagnosticReport,
          WorkspaceUnchangedDocumentDiagnosticReport>> items;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) =>
                !WorkspaceFullDocumentDiagnosticReport.canParse(
                    item, reporter) &&
                !WorkspaceUnchangedDocumentDiagnosticReport.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceDiagnosticReport &&
        other.runtimeType == WorkspaceDiagnosticReport &&
        listEqual(
            items,
            other.items,
            (Either2<WorkspaceFullDocumentDiagnosticReport,
                            WorkspaceUnchangedDocumentDiagnosticReport>
                        a,
                    Either2<WorkspaceFullDocumentDiagnosticReport,
                            WorkspaceUnchangedDocumentDiagnosticReport>
                        b) =>
                a == b);
  }

  @override
  int get hashCode => lspHashCode(items);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A partial result for a workspace diagnostic report.
///
/// @since 3.17.0
class WorkspaceDiagnosticReportPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceDiagnosticReportPartialResult.canParse,
    WorkspaceDiagnosticReportPartialResult.fromJson,
  );

  WorkspaceDiagnosticReportPartialResult({
    required this.items,
  });
  static WorkspaceDiagnosticReportPartialResult fromJson(
      Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => WorkspaceFullDocumentDiagnosticReport.canParse(
                item, nullLspJsonReporter)
            ? Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>.t1(
                WorkspaceFullDocumentDiagnosticReport.fromJson(
                    item as Map<String, Object?>))
            : (WorkspaceUnchangedDocumentDiagnosticReport.canParse(
                    item, nullLspJsonReporter)
                ? Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>.t2(
                    WorkspaceUnchangedDocumentDiagnosticReport.fromJson(
                        item as Map<String, Object?>))
                : (throw '''$item was not one of (WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport)''')))
        .toList();
    return WorkspaceDiagnosticReportPartialResult(
      items: items,
    );
  }

  final List<
      Either2<WorkspaceFullDocumentDiagnosticReport,
          WorkspaceUnchangedDocumentDiagnosticReport>> items;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) =>
                !WorkspaceFullDocumentDiagnosticReport.canParse(
                    item, reporter) &&
                !WorkspaceUnchangedDocumentDiagnosticReport.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceDiagnosticReportPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceDiagnosticReportPartialResult &&
        other.runtimeType == WorkspaceDiagnosticReportPartialResult &&
        listEqual(
            items,
            other.items,
            (Either2<WorkspaceFullDocumentDiagnosticReport,
                            WorkspaceUnchangedDocumentDiagnosticReport>
                        a,
                    Either2<WorkspaceFullDocumentDiagnosticReport,
                            WorkspaceUnchangedDocumentDiagnosticReport>
                        b) =>
                a == b);
  }

  @override
  int get hashCode => lspHashCode(items);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A workspace edit represents changes to many resources managed in the
/// workspace. The edit should either provide `changes` or `documentChanges`. If
/// documentChanges are present they are preferred over `changes` if the client
/// can handle versioned document edits.
///
/// Since version 3.13.0 a workspace edit can contain resource operations as
/// well. If resource operations are present clients need to execute the
/// operations in the order in which they are provided. So a workspace edit for
/// example can consist of the following two changes:
/// (1) a create file a.txt and (2) a text document edit which insert text into
/// file a.txt.
///
/// An invalid sequence (e.g. (1) delete file a.txt and (2) insert text into
/// file a.txt) will cause failure of the operation. How the client recovers
/// from the failure is described by the client capability:
/// `workspace.workspaceEdit.failureHandling`
class WorkspaceEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceEdit.canParse,
    WorkspaceEdit.fromJson,
  );

  WorkspaceEdit({
    this.changeAnnotations,
    this.changes,
    this.documentChanges,
  });
  static WorkspaceEdit fromJson(Map<String, Object?> json) {
    final changeAnnotationsJson = json['changeAnnotations'];
    final changeAnnotations = (changeAnnotationsJson as Map<Object, Object?>?)
        ?.map((key, value) => MapEntry(key as String,
            ChangeAnnotation.fromJson(value as Map<String, Object?>)));
    final changesJson = json['changes'];
    final changes = (changesJson as Map<Object, Object?>?)?.map((key, value) =>
        MapEntry(
            key as String,
            (value as List<Object?>)
                .map((item) => TextEdit.fromJson(item as Map<String, Object?>))
                .toList()));
    final documentChangesJson = json['documentChanges'];
    final documentChanges = (documentChangesJson as List<Object?>?)
        ?.map((item) => CreateFile.canParse(item, nullLspJsonReporter)
            ? Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>.t1(
                CreateFile.fromJson(item as Map<String, Object?>))
            : (DeleteFile.canParse(item, nullLspJsonReporter)
                ? Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>.t2(
                    DeleteFile.fromJson(item as Map<String, Object?>))
                : (RenameFile.canParse(item, nullLspJsonReporter)
                    ? Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>.t3(
                        RenameFile.fromJson(item as Map<String, Object?>))
                    : (TextDocumentEdit.canParse(item, nullLspJsonReporter)
                        ? Either4<CreateFile, DeleteFile, RenameFile,
                                TextDocumentEdit>.t4(
                            TextDocumentEdit.fromJson(item as Map<String, Object?>))
                        : (throw '''$item was not one of (CreateFile, DeleteFile, RenameFile, TextDocumentEdit)''')))))
        .toList();
    return WorkspaceEdit(
      changeAnnotations: changeAnnotations,
      changes: changes,
      documentChanges: documentChanges,
    );
  }

  /// A map of change annotations that can be referenced in `AnnotatedTextEdit`s
  /// or create, rename and delete file / folder operations.
  ///
  /// Whether clients honor this property depends on the client capability
  /// `workspace.changeAnnotationSupport`.
  ///
  /// @since 3.16.0
  final Map<String, ChangeAnnotation>? changeAnnotations;

  /// Holds changes to existing resources.
  final Map<String, List<TextEdit>>? changes;

  /// Depending on the client capability
  /// `workspace.workspaceEdit.resourceOperations` document changes are either
  /// an array of `TextDocumentEdit`s to express changes to n different text
  /// documents where each text document edit addresses a specific version of a
  /// text document. Or it can contain above `TextDocumentEdit`s mixed with
  /// create, rename and delete file / folder operations.
  ///
  /// Whether a client supports versioned document edits is expressed via
  /// `workspace.workspaceEdit.documentChanges` client capability.
  ///
  /// If a client neither supports `documentChanges` nor
  /// `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s
  /// using the `changes` property are supported.
  final List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>?
      documentChanges;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (changeAnnotations != null) {
      result['changeAnnotations'] = changeAnnotations;
    }
    if (changes != null) {
      result['changes'] = changes;
    }
    if (documentChanges != null) {
      result['documentChanges'] = documentChanges;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('changeAnnotations');
      try {
        final changeAnnotations = obj['changeAnnotations'];
        if (changeAnnotations != null &&
            (changeAnnotations is! Map ||
                (changeAnnotations.keys.any((item) =>
                    item is! String ||
                    changeAnnotations.values.any((item) =>
                        !ChangeAnnotation.canParse(item, reporter)))))) {
          reporter.reportError('must be of type Map<String, ChangeAnnotation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('changes');
      try {
        final changes = obj['changes'];
        if (changes != null &&
            (changes is! Map ||
                (changes.keys.any((item) =>
                    item is! String ||
                    changes.values.any((item) =>
                        item is! List<Object?> ||
                        item.any(
                            (item) => !TextEdit.canParse(item, reporter))))))) {
          reporter.reportError('must be of type Map<String, List<TextEdit>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentChanges');
      try {
        final documentChanges = obj['documentChanges'];
        if (documentChanges != null &&
            (documentChanges is! List<Object?> ||
                documentChanges.any((item) =>
                    !CreateFile.canParse(item, reporter) &&
                    !DeleteFile.canParse(item, reporter) &&
                    !RenameFile.canParse(item, reporter) &&
                    !TextDocumentEdit.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceEdit &&
        other.runtimeType == WorkspaceEdit &&
        mapEqual(changeAnnotations, other.changeAnnotations,
            (ChangeAnnotation a, ChangeAnnotation b) => a == b) &&
        mapEqual(
            changes,
            other.changes,
            (List<TextEdit> a, List<TextEdit> b) =>
                listEqual(a, b, (TextEdit a, TextEdit b) => a == b)) &&
        listEqual(
            documentChanges,
            other.documentChanges,
            (Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit> a,
                    Either4<CreateFile, DeleteFile, RenameFile,
                            TextDocumentEdit>
                        b) =>
                a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(changeAnnotations),
        lspHashCode(changes),
        lspHashCode(documentChanges),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceEditClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceEditClientCapabilities.canParse,
    WorkspaceEditClientCapabilities.fromJson,
  );

  WorkspaceEditClientCapabilities({
    this.changeAnnotationSupport,
    this.documentChanges,
    this.failureHandling,
    this.normalizesLineEndings,
    this.resourceOperations,
  });
  static WorkspaceEditClientCapabilities fromJson(Map<String, Object?> json) {
    final changeAnnotationSupportJson = json['changeAnnotationSupport'];
    final changeAnnotationSupport = changeAnnotationSupportJson != null
        ? WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson(
            changeAnnotationSupportJson as Map<String, Object?>)
        : null;
    final documentChangesJson = json['documentChanges'];
    final documentChanges = documentChangesJson as bool?;
    final failureHandlingJson = json['failureHandling'];
    final failureHandling = failureHandlingJson != null
        ? FailureHandlingKind.fromJson(failureHandlingJson as String)
        : null;
    final normalizesLineEndingsJson = json['normalizesLineEndings'];
    final normalizesLineEndings = normalizesLineEndingsJson as bool?;
    final resourceOperationsJson = json['resourceOperations'];
    final resourceOperations = (resourceOperationsJson as List<Object?>?)
        ?.map((item) => ResourceOperationKind.fromJson(item as String))
        .toList();
    return WorkspaceEditClientCapabilities(
      changeAnnotationSupport: changeAnnotationSupport,
      documentChanges: documentChanges,
      failureHandling: failureHandling,
      normalizesLineEndings: normalizesLineEndings,
      resourceOperations: resourceOperations,
    );
  }

  /// Whether the client in general supports change annotations on text edits,
  /// create file, rename file and delete file changes.
  ///
  /// @since 3.16.0
  final WorkspaceEditClientCapabilitiesChangeAnnotationSupport?
      changeAnnotationSupport;

  /// The client supports versioned document changes in `WorkspaceEdit`s
  final bool? documentChanges;

  /// The failure handling strategy of a client if applying the workspace edit
  /// fails.
  ///
  /// @since 3.13.0
  final FailureHandlingKind? failureHandling;

  /// Whether the client normalizes line endings to the client specific setting.
  /// If set to `true` the client will normalize line ending characters in a
  /// workspace edit to the client-specified new line character.
  ///
  /// @since 3.16.0
  final bool? normalizesLineEndings;

  /// The resource operations the client supports. Clients should at least
  /// support 'create', 'rename' and 'delete' files and folders.
  ///
  /// @since 3.13.0
  final List<ResourceOperationKind>? resourceOperations;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (changeAnnotationSupport != null) {
      result['changeAnnotationSupport'] = changeAnnotationSupport?.toJson();
    }
    if (documentChanges != null) {
      result['documentChanges'] = documentChanges;
    }
    if (failureHandling != null) {
      result['failureHandling'] = failureHandling?.toJson();
    }
    if (normalizesLineEndings != null) {
      result['normalizesLineEndings'] = normalizesLineEndings;
    }
    if (resourceOperations != null) {
      result['resourceOperations'] =
          resourceOperations?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('changeAnnotationSupport');
      try {
        final changeAnnotationSupport = obj['changeAnnotationSupport'];
        if (changeAnnotationSupport != null &&
            !WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse(
                changeAnnotationSupport, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentChanges');
      try {
        final documentChanges = obj['documentChanges'];
        if (documentChanges != null && documentChanges is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('failureHandling');
      try {
        final failureHandling = obj['failureHandling'];
        if (failureHandling != null &&
            !FailureHandlingKind.canParse(failureHandling, reporter)) {
          reporter.reportError('must be of type FailureHandlingKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('normalizesLineEndings');
      try {
        final normalizesLineEndings = obj['normalizesLineEndings'];
        if (normalizesLineEndings != null && normalizesLineEndings is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resourceOperations');
      try {
        final resourceOperations = obj['resourceOperations'];
        if (resourceOperations != null &&
            (resourceOperations is! List<Object?> ||
                resourceOperations.any((item) =>
                    !ResourceOperationKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<ResourceOperationKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceEditClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceEditClientCapabilities &&
        other.runtimeType == WorkspaceEditClientCapabilities &&
        changeAnnotationSupport == other.changeAnnotationSupport &&
        documentChanges == other.documentChanges &&
        failureHandling == other.failureHandling &&
        normalizesLineEndings == other.normalizesLineEndings &&
        listEqual(resourceOperations, other.resourceOperations,
            (ResourceOperationKind a, ResourceOperationKind b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        changeAnnotationSupport,
        documentChanges,
        failureHandling,
        normalizesLineEndings,
        lspHashCode(resourceOperations),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceEditClientCapabilitiesChangeAnnotationSupport
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse,
    WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson,
  );

  WorkspaceEditClientCapabilitiesChangeAnnotationSupport({
    this.groupsOnLabel,
  });
  static WorkspaceEditClientCapabilitiesChangeAnnotationSupport fromJson(
      Map<String, Object?> json) {
    final groupsOnLabelJson = json['groupsOnLabel'];
    final groupsOnLabel = groupsOnLabelJson as bool?;
    return WorkspaceEditClientCapabilitiesChangeAnnotationSupport(
      groupsOnLabel: groupsOnLabel,
    );
  }

  /// Whether the client groups edits with equal labels into tree nodes,
  /// for instance all edits labelled with "Changes in Strings" would be a tree
  /// node.
  final bool? groupsOnLabel;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (groupsOnLabel != null) {
      result['groupsOnLabel'] = groupsOnLabel;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('groupsOnLabel');
      try {
        final groupsOnLabel = obj['groupsOnLabel'];
        if (groupsOnLabel != null && groupsOnLabel is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceEditClientCapabilitiesChangeAnnotationSupport &&
        other.runtimeType ==
            WorkspaceEditClientCapabilitiesChangeAnnotationSupport &&
        groupsOnLabel == other.groupsOnLabel;
  }

  @override
  int get hashCode => groupsOnLabel.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A workspace folder inside a client.
class WorkspaceFolder implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFolder.canParse,
    WorkspaceFolder.fromJson,
  );

  WorkspaceFolder({
    required this.name,
    required this.uri,
  });
  static WorkspaceFolder fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return WorkspaceFolder(
      name: name,
      uri: uri,
    );
  }

  /// The name of the workspace folder. Used to refer to this workspace folder
  /// in the user interface.
  final String name;

  /// The associated URI for this workspace folder.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['name'] = name;
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceFolder');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceFolder &&
        other.runtimeType == WorkspaceFolder &&
        name == other.name &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        name,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The workspace folder change event.
class WorkspaceFoldersChangeEvent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFoldersChangeEvent.canParse,
    WorkspaceFoldersChangeEvent.fromJson,
  );

  WorkspaceFoldersChangeEvent({
    required this.added,
    required this.removed,
  });
  static WorkspaceFoldersChangeEvent fromJson(Map<String, Object?> json) {
    final addedJson = json['added'];
    final added = (addedJson as List<Object?>)
        .map((item) => WorkspaceFolder.fromJson(item as Map<String, Object?>))
        .toList();
    final removedJson = json['removed'];
    final removed = (removedJson as List<Object?>)
        .map((item) => WorkspaceFolder.fromJson(item as Map<String, Object?>))
        .toList();
    return WorkspaceFoldersChangeEvent(
      added: added,
      removed: removed,
    );
  }

  /// The array of added workspace folders
  final List<WorkspaceFolder> added;

  /// The array of the removed workspace folders
  final List<WorkspaceFolder> removed;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['added'] = added.map((item) => item.toJson()).toList();
    result['removed'] = removed.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('added');
      try {
        if (!obj.containsKey('added')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final added = obj['added'];
        if (added == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (added is! List<Object?> ||
            added.any((item) => !WorkspaceFolder.canParse(item, reporter))) {
          reporter.reportError('must be of type List<WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('removed');
      try {
        if (!obj.containsKey('removed')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final removed = obj['removed'];
        if (removed == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (removed is! List<Object?> ||
            removed.any((item) => !WorkspaceFolder.canParse(item, reporter))) {
          reporter.reportError('must be of type List<WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceFoldersChangeEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceFoldersChangeEvent &&
        other.runtimeType == WorkspaceFoldersChangeEvent &&
        listEqual(added, other.added,
            (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
        listEqual(removed, other.removed,
            (WorkspaceFolder a, WorkspaceFolder b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(added),
        lspHashCode(removed),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceFoldersServerCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFoldersServerCapabilities.canParse,
    WorkspaceFoldersServerCapabilities.fromJson,
  );

  WorkspaceFoldersServerCapabilities({
    this.changeNotifications,
    this.supported,
  });
  static WorkspaceFoldersServerCapabilities fromJson(
      Map<String, Object?> json) {
    final changeNotificationsJson = json['changeNotifications'];
    final changeNotifications = changeNotificationsJson == null
        ? null
        : (changeNotificationsJson is bool
            ? Either2<bool, String>.t1(changeNotificationsJson)
            : (changeNotificationsJson is String
                ? Either2<bool, String>.t2(changeNotificationsJson)
                : (throw '''$changeNotificationsJson was not one of (bool, String)''')));
    final supportedJson = json['supported'];
    final supported = supportedJson as bool?;
    return WorkspaceFoldersServerCapabilities(
      changeNotifications: changeNotifications,
      supported: supported,
    );
  }

  /// Whether the server wants to receive workspace folder change notifications.
  ///
  /// If a string is provided the string is treated as an ID under which the
  /// notification is registered on the client side. The ID can be used to
  /// unregister for these events using the `client/unregisterCapability`
  /// request.
  final Either2<bool, String>? changeNotifications;

  /// The server has support for workspace folders
  final bool? supported;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (changeNotifications != null) {
      result['changeNotifications'] = changeNotifications;
    }
    if (supported != null) {
      result['supported'] = supported;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('changeNotifications');
      try {
        final changeNotifications = obj['changeNotifications'];
        if (changeNotifications != null &&
            changeNotifications is! bool &&
            changeNotifications is! String) {
          reporter.reportError('must be of type Either2<bool, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('supported');
      try {
        final supported = obj['supported'];
        if (supported != null && supported is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type WorkspaceFoldersServerCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceFoldersServerCapabilities &&
        other.runtimeType == WorkspaceFoldersServerCapabilities &&
        changeNotifications == other.changeNotifications &&
        supported == other.supported;
  }

  @override
  int get hashCode => Object.hash(
        changeNotifications,
        supported,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A full document diagnostic report for a workspace diagnostic result.
///
/// @since 3.17.0
class WorkspaceFullDocumentDiagnosticReport
    implements FullDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFullDocumentDiagnosticReport.canParse,
    WorkspaceFullDocumentDiagnosticReport.fromJson,
  );

  WorkspaceFullDocumentDiagnosticReport({
    required this.items,
    this.kind = 'full',
    this.resultId,
    required this.uri,
    this.version,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static WorkspaceFullDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return WorkspaceFullDocumentDiagnosticReport(
      items: items,
      kind: kind,
      resultId: resultId,
      uri: uri,
      version: version,
    );
  }

  /// The actual items.
  @override
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  @override
  final String kind;

  /// An optional result id. If provided it will be sent on the next diagnostic
  /// request for the same document.
  @override
  final String? resultId;

  /// The URI for which diagnostic information is reported.
  final String uri;

  /// The version number for which the diagnostics are reported. If the document
  /// is not marked as open `null` can be provided.
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    result['kind'] = kind;
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) => !Diagnostic.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'full') {
          reporter.reportError('must be the literal \'full\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version != null && version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type WorkspaceFullDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceFullDocumentDiagnosticReport &&
        other.runtimeType == WorkspaceFullDocumentDiagnosticReport &&
        listEqual(items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
        kind == other.kind &&
        resultId == other.resultId &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(items),
        kind,
        resultId,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A special workspace symbol that supports locations without a range.
///
/// See also SymbolInformation.
///
/// @since 3.17.0
class WorkspaceSymbol implements BaseSymbolInformation, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbol.canParse,
    WorkspaceSymbol.fromJson,
  );

  WorkspaceSymbol({
    this.containerName,
    this.data,
    required this.kind,
    required this.location,
    required this.name,
    this.tags,
  });
  static WorkspaceSymbol fromJson(Map<String, Object?> json) {
    final containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    final dataJson = json['data'];
    final data = dataJson;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final locationJson = json['location'];
    final location = Location.canParse(locationJson, nullLspJsonReporter)
        ? Either2<Location, WorkspaceSymbolLocation>.t1(
            Location.fromJson(locationJson as Map<String, Object?>))
        : (WorkspaceSymbolLocation.canParse(locationJson, nullLspJsonReporter)
            ? Either2<Location, WorkspaceSymbolLocation>.t2(
                WorkspaceSymbolLocation.fromJson(
                    locationJson as Map<String, Object?>))
            : (throw '''$locationJson was not one of (Location, WorkspaceSymbolLocation)'''));
    final nameJson = json['name'];
    final name = nameJson as String;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return WorkspaceSymbol(
      containerName: containerName,
      data: data,
      kind: kind,
      location: location,
      name: name,
      tags: tags,
    );
  }

  /// The name of the symbol containing this symbol. This information is for
  /// user interface purposes (e.g. to render a qualifier in the user interface
  /// if necessary). It can't be used to re-infer a hierarchy for the document
  /// symbols.
  @override
  final String? containerName;

  /// A data entry field that is preserved on a workspace symbol between a
  /// workspace symbol request and a workspace symbol resolve request.
  final Object? data;

  /// The kind of this symbol.
  @override
  final SymbolKind kind;

  /// The location of the symbol. Whether a server is allowed to return a
  /// location without a range depends on the client capability
  /// `workspace.symbol.resolveSupport`.
  ///
  /// See SymbolInformation#location for more details.
  final Either2<Location, WorkspaceSymbolLocation> location;

  /// The name of this symbol.
  @override
  final String name;

  /// Tags for this symbol.
  ///
  /// @since 3.16.0
  @override
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (containerName != null) {
      result['containerName'] = containerName;
    }
    if (data != null) {
      result['data'] = data;
    }
    result['kind'] = kind.toJson();
    result['location'] = location;
    result['name'] = name;
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('containerName');
      try {
        final containerName = obj['containerName'];
        if (containerName != null && containerName is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('location');
      try {
        if (!obj.containsKey('location')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final location = obj['location'];
        if (location == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Location.canParse(location, reporter) &&
            !WorkspaceSymbolLocation.canParse(location, reporter)) {
          reporter.reportError(
              'must be of type Either2<Location, WorkspaceSymbolLocation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbol');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbol &&
        other.runtimeType == WorkspaceSymbol &&
        containerName == other.containerName &&
        data == other.data &&
        kind == other.kind &&
        location == other.location &&
        name == other.name &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        containerName,
        data,
        kind,
        location,
        name,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities for a WorkspaceSymbolRequest.
class WorkspaceSymbolClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilities.canParse,
    WorkspaceSymbolClientCapabilities.fromJson,
  );

  WorkspaceSymbolClientCapabilities({
    this.dynamicRegistration,
    this.resolveSupport,
    this.symbolKind,
    this.tagSupport,
  });
  static WorkspaceSymbolClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final resolveSupportJson = json['resolveSupport'];
    final resolveSupport = resolveSupportJson != null
        ? WorkspaceSymbolClientCapabilitiesResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    final symbolKindJson = json['symbolKind'];
    final symbolKind = symbolKindJson != null
        ? WorkspaceSymbolClientCapabilitiesSymbolKind.fromJson(
            symbolKindJson as Map<String, Object?>)
        : null;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? WorkspaceSymbolClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    return WorkspaceSymbolClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      resolveSupport: resolveSupport,
      symbolKind: symbolKind,
      tagSupport: tagSupport,
    );
  }

  /// Symbol request supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client support partial workspace symbols. The client will send the
  /// request `workspaceSymbol/resolve` to the server to resolve additional
  /// properties.
  ///
  /// @since 3.17.0
  final WorkspaceSymbolClientCapabilitiesResolveSupport? resolveSupport;

  /// Specific capabilities for the `SymbolKind` in the `workspace/symbol`
  /// request.
  final WorkspaceSymbolClientCapabilitiesSymbolKind? symbolKind;

  /// The client supports tags on `SymbolInformation`. Clients supporting tags
  /// have to handle unknown tags gracefully.
  ///
  /// @since 3.16.0
  final WorkspaceSymbolClientCapabilitiesTagSupport? tagSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (resolveSupport != null) {
      result['resolveSupport'] = resolveSupport?.toJson();
    }
    if (symbolKind != null) {
      result['symbolKind'] = symbolKind?.toJson();
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveSupport');
      try {
        final resolveSupport = obj['resolveSupport'];
        if (resolveSupport != null &&
            !WorkspaceSymbolClientCapabilitiesResolveSupport.canParse(
                resolveSupport, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceSymbolClientCapabilitiesResolveSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('symbolKind');
      try {
        final symbolKind = obj['symbolKind'];
        if (symbolKind != null &&
            !WorkspaceSymbolClientCapabilitiesSymbolKind.canParse(
                symbolKind, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        final tagSupport = obj['tagSupport'];
        if (tagSupport != null &&
            !WorkspaceSymbolClientCapabilitiesTagSupport.canParse(
                tagSupport, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolClientCapabilities &&
        other.runtimeType == WorkspaceSymbolClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        resolveSupport == other.resolveSupport &&
        symbolKind == other.symbolKind &&
        tagSupport == other.tagSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        resolveSupport,
        symbolKind,
        tagSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesResolveSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilitiesResolveSupport.canParse,
    WorkspaceSymbolClientCapabilitiesResolveSupport.fromJson,
  );

  WorkspaceSymbolClientCapabilitiesResolveSupport({
    required this.properties,
  });
  static WorkspaceSymbolClientCapabilitiesResolveSupport fromJson(
      Map<String, Object?> json) {
    final propertiesJson = json['properties'];
    final properties = (propertiesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return WorkspaceSymbolClientCapabilitiesResolveSupport(
      properties: properties,
    );
  }

  /// The properties that a client can resolve lazily. Usually `location.range`
  final List<String> properties;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('properties');
      try {
        if (!obj.containsKey('properties')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final properties = obj['properties'];
        if (properties == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (properties is! List<Object?> ||
            properties.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesResolveSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolClientCapabilitiesResolveSupport &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesResolveSupport &&
        listEqual(properties, other.properties, (String a, String b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(properties);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesSymbolKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilitiesSymbolKind.canParse,
    WorkspaceSymbolClientCapabilitiesSymbolKind.fromJson,
  );

  WorkspaceSymbolClientCapabilitiesSymbolKind({
    this.valueSet,
  });
  static WorkspaceSymbolClientCapabilitiesSymbolKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => SymbolKind.fromJson(item as int))
        .toList();
    return WorkspaceSymbolClientCapabilitiesSymbolKind(
      valueSet: valueSet,
    );
  }

  /// The symbol kind values the client supports. When this property exists the
  /// client also guarantees that it will handle values outside its set
  /// gracefully and falls back to a default value when unknown.
  ///
  /// If this property is not present the client only supports the symbol kinds
  /// from `File` to `Array` as defined in the initial version of the protocol.
  final List<SymbolKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        final valueSet = obj['valueSet'];
        if (valueSet != null &&
            (valueSet is! List<Object?> ||
                valueSet.any((item) => !SymbolKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolClientCapabilitiesSymbolKind &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesSymbolKind &&
        listEqual(
            valueSet, other.valueSet, (SymbolKind a, SymbolKind b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilitiesTagSupport.canParse,
    WorkspaceSymbolClientCapabilitiesTagSupport.fromJson,
  );

  WorkspaceSymbolClientCapabilitiesTagSupport({
    required this.valueSet,
  });
  static WorkspaceSymbolClientCapabilitiesTagSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return WorkspaceSymbolClientCapabilitiesTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<SymbolTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final valueSet = obj['valueSet'];
        if (valueSet == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (valueSet is! List<Object?> ||
            valueSet.any((item) => !SymbolTag.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolClientCapabilitiesTagSupport &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesTagSupport &&
        listEqual(
            valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolLocation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolLocation.canParse,
    WorkspaceSymbolLocation.fromJson,
  );

  WorkspaceSymbolLocation({
    required this.uri,
  });
  static WorkspaceSymbolLocation fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return WorkspaceSymbolLocation(
      uri: uri,
    );
  }

  final String uri;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolLocation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolLocation &&
        other.runtimeType == WorkspaceSymbolLocation &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Server capabilities for a WorkspaceSymbolRequest.
class WorkspaceSymbolOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolOptions.canParse,
    WorkspaceSymbolOptions.fromJson,
  );

  WorkspaceSymbolOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static WorkspaceSymbolOptions fromJson(Map<String, Object?> json) {
    if (WorkspaceSymbolRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceSymbolRegistrationOptions.fromJson(json);
    }
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkspaceSymbolOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The server provides support to resolve additional information for a
  /// workspace symbol.
  ///
  /// @since 3.17.0
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolOptions &&
        other.runtimeType == WorkspaceSymbolOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a WorkspaceSymbolRequest.
class WorkspaceSymbolParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolParams.canParse,
    WorkspaceSymbolParams.fromJson,
  );

  WorkspaceSymbolParams({
    this.partialResultToken,
    required this.query,
    this.workDoneToken,
  });
  static WorkspaceSymbolParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final queryJson = json['query'];
    final query = queryJson as String;
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return WorkspaceSymbolParams(
      partialResultToken: partialResultToken,
      query: query,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// A query string to filter symbols by. Clients may send an empty string here
  /// to request all symbols.
  final String query;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['query'] = query;
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('query');
      try {
        if (!obj.containsKey('query')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final query = obj['query'];
        if (query == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (query is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolParams &&
        other.runtimeType == WorkspaceSymbolParams &&
        partialResultToken == other.partialResultToken &&
        query == other.query &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        query,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a WorkspaceSymbolRequest.
class WorkspaceSymbolRegistrationOptions
    implements WorkspaceSymbolOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolRegistrationOptions.canParse,
    WorkspaceSymbolRegistrationOptions.fromJson,
  );

  WorkspaceSymbolRegistrationOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static WorkspaceSymbolRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkspaceSymbolRegistrationOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The server provides support to resolve additional information for a
  /// workspace symbol.
  ///
  /// @since 3.17.0
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type WorkspaceSymbolRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolRegistrationOptions &&
        other.runtimeType == WorkspaceSymbolRegistrationOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An unchanged document diagnostic report for a workspace diagnostic result.
///
/// @since 3.17.0
class WorkspaceUnchangedDocumentDiagnosticReport
    implements UnchangedDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceUnchangedDocumentDiagnosticReport.canParse,
    WorkspaceUnchangedDocumentDiagnosticReport.fromJson,
  );

  WorkspaceUnchangedDocumentDiagnosticReport({
    this.kind = 'unchanged',
    required this.resultId,
    required this.uri,
    this.version,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static WorkspaceUnchangedDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return WorkspaceUnchangedDocumentDiagnosticReport(
      kind: kind,
      resultId: resultId,
      uri: uri,
      version: version,
    );
  }

  /// A document diagnostic report indicating no changes to the last result. A
  /// server can only return `unchanged` if result ids are provided.
  @override
  final String kind;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  @override
  final String resultId;

  /// The URI for which diagnostic information is reported.
  final String uri;

  /// The version number for which the diagnostics are reported. If the document
  /// is not marked as open `null` can be provided.
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    result['resultId'] = resultId;
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'unchanged') {
          reporter.reportError('must be the literal \'unchanged\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        if (!obj.containsKey('resultId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final resultId = obj['resultId'];
        if (resultId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version != null && version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceUnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceUnchangedDocumentDiagnosticReport &&
        other.runtimeType == WorkspaceUnchangedDocumentDiagnosticReport &&
        kind == other.kind &&
        resultId == other.resultId &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        resultId,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}
