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

// ignore_for_file: annotate_overrides
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: prefer_is_not_operator
// ignore_for_file: unnecessary_parenthesis

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 annotation identifier.
  final String annotationId;

  /// 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;

  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) {
    if (other is AnnotatedTextEdit && other.runtimeType == AnnotatedTextEdit) {
      return annotationId == other.annotationId &&
          newText == other.newText &&
          range == other.range &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is ApplyWorkspaceEditParams &&
        other.runtimeType == ApplyWorkspaceEditParams) {
      return edit == other.edit && label == other.label && true;
    }
    return false;
  }

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

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

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 `failureHandling` strategy 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;

  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) {
    if (other is ApplyWorkspaceEditResult &&
        other.runtimeType == ApplyWorkspaceEditResult) {
      return applied == other.applied &&
          failedChange == other.failedChange &&
          failureReason == other.failureReason &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is CallHierarchyClientCapabilities &&
        other.runtimeType == CallHierarchyClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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`](#CallHierarchyIncomingCall.from).
  final List<Range> fromRanges;

  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.every((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) {
    if (other is CallHierarchyIncomingCall &&
        other.runtimeType == CallHierarchyIncomingCall) {
      return from == other.from &&
          listEqual(
              fromRanges, other.fromRanges, (Range a, Range b) => a == b) &&
          true;
    }
    return false;
  }

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

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

class CallHierarchyIncomingCallsParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  final Either2<int, String>? partialResultToken;

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

  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) {
    if (other is CallHierarchyIncomingCallsParams &&
        other.runtimeType == CallHierarchyIncomingCallsParams) {
      return item == other.item &&
          partialResultToken == other.partialResultToken &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

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`](#CallHierarchyItem.range).
  final Range selectionRange;

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

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

  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.every((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) {
    if (other is CallHierarchyItem && other.runtimeType == CallHierarchyItem) {
      return 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 &&
          true;
    }
    return false;
  }

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

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

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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is CallHierarchyOptions &&
        other.runtimeType == CallHierarchyOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

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 `callHierarchy/outgoingCalls` request.
  final List<Range> fromRanges;

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

  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.every((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) {
    if (other is CallHierarchyOutgoingCall &&
        other.runtimeType == CallHierarchyOutgoingCall) {
      return listEqual(
              fromRanges, other.fromRanges, (Range a, Range b) => a == b) &&
          to == other.to &&
          true;
    }
    return false;
  }

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

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

class CallHierarchyOutgoingCallsParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  final Either2<int, String>? partialResultToken;

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

  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) {
    if (other is CallHierarchyOutgoingCallsParams &&
        other.runtimeType == CallHierarchyOutgoingCallsParams) {
      return item == other.item &&
          partialResultToken == other.partialResultToken &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

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.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is CallHierarchyPrepareParams &&
        other.runtimeType == CallHierarchyPrepareParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class CallHierarchyRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        CallHierarchyOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is CallHierarchyRegistrationOptions &&
        other.runtimeType == CallHierarchyRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is CancelParams && other.runtimeType == CancelParams) {
      return id == other.id && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is ChangeAnnotation && other.runtimeType == ChangeAnnotation) {
      return description == other.description &&
          label == other.label &&
          needsConfirmation == other.needsConfirmation &&
          true;
    }
    return false;
  }

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

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

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
        ? ClientCapabilitiesGeneral.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 ClientCapabilitiesGeneral? 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;

  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 &&
            !(ClientCapabilitiesGeneral.canParse(general, reporter))) {
          reporter.reportError('must be of type ClientCapabilitiesGeneral');
          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) {
    if (other is ClientCapabilities &&
        other.runtimeType == ClientCapabilities) {
      return experimental == other.experimental &&
          general == other.general &&
          notebookDocument == other.notebookDocument &&
          textDocument == other.textDocument &&
          window == other.window &&
          workspace == other.workspace &&
          true;
    }
    return false;
  }

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

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

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

  ClientCapabilitiesFileOperations({
    this.didCreate,
    this.didDelete,
    this.didRename,
    this.dynamicRegistration,
    this.willCreate,
    this.willDelete,
    this.willRename,
  });
  static ClientCapabilitiesFileOperations 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 ClientCapabilitiesFileOperations(
      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;

  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 ClientCapabilitiesFileOperations');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ClientCapabilitiesFileOperations &&
        other.runtimeType == ClientCapabilitiesFileOperations) {
      return didCreate == other.didCreate &&
          didDelete == other.didDelete &&
          didRename == other.didRename &&
          dynamicRegistration == other.dynamicRegistration &&
          willCreate == other.willCreate &&
          willDelete == other.willDelete &&
          willRename == other.willRename &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        didCreate,
        didDelete,
        didRename,
        dynamicRegistration,
        willCreate,
        willDelete,
        willRename,
      );

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

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

  ClientCapabilitiesGeneral({
    this.markdown,
    this.positionEncodings,
    this.regularExpressions,
    this.staleRequestSupport,
  });
  static ClientCapabilitiesGeneral 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
        ? ClientCapabilitiesStaleRequestSupport.fromJson(
            staleRequestSupportJson as Map<String, Object?>)
        : null;
    return ClientCapabilitiesGeneral(
      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 side.
  ///
  /// 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 ClientCapabilitiesStaleRequestSupport? staleRequestSupport;

  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.every((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 &&
            !(ClientCapabilitiesStaleRequestSupport.canParse(
                staleRequestSupport, reporter))) {
          reporter.reportError(
              'must be of type ClientCapabilitiesStaleRequestSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ClientCapabilitiesGeneral');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ClientCapabilitiesGeneral &&
        other.runtimeType == ClientCapabilitiesGeneral) {
      return markdown == other.markdown &&
          listEqual(positionEncodings, other.positionEncodings,
              (PositionEncodingKind a, PositionEncodingKind b) => a == b) &&
          regularExpressions == other.regularExpressions &&
          staleRequestSupport == other.staleRequestSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        markdown,
        lspHashCode(positionEncodings),
        regularExpressions,
        staleRequestSupport,
      );

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

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

  ClientCapabilitiesStaleRequestSupport({
    required this.cancel,
    required this.retryOnContentModified,
  });
  static ClientCapabilitiesStaleRequestSupport 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 ClientCapabilitiesStaleRequestSupport(
      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;

  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.every((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 ClientCapabilitiesStaleRequestSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ClientCapabilitiesStaleRequestSupport &&
        other.runtimeType == ClientCapabilitiesStaleRequestSupport) {
      return cancel == other.cancel &&
          listEqual(retryOnContentModified, other.retryOnContentModified,
              (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        cancel,
        lspHashCode(retryOnContentModified),
      );

  @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 code
  ///   action menus.
  ///
  /// - Disabled actions are shown as faded out in the code action menu when
  ///   the user request a more specific type of code action, such as
  ///   refactorings.
  ///
  /// - If the user has a keybinding that auto applies a code action and only
  ///   a 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;

  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
                    .every((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) {
    if (other is CodeAction && other.runtimeType == CodeAction) {
      return 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 &&
          true;
    }
    return false;
  }

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

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

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 supports code action literals as a valid response of the
  /// `textDocument/codeAction` request.
  ///  @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;

  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) {
    if (other is CodeActionClientCapabilities &&
        other.runtimeType == CodeActionClientCapabilities) {
      return codeActionLiteralSupport == other.codeActionLiteralSupport &&
          dataSupport == other.dataSupport &&
          disabledSupport == other.disabledSupport &&
          dynamicRegistration == other.dynamicRegistration &&
          honorsChangeAnnotations == other.honorsChangeAnnotations &&
          isPreferredSupport == other.isPreferredSupport &&
          resolveSupport == other.resolveSupport &&
          true;
    }
    return false;
  }

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

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

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

  CodeActionClientCapabilitiesCodeActionKind({
    required this.valueSet,
  });
  static CodeActionClientCapabilitiesCodeActionKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => CodeActionKind.fromJson(item as String))
        .toList();
    return CodeActionClientCapabilitiesCodeActionKind(
      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;

  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
                .every((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 CodeActionClientCapabilitiesCodeActionKind');
      return false;
    }
  }

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

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

  @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 = CodeActionClientCapabilitiesCodeActionKind.fromJson(
        codeActionKindJson as Map<String, Object?>);
    return CodeActionClientCapabilitiesCodeActionLiteralSupport(
      codeActionKind: codeActionKind,
    );
  }

  /// The code action kind is supported with the following value set.
  final CodeActionClientCapabilitiesCodeActionKind codeActionKind;

  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 (!(CodeActionClientCapabilitiesCodeActionKind.canParse(
            codeActionKind, reporter))) {
          reporter.reportError(
              'must be of type CodeActionClientCapabilitiesCodeActionKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type CodeActionClientCapabilitiesCodeActionLiteralSupport');
      return false;
    }
  }

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

  @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;

  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.every((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) {
    if (other is CodeActionClientCapabilitiesResolveSupport &&
        other.runtimeType == CodeActionClientCapabilitiesResolveSupport) {
      return listEqual(
              properties, other.properties, (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @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;

  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
                .every((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.every(
                    (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) {
    if (other is CodeActionContext && other.runtimeType == CodeActionContext) {
      return listEqual(diagnostics, other.diagnostics,
              (Diagnostic a, Diagnostic b) => a == b) &&
          listEqual(only, other.only,
              (CodeActionKind a, CodeActionKind b) => a == b) &&
          triggerKind == other.triggerKind &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is CodeActionDisabled &&
        other.runtimeType == CodeActionDisabled) {
      return reason == other.reason && true;
    }
    return false;
  }

  @override
  int get hashCode => reason.hashCode;

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

/// A set of predefined code action kinds.
class CodeActionKind {
  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 an organize imports source action: `source.organizeImports`.
  static const SourceOrganizeImports = CodeActionKind('source.organizeImports');

  /// Base kind for a 'fix all' source action: `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.17.0
  static const SourceFixAll = CodeActionKind('source.fixAll');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is CodeActionKind && o._value == _value;
}

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;
  final bool? workDoneProgress;

  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.every(
                    (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) {
    if (other is CodeActionOptions && other.runtimeType == CodeActionOptions) {
      return listEqual(codeActionKinds, other.codeActionKinds,
              (CodeActionKind a, CodeActionKind b) => a == b) &&
          resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

/// Params for the CodeActionRequest
class CodeActionParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is CodeActionParams && other.runtimeType == CodeActionParams) {
      return context == other.context &&
          partialResultToken == other.partialResultToken &&
          range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class CodeActionRegistrationOptions
    implements TextDocumentRegistrationOptions, CodeActionOptions, 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) => TextDocumentFilter.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.
  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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is CodeActionRegistrationOptions &&
        other.runtimeType == CodeActionRegistrationOptions) {
      return listEqual(codeActionKinds, other.codeActionKinds,
              (CodeActionKind a, CodeActionKind b) => a == b) &&
          listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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 {
  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 explicitly requested by the user or by an extension.
  static const Invoked = CodeActionTriggerKind(1);

  /// 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);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is CodeActionTriggerKind && o._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;

  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) {
    if (other is CodeDescription && other.runtimeType == CodeDescription) {
      return href == other.href && true;
    }
    return false;
  }

  @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 code
  /// lens and a code lens resolve request.
  final Object? data;

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

  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) {
    if (other is CodeLens && other.runtimeType == CodeLens) {
      return command == other.command &&
          data == other.data &&
          range == other.range &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is CodeLensClientCapabilities &&
        other.runtimeType == CodeLensClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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;
  final bool? workDoneProgress;

  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) {
    if (other is CodeLensOptions && other.runtimeType == CodeLensOptions) {
      return resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

class CodeLensParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is CodeLensParams && other.runtimeType == CodeLensParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class CodeLensRegistrationOptions
    implements TextDocumentRegistrationOptions, CodeLensOptions, 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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is CodeLensRegistrationOptions &&
        other.runtimeType == CodeLensRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is CodeLensWorkspaceClientCapabilities &&
        other.runtimeType == CodeLensWorkspaceClientCapabilities) {
      return refreshSupport == other.refreshSupport && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is Color && other.runtimeType == Color) {
      return alpha == other.alpha &&
          blue == other.blue &&
          green == other.green &&
          red == other.red &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is ColorInformation && other.runtimeType == ColorInformation) {
      return color == other.color && range == other.range && true;
    }
    return false;
  }

  @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 ([TextEdit]) that are applied
  /// when selecting this color presentation. Edits must not overlap with the
  /// main [edit](#ColorPresentation.textEdit) 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 ([TextEdit]) which is applied to a document when selecting this
  /// presentation for the color. When `falsy` the
  /// [label](#ColorPresentation.label) is used.
  final TextEdit? textEdit;

  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
                    .every((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) {
    if (other is ColorPresentation && other.runtimeType == ColorPresentation) {
      return listEqual(additionalTextEdits, other.additionalTextEdits,
              (TextEdit a, TextEdit b) => a == b) &&
          label == other.label &&
          textEdit == other.textEdit &&
          true;
    }
    return false;
  }

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

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

class ColorPresentationParams
    implements WorkDoneProgressParams, PartialResultParams, 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 information 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.
  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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is ColorPresentationParams &&
        other.runtimeType == ColorPresentationParams) {
      return color == other.color &&
          partialResultToken == other.partialResultToken &&
          range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

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;

  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.every((item) => true))))) {
          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) {
    if (other is Command && other.runtimeType == Command) {
      return listEqual(
              arguments, other.arguments, (Object? a, Object? b) => a == b) &&
          command == other.command &&
          title == other.title &&
          true;
    }
    return false;
  }

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

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

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;

  /// The client's default when the completion item doesn't provide a
  /// `insertTextMode` property.
  ///  @since 3.17.0
  final InsertTextMode? insertTextMode;

  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) {
    if (other is CompletionClientCapabilities &&
        other.runtimeType == CompletionClientCapabilities) {
      return completionItem == other.completionItem &&
          completionItemKind == other.completionItemKind &&
          completionList == other.completionList &&
          contextSupport == other.contextSupport &&
          dynamicRegistration == other.dynamicRegistration &&
          insertTextMode == other.insertTextMode &&
          true;
    }
    return false;
  }

  @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
        ? CompletionClientCapabilitiesInsertTextModeSupport.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
        ? CompletionClientCapabilitiesResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    final snippetSupportJson = json['snippetSupport'];
    final snippetSupport = snippetSupportJson as bool?;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? CompletionClientCapabilitiesTagSupport.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 follow content formats for the documentation property.
  /// The order describes the preferred format of the client.
  final List<MarkupKind>? documentationFormat;

  /// Client supports 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 CompletionClientCapabilitiesInsertTextModeSupport?
      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 `detail` could be resolved lazily.
  ///  @since 3.16.0
  final CompletionClientCapabilitiesResolveSupport? 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 CompletionClientCapabilitiesTagSupport? tagSupport;

  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
                    .every((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 &&
            !(CompletionClientCapabilitiesInsertTextModeSupport.canParse(
                insertTextModeSupport, reporter))) {
          reporter.reportError(
              'must be of type CompletionClientCapabilitiesInsertTextModeSupport');
          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 &&
            !(CompletionClientCapabilitiesResolveSupport.canParse(
                resolveSupport, reporter))) {
          reporter.reportError(
              'must be of type CompletionClientCapabilitiesResolveSupport');
          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 &&
            !(CompletionClientCapabilitiesTagSupport.canParse(
                tagSupport, reporter))) {
          reporter.reportError(
              'must be of type CompletionClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type CompletionClientCapabilitiesCompletionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is CompletionClientCapabilitiesCompletionItem &&
        other.runtimeType == CompletionClientCapabilitiesCompletionItem) {
      return 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 &&
          true;
    }
    return false;
  }

  @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;

  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.every(
                    (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) {
    if (other is CompletionClientCapabilitiesCompletionItemKind &&
        other.runtimeType == CompletionClientCapabilitiesCompletionItemKind) {
      return listEqual(valueSet, other.valueSet,
              (CompletionItemKind a, CompletionItemKind b) => a == b) &&
          true;
    }
    return false;
  }

  @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 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;

  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.every((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) {
    if (other is CompletionClientCapabilitiesCompletionList &&
        other.runtimeType == CompletionClientCapabilitiesCompletionList) {
      return listEqual(itemDefaults, other.itemDefaults,
              (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

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

  final List<InsertTextMode> valueSet;

  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
                .every((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 CompletionClientCapabilitiesInsertTextModeSupport');
      return false;
    }
  }

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

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

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

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

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

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

  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.every((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 CompletionClientCapabilitiesResolveSupport');
      return false;
    }
  }

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

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

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

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

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

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

  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.every(
                (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 CompletionClientCapabilitiesTagSupport');
      return false;
    }
  }

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

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

  @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;

  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) {
    if (other is CompletionContext && other.runtimeType == CompletionContext) {
      return triggerCharacter == other.triggerCharacter &&
          triggerKind == other.triggerKind &&
          true;
    }
    return false;
  }

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

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

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
  /// completion and a completion resolve request.
  final CompletionItemResolutionInfo? data;

  /// Indicates if this item is deprecated.
  ///  @deprecated Use `tags` instead if supported.
  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 as the filter text for this item.
  final String? filterText;

  /// A string that should be inserted into a document when selecting this
  /// completion. When `falsy` the label is used as the insert text for this
  /// item.
  ///
  /// 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 client's default value depends on the
  /// `textDocument.completion.insertTextMode` client capability.
  ///  @since 3.16.0 @since 3.17.0 - support for
  /// `textDocument.completion.insertTextMode`
  final InsertTextMode? insertTextMode;

  /// The kind of this completion item. Based of the kind an icon is chosen by
  /// the editor. The standardized set of available values is defined in
  /// `CompletionItemKind`.
  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 as the sort text for this item.
  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.
  ///
  /// *Note:* The range of the edit must be a single line range and it must
  /// contain the position at which completion has been requested.
  ///
  /// 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 `InsertReplaceEdit`s via the
  /// `textDocument.completion.completionItem.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;

  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
                    .every((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.every((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.every(
                    (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) {
    if (other is CompletionItem && other.runtimeType == CompletionItem) {
      return 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 &&
          true;
    }
    return false;
  }

  @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());
}

/// The kind of a completion entry.
class CompletionItemKind {
  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 Text = CompletionItemKind(1);
  static const Method = CompletionItemKind(2);
  static const Function = CompletionItemKind(3);
  static const Constructor = CompletionItemKind(4);
  static const Field = CompletionItemKind(5);
  static const Variable = CompletionItemKind(6);
  static const Class = CompletionItemKind(7);
  static const Interface = CompletionItemKind(8);
  static const Module = CompletionItemKind(9);
  static const Property = CompletionItemKind(10);
  static const Unit = CompletionItemKind(11);
  static const Value = CompletionItemKind(12);
  static const Enum = CompletionItemKind(13);
  static const Keyword = CompletionItemKind(14);
  static const Snippet = CompletionItemKind(15);
  static const Color = CompletionItemKind(16);
  static const File = CompletionItemKind(17);
  static const Reference = CompletionItemKind(18);
  static const Folder = CompletionItemKind(19);
  static const EnumMember = CompletionItemKind(20);
  static const Constant = CompletionItemKind(21);
  static const Struct = CompletionItemKind(22);
  static const Event = CompletionItemKind(23);
  static const Operator = CompletionItemKind(24);
  static const TypeParameter = CompletionItemKind(25);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is CompletionItemKind && o._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
  /// CompletionItemLabelDetails.detail}. Should be used for fully qualified
  /// names or file path.
  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 or type annotations.
  final String? detail;

  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) {
    if (other is CompletionItemLabelDetails &&
        other.runtimeType == CompletionItemLabelDetails) {
      return description == other.description && detail == other.detail && true;
    }
    return false;
  }

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

  @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 {
  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);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is CompletionItemTag && o._value == _value;
}

/// Represents a collection of completion items ([CompletionItem]) 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 is not complete. Further typing should result 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;

  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
                .every((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) {
    if (other is CompletionList && other.runtimeType == CompletionList) {
      return isIncomplete == other.isIncomplete &&
          itemDefaults == other.itemDefaults &&
          listEqual(items, other.items,
              (CompletionItem a, CompletionItem b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

  CompletionListEditRange({
    required this.insert,
    required this.replace,
  });
  static CompletionListEditRange 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 CompletionListEditRange(
      insert: insert,
      replace: replace,
    );
  }

  final Range insert;
  final Range replace;

  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 CompletionListEditRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is CompletionListEditRange &&
        other.runtimeType == CompletionListEditRange) {
      return insert == other.insert && replace == other.replace && true;
    }
    return false;
  }

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

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

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

  CompletionListItemDefaults({
    this.commitCharacters,
    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 editRangeJson = json['editRange'];
    final editRange = editRangeJson == null
        ? null
        : (CompletionListEditRange.canParse(editRangeJson, nullLspJsonReporter)
            ? Either2<CompletionListEditRange, Range>.t1(
                CompletionListEditRange.fromJson(
                    editRangeJson as Map<String, Object?>))
            : (Range.canParse(editRangeJson, nullLspJsonReporter)
                ? Either2<CompletionListEditRange, Range>.t2(
                    Range.fromJson(editRangeJson as Map<String, Object?>))
                : (throw '''$editRangeJson was not one of (CompletionListEditRange, 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,
      editRange: editRange,
      insertTextFormat: insertTextFormat,
      insertTextMode: insertTextMode,
    );
  }

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

  /// A default edit range
  ///  @since 3.17.0
  final Either2<CompletionListEditRange, 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;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (commitCharacters != null) {
      __result['commitCharacters'] = commitCharacters;
    }
    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.every((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 &&
            !((CompletionListEditRange.canParse(editRange, reporter) ||
                Range.canParse(editRange, reporter)))) {
          reporter.reportError(
              'must be of type Either2<CompletionListEditRange, 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) {
    if (other is CompletionListItemDefaults &&
        other.runtimeType == CompletionListItemDefaults) {
      return listEqual(commitCharacters, other.commitCharacters,
              (String a, String b) => a == b) &&
          editRange == other.editRange &&
          insertTextFormat == other.insertTextFormat &&
          insertTextMode == other.insertTextMode &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(commitCharacters),
        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 client capability
  /// `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;
  final bool? workDoneProgress;

  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.every((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.every((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) {
    if (other is CompletionOptions && other.runtimeType == CompletionOptions) {
      return 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 &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is CompletionOptionsCompletionItem &&
        other.runtimeType == CompletionOptionsCompletionItem) {
      return labelDetailsSupport == other.labelDetailsSupport && true;
    }
    return false;
  }

  @override
  int get hashCode => labelDetailsSupport.hashCode;

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

class CompletionParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        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 if the client specifies to
  /// send this using the client capability `completion.contextSupport === true`
  final CompletionContext? context;

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

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is CompletionParams && other.runtimeType == CompletionParams) {
      return context == other.context &&
          partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class CompletionRegistrationOptions
    implements TextDocumentRegistrationOptions, CompletionOptions, 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) => TextDocumentFilter.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 client capability
  /// `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;

  /// 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<TextDocumentFilter>? documentSelector;

  /// 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;
  final bool? workDoneProgress;

  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.every((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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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.every((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) {
    if (other is CompletionRegistrationOptions &&
        other.runtimeType == CompletionRegistrationOptions) {
      return listEqual(allCommitCharacters, other.allCommitCharacters,
              (String a, String b) => a == b) &&
          completionItem == other.completionItem &&
          listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          resolveProvider == other.resolveProvider &&
          listEqual(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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 {
  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 the current completion list is incomplete.
  static const TriggerForIncompleteCompletions = CompletionTriggerKind._(3);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is CompletionTriggerKind && o._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;

  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) {
    if (other is ConfigurationItem && other.runtimeType == ConfigurationItem) {
      return scopeUri == other.scopeUri && section == other.section && true;
    }
    return false;
  }

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

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

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;

  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.every(
                (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) {
    if (other is ConfigurationParams &&
        other.runtimeType == ConfigurationParams) {
      return listEqual(items, other.items,
              (ConfigurationItem a, ConfigurationItem b) => a == b) &&
          true;
    }
    return false;
  }

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

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

/// Create file operation
class CreateFile implements 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
  final String? annotationId;

  /// A create
  final String kind;

  /// Additional options
  final CreateFileOptions? options;

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

  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) {
    if (other is CreateFile && other.runtimeType == CreateFile) {
      return annotationId == other.annotationId &&
          kind == other.kind &&
          options == other.options &&
          uri == other.uri &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is CreateFileOptions && other.runtimeType == CreateFileOptions) {
      return ignoreIfExists == other.ignoreIfExists &&
          overwrite == other.overwrite &&
          true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is CreateFilesParams && other.runtimeType == CreateFilesParams) {
      return listEqual(
              files, other.files, (FileCreate a, FileCreate b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is DeclarationClientCapabilities &&
        other.runtimeType == DeclarationClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          linkSupport == other.linkSupport &&
          true;
    }
    return false;
  }

  @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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is DeclarationOptions &&
        other.runtimeType == DeclarationOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class DeclarationParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        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.
  final Either2<int, String>? partialResultToken;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is DeclarationParams && other.runtimeType == DeclarationParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class DeclarationRegistrationOptions
    implements
        DeclarationOptions,
        TextDocumentRegistrationOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is DeclarationRegistrationOptions &&
        other.runtimeType == DeclarationRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is DefinitionClientCapabilities &&
        other.runtimeType == DefinitionClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          linkSupport == other.linkSupport &&
          true;
    }
    return false;
  }

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

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

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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is DefinitionOptions && other.runtimeType == DefinitionOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class DefinitionParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        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.
  final Either2<int, String>? partialResultToken;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is DefinitionParams && other.runtimeType == DefinitionParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class DefinitionRegistrationOptions
    implements TextDocumentRegistrationOptions, DefinitionOptions, 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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is DefinitionRegistrationOptions &&
        other.runtimeType == DefinitionRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

/// Delete file operation
class DeleteFile implements 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
  final String? annotationId;

  /// A delete
  final String kind;

  /// Delete options.
  final DeleteFileOptions? options;

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

  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) {
    if (other is DeleteFile && other.runtimeType == DeleteFile) {
      return annotationId == other.annotationId &&
          kind == other.kind &&
          options == other.options &&
          uri == other.uri &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is DeleteFileOptions && other.runtimeType == DeleteFileOptions) {
      return ignoreIfNotExists == other.ignoreIfNotExists &&
          recursive == other.recursive &&
          true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is DeleteFilesParams && other.runtimeType == DeleteFilesParams) {
      return listEqual(
              files, other.files, (FileDelete a, FileDelete b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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 might appear in the user interface.
  final String? code;

  /// An optional property to describe the error code.
  ///  @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.
  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'.
  final String? source;

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

  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.every((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.every(
                    (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) {
    if (other is Diagnostic && other.runtimeType == Diagnostic) {
      return 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) &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is DiagnosticClientCapabilities &&
        other.runtimeType == DiagnosticClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          relatedDocumentSupport == other.relatedDocumentSupport &&
          true;
    }
    return false;
  }

  @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;
  final bool? workDoneProgress;

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

  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) {
    if (other is DiagnosticOptions && other.runtimeType == DiagnosticOptions) {
      return identifier == other.identifier &&
          interFileDependencies == other.interFileDependencies &&
          workDoneProgress == other.workDoneProgress &&
          workspaceDiagnostics == other.workspaceDiagnostics &&
          true;
    }
    return false;
  }

  @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
        TextDocumentRegistrationOptions,
        DiagnosticOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  /// 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;
  final bool? workDoneProgress;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is DiagnosticRegistrationOptions &&
        other.runtimeType == DiagnosticRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          identifier == other.identifier &&
          interFileDependencies == other.interFileDependencies &&
          workDoneProgress == other.workDoneProgress &&
          workspaceDiagnostics == other.workspaceDiagnostics &&
          true;
    }
    return false;
  }

  @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 are 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;

  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) {
    if (other is DiagnosticRelatedInformation &&
        other.runtimeType == DiagnosticRelatedInformation) {
      return location == other.location && message == other.message && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is DiagnosticServerCancellationData &&
        other.runtimeType == DiagnosticServerCancellationData) {
      return retriggerRequest == other.retriggerRequest && true;
    }
    return false;
  }

  @override
  int get hashCode => retriggerRequest.hashCode;

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

class DiagnosticSeverity {
  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 warning.
  static const Warning = DiagnosticSeverity(2);

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is DiagnosticSeverity && o._value == _value;
}

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

  final int _value;

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

  /// 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);

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is DiagnosticTag && o._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;

  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) {
    if (other is DiagnosticWorkspaceClientCapabilities &&
        other.runtimeType == DiagnosticWorkspaceClientCapabilities) {
      return refreshSupport == other.refreshSupport && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is DidChangeConfigurationClientCapabilities &&
        other.runtimeType == DidChangeConfigurationClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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;

  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) {
    if (other is DidChangeConfigurationParams &&
        other.runtimeType == DidChangeConfigurationParams) {
      return settings == other.settings && true;
    }
    return false;
  }

  @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 change describes single state change to the notebook document. So it
  /// moves a notebook document, its cells and its cell text document contents
  /// from state S to 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.
  final NotebookDocumentChangeEvent change;

  /// The notebook document that did change. The version number points to the
  /// version after all provided changes have been applied.
  final VersionedNotebookDocumentIdentifier notebookDocument;

  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) {
    if (other is DidChangeNotebookDocumentParams &&
        other.runtimeType == DidChangeNotebookDocumentParams) {
      return change == other.change &&
          notebookDocument == other.notebookDocument &&
          true;
    }
    return false;
  }

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

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

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;

  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.every((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) {
    if (other is DidChangeTextDocumentParams &&
        other.runtimeType == DidChangeTextDocumentParams) {
      return listEqual(
              contentChanges,
              other.contentChanges,
              (Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          a,
                      Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          b) =>
                  a == b) &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

  @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 relative patterns or not.
  ///  @since 3.17.0
  final bool? relativePatternSupport;

  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) {
    if (other is DidChangeWatchedFilesClientCapabilities &&
        other.runtimeType == DidChangeWatchedFilesClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          relativePatternSupport == other.relativePatternSupport &&
          true;
    }
    return false;
  }

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

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

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;

  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.every((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) {
    if (other is DidChangeWatchedFilesParams &&
        other.runtimeType == DidChangeWatchedFilesParams) {
      return listEqual(
              changes, other.changes, (FileEvent a, FileEvent b) => a == b) &&
          true;
    }
    return false;
  }

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

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

/// Describe options to be used when registering for file system 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;

  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.every(
                (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) {
    if (other is DidChangeWatchedFilesRegistrationOptions &&
        other.runtimeType == DidChangeWatchedFilesRegistrationOptions) {
      return listEqual(watchers, other.watchers,
              (FileSystemWatcher a, FileSystemWatcher b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is DidChangeWorkspaceFoldersParams &&
        other.runtimeType == DidChangeWorkspaceFoldersParams) {
      return event == other.event && true;
    }
    return false;
  }

  @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;

  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.every(
                (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) {
    if (other is DidCloseNotebookDocumentParams &&
        other.runtimeType == DidCloseNotebookDocumentParams) {
      return listEqual(cellTextDocuments, other.cellTextDocuments,
              (TextDocumentIdentifier a, TextDocumentIdentifier b) => a == b) &&
          notebookDocument == other.notebookDocument &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cellTextDocuments),
        notebookDocument,
      );

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

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;

  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) {
    if (other is DidCloseTextDocumentParams &&
        other.runtimeType == DidCloseTextDocumentParams) {
      return textDocument == other.textDocument && true;
    }
    return false;
  }

  @override
  int get hashCode => textDocument.hashCode;

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

/// The params sent in a 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;

  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.every(
                (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) {
    if (other is DidOpenNotebookDocumentParams &&
        other.runtimeType == DidOpenNotebookDocumentParams) {
      return listEqual(cellTextDocuments, other.cellTextDocuments,
              (TextDocumentItem a, TextDocumentItem b) => a == b) &&
          notebookDocument == other.notebookDocument &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cellTextDocuments),
        notebookDocument,
      );

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

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;

  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) {
    if (other is DidOpenTextDocumentParams &&
        other.runtimeType == DidOpenTextDocumentParams) {
      return textDocument == other.textDocument && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is DidSaveNotebookDocumentParams &&
        other.runtimeType == DidSaveNotebookDocumentParams) {
      return notebookDocument == other.notebookDocument && true;
    }
    return false;
  }

  @override
  int get hashCode => notebookDocument.hashCode;

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

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;

  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) {
    if (other is DidSaveTextDocumentParams &&
        other.runtimeType == DidSaveTextDocumentParams) {
      return text == other.text && textDocument == other.textDocument && true;
    }
    return false;
  }

  @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 document color supports dynamic registration.
  final bool? dynamicRegistration;

  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) {
    if (other is DocumentColorClientCapabilities &&
        other.runtimeType == DocumentColorClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is DocumentColorOptions &&
        other.runtimeType == DocumentColorOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class DocumentColorParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is DocumentColorParams &&
        other.runtimeType == DocumentColorParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class DocumentColorRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        StaticRegistrationOptions,
        DocumentColorOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is DocumentColorRegistrationOptions &&
        other.runtimeType == DocumentColorRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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 WorkDoneProgressParams, PartialResultParams, 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.
  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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is DocumentDiagnosticParams &&
        other.runtimeType == DocumentDiagnosticParams) {
      return identifier == other.identifier &&
          partialResultToken == other.partialResultToken &&
          previousResultId == other.previousResultId &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

/// The document diagnostic report kinds.
///  @since 3.17.0
class DocumentDiagnosticReportKind {
  const DocumentDiagnosticReportKind(this._value);
  const DocumentDiagnosticReportKind.fromJson(this._value);

  final String _value;

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

  /// A diagnostic report with a full set of problems.
  static const Full = DocumentDiagnosticReportKind('full');

  /// A report indicating that the last returned report is still accurate.
  static const Unchanged = DocumentDiagnosticReportKind('unchanged');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is DocumentDiagnosticReportKind && o._value == _value;
}

/// 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;

  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.every((item) =>
                item is String &&
                relatedDocuments.values.every((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) {
    if (other is DocumentDiagnosticReportPartialResult &&
        other.runtimeType == DocumentDiagnosticReportPartialResult) {
      return mapEqual(
              relatedDocuments,
              other.relatedDocuments,
              (Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          a,
                      Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is DocumentFormattingClientCapabilities &&
        other.runtimeType == DocumentFormattingClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is DocumentFormattingOptions &&
        other.runtimeType == DocumentFormattingOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is DocumentFormattingParams &&
        other.runtimeType == DocumentFormattingParams) {
      return options == other.options &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class DocumentFormattingRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        DocumentFormattingOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is DocumentFormattingRegistrationOptions &&
        other.runtimeType == DocumentFormattingRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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 DocumentHighlightKind.Text.
  final DocumentHighlightKind? kind;

  /// The range this highlight applies to.
  final Range range;

  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) {
    if (other is DocumentHighlight && other.runtimeType == DocumentHighlight) {
      return kind == other.kind && range == other.range && true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is DocumentHighlightClientCapabilities &&
        other.runtimeType == DocumentHighlightClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

/// A document highlight kind.
class DocumentHighlightKind {
  const DocumentHighlightKind(this._value);
  const DocumentHighlightKind.fromJson(this._value);

  final int _value;

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

  /// A textual occurrence.
  static const Text = DocumentHighlightKind(1);

  /// Read-access of a symbol, like reading a variable.
  static const Read = DocumentHighlightKind(2);

  /// Write-access of a symbol, like writing to a variable.
  static const Write = DocumentHighlightKind(3);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is DocumentHighlightKind && o._value == _value;
}

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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is DocumentHighlightOptions &&
        other.runtimeType == DocumentHighlightOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class DocumentHighlightParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        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.
  final Either2<int, String>? partialResultToken;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is DocumentHighlightParams &&
        other.runtimeType == DocumentHighlightParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class DocumentHighlightRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        DocumentHighlightOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is DocumentHighlightRegistrationOptions &&
        other.runtimeType == DocumentHighlightRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is DocumentLink && other.runtimeType == DocumentLink) {
      return data == other.data &&
          range == other.range &&
          target == other.target &&
          tooltip == other.tooltip &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is DocumentLinkClientCapabilities &&
        other.runtimeType == DocumentLinkClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          tooltipSupport == other.tooltipSupport &&
          true;
    }
    return false;
  }

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

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

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;
  final bool? workDoneProgress;

  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) {
    if (other is DocumentLinkOptions &&
        other.runtimeType == DocumentLinkOptions) {
      return resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

class DocumentLinkParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is DocumentLinkParams &&
        other.runtimeType == DocumentLinkParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class DocumentLinkRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        DocumentLinkOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

  /// Document links have a resolve provider as well.
  final bool? resolveProvider;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is DocumentLinkRegistrationOptions &&
        other.runtimeType == DocumentLinkRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is DocumentOnTypeFormattingClientCapabilities &&
        other.runtimeType == DocumentOnTypeFormattingClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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;

  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.every((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) {
    if (other is DocumentOnTypeFormattingOptions &&
        other.runtimeType == DocumentOnTypeFormattingOptions) {
      return firstTriggerCharacter == other.firstTriggerCharacter &&
          listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
              (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        firstTriggerCharacter,
        lspHashCode(moreTriggerCharacter),
      );

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

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;

  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) {
    if (other is DocumentOnTypeFormattingParams &&
        other.runtimeType == DocumentOnTypeFormattingParams) {
      return ch == other.ch &&
          options == other.options &&
          position == other.position &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

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

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

class DocumentOnTypeFormattingRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        DocumentOnTypeFormattingOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

  /// A character on which formatting should be triggered, like `{`.
  final String firstTriggerCharacter;

  /// More trigger characters.
  final List<String>? moreTriggerCharacter;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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.every((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) {
    if (other is DocumentOnTypeFormattingRegistrationOptions &&
        other.runtimeType == DocumentOnTypeFormattingRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          firstTriggerCharacter == other.firstTriggerCharacter &&
          listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
              (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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 formatting supports dynamic registration.
  final bool? dynamicRegistration;

  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) {
    if (other is DocumentRangeFormattingClientCapabilities &&
        other.runtimeType == DocumentRangeFormattingClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is DocumentRangeFormattingOptions &&
        other.runtimeType == DocumentRangeFormattingOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is DocumentRangeFormattingParams &&
        other.runtimeType == DocumentRangeFormattingParams) {
      return options == other.options &&
          range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class DocumentRangeFormattingRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        DocumentRangeFormattingOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is DocumentRangeFormattingRegistrationOptions &&
        other.runtimeType == DocumentRangeFormattingRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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;

  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.every(
                    (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.every((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) {
    if (other is DocumentSymbol && other.runtimeType == DocumentSymbol) {
      return 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) &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is DocumentSymbolClientCapabilities &&
        other.runtimeType == DocumentSymbolClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          hierarchicalDocumentSymbolSupport ==
              other.hierarchicalDocumentSymbolSupport &&
          labelSupport == other.labelSupport &&
          symbolKind == other.symbolKind &&
          tagSupport == other.tagSupport &&
          true;
    }
    return false;
  }

  @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;

  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
                    .every((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) {
    if (other is DocumentSymbolClientCapabilitiesSymbolKind &&
        other.runtimeType == DocumentSymbolClientCapabilitiesSymbolKind) {
      return listEqual(valueSet, other.valueSet,
              (SymbolKind a, SymbolKind b) => a == b) &&
          true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is DocumentSymbolClientCapabilitiesTagSupport &&
        other.runtimeType == DocumentSymbolClientCapabilitiesTagSupport) {
      return listEqual(
              valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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;
  final bool? workDoneProgress;

  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) {
    if (other is DocumentSymbolOptions &&
        other.runtimeType == DocumentSymbolOptions) {
      return label == other.label &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

class DocumentSymbolParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is DocumentSymbolParams &&
        other.runtimeType == DocumentSymbolParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class DocumentSymbolRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        DocumentSymbolOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

  /// A human-readable string that is shown when multiple outlines trees are
  /// shown for the same document.
  ///  @since 3.16.0
  final String? label;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is DocumentSymbolRegistrationOptions &&
        other.runtimeType == DocumentSymbolRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          label == other.label &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

class ErrorCodes {
  const ErrorCodes(this._value);
  const ErrorCodes.fromJson(this._value);

  final int _value;

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

  /// Defined by JSON RPC
  static const ParseError = ErrorCodes(-32700);
  static const InvalidRequest = ErrorCodes(-32600);
  static const MethodNotFound = ErrorCodes(-32601);
  static const InvalidParams = ErrorCodes(-32602);
  static const InternalError = ErrorCodes(-32603);

  /// This is the start range of JSON RPC reserved error codes. It doesn't
  /// denote a real error code. No LSP 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);

  /// 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);

  /// 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 LSP reserved error codes. It doesn't denote a
  /// real error code.
  ///  @since 3.16.0
  static const lspReservedErrorRangeStart = ErrorCodes(-32899);

  /// 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);

  /// 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);

  /// The client has canceled a request and a server as detected the cancel.
  static const RequestCancelled = ErrorCodes(-32800);

  /// 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);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is ErrorCodes && o._value == _value;
}

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;

  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) {
    if (other is ExecuteCommandClientCapabilities &&
        other.runtimeType == ExecuteCommandClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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;
  final bool? workDoneProgress;

  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.every((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) {
    if (other is ExecuteCommandOptions &&
        other.runtimeType == ExecuteCommandOptions) {
      return listEqual(
              commands, other.commands, (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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.
  final Either2<int, String>? workDoneToken;

  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.every((item) => true))))) {
          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) {
    if (other is ExecuteCommandParams &&
        other.runtimeType == ExecuteCommandParams) {
      return listEqual(
              arguments, other.arguments, (Object? a, Object? b) => a == b) &&
          command == other.command &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

/// Execute command registration options.
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
  final List<String> commands;
  final bool? workDoneProgress;

  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.every((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) {
    if (other is ExecuteCommandRegistrationOptions &&
        other.runtimeType == ExecuteCommandRegistrationOptions) {
      return listEqual(
              commands, other.commands, (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is ExecutionSummary && other.runtimeType == ExecutionSummary) {
      return executionOrder == other.executionOrder &&
          success == other.success &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        executionOrder,
        success,
      );

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

class FailureHandlingKind {
  const FailureHandlingKind._(this._value);
  const FailureHandlingKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'abort':
      case 'transactional':
      case 'textOnlyTransactional':
      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');

  /// 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');

  /// 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');

  /// The client tries to undo the operations already executed. But there is no
  /// guarantee that this is succeeding.
  static const Undo = FailureHandlingKind._('undo');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is FailureHandlingKind && o._value == _value;
}

/// The file event type.
class FileChangeType {
  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 created.
  static const Created = FileChangeType(1);

  /// The file got changed.
  static const Changed = FileChangeType(2);

  /// The file got deleted.
  static const Deleted = FileChangeType(3);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is FileChangeType && o._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;

  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) {
    if (other is FileCreate && other.runtimeType == FileCreate) {
      return uri == other.uri && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is FileDelete && other.runtimeType == FileDelete) {
      return uri == other.uri && true;
    }
    return false;
  }

  @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 = typeJson as int;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return FileEvent(
      type: type,
      uri: uri,
    );
  }

  /// The change type.
  final int type;

  /// The file's URI.
  final String uri;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['type'] = type;
    __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 (!(type is int)) {
          reporter.reportError('must be of type int');
          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) {
    if (other is FileEvent && other.runtimeType == FileEvent) {
      return type == other.type && uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        type,
        uri,
      );

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

/// A filter to describe in which file operation requests or notifications the
/// server is interested in.
///  @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 like `file` or `untitled`.
  final String? scheme;

  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) {
    if (other is FileOperationFilter &&
        other.runtimeType == FileOperationFilter) {
      return pattern == other.pattern && scheme == other.scheme && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        pattern,
        scheme,
      );

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

/// A pattern to describe in which file operation requests or notifications the
/// server is interested in.
///  @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;

  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) {
    if (other is FileOperationPattern &&
        other.runtimeType == FileOperationPattern) {
      return glob == other.glob &&
          matches == other.matches &&
          options == other.options &&
          true;
    }
    return false;
  }

  @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 {
  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');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is FileOperationPatternKind && o._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;

  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) {
    if (other is FileOperationPatternOptions &&
        other.runtimeType == FileOperationPatternOptions) {
      return ignoreCase == other.ignoreCase && true;
    }
    return false;
  }

  @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;

  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.every(
                (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) {
    if (other is FileOperationRegistrationOptions &&
        other.runtimeType == FileOperationRegistrationOptions) {
      return listEqual(filters, other.filters,
              (FileOperationFilter a, FileOperationFilter b) => a == b) &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is FileRename && other.runtimeType == FileRename) {
      return newUri == other.newUri && oldUri == other.oldUri && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is FileSystemWatcher && other.runtimeType == FileSystemWatcher) {
      return globPattern == other.globPattern && kind == other.kind && true;
    }
    return false;
  }

  @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 - proposed
  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;

  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) {
    if (other is FoldingRange && other.runtimeType == FoldingRange) {
      return collapsedText == other.collapsedText &&
          endCharacter == other.endCharacter &&
          endLine == other.endLine &&
          kind == other.kind &&
          startCharacter == other.startCharacter &&
          startLine == other.startLine &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is FoldingRangeClientCapabilities &&
        other.runtimeType == FoldingRangeClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          foldingRange == other.foldingRange &&
          foldingRangeKind == other.foldingRangeKind &&
          lineFoldingOnly == other.lineFoldingOnly &&
          rangeLimit == other.rangeLimit &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is FoldingRangeClientCapabilitiesFoldingRange &&
        other.runtimeType == FoldingRangeClientCapabilitiesFoldingRange) {
      return collapsedText == other.collapsedText && true;
    }
    return false;
  }

  @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;

  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.every(
                    (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) {
    if (other is FoldingRangeClientCapabilitiesFoldingRangeKind &&
        other.runtimeType == FoldingRangeClientCapabilitiesFoldingRangeKind) {
      return listEqual(valueSet, other.valueSet,
              (FoldingRangeKind a, FoldingRangeKind b) => a == b) &&
          true;
    }
    return false;
  }

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

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

/// A set of predefined range kinds.
class FoldingRangeKind {
  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 a imports or includes
  static const Imports = FoldingRangeKind('imports');

  /// Folding range for a region (e.g. `#region`)
  static const Region = FoldingRangeKind('region');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is FoldingRangeKind && o._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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is FoldingRangeOptions &&
        other.runtimeType == FoldingRangeOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class FoldingRangeParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is FoldingRangeParams &&
        other.runtimeType == FoldingRangeParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class FoldingRangeRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        FoldingRangeOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is FoldingRangeRegistrationOptions &&
        other.runtimeType == FoldingRangeRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is FormattingOptions && other.runtimeType == FormattingOptions) {
      return insertFinalNewline == other.insertFinalNewline &&
          insertSpaces == other.insertSpaces &&
          tabSize == other.tabSize &&
          trimFinalNewlines == other.trimFinalNewlines &&
          trimTrailingWhitespace == other.trimTrailingWhitespace &&
          true;
    }
    return false;
  }

  @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 (RelatedFullDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return RelatedFullDocumentDiagnosticReport.fromJson(json);
    }
    if (WorkspaceFullDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceFullDocumentDiagnosticReport.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;

  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.every((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) {
    if (other is FullDocumentDiagnosticReport &&
        other.runtimeType == FullDocumentDiagnosticReport) {
      return listEqual(
              items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
          kind == other.kind &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

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

  @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 is a range inside a text document that is used to
  /// visualize a hover, e.g. by changing the background color.
  final Range? range;

  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) {
    if (other is Hover && other.runtimeType == Hover) {
      return contents == other.contents && range == other.range && true;
    }
    return false;
  }

  @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 follow content formats if the content property refers
  /// to a `literal of type MarkupContent`. The order describes the preferred
  /// format of the client.
  final List<MarkupKind>? contentFormat;

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

  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
                    .every((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) {
    if (other is HoverClientCapabilities &&
        other.runtimeType == HoverClientCapabilities) {
      return listEqual(contentFormat, other.contentFormat,
              (MarkupKind a, MarkupKind b) => a == b) &&
          dynamicRegistration == other.dynamicRegistration &&
          true;
    }
    return false;
  }

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

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

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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is HoverOptions && other.runtimeType == HoverOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

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.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is HoverParams && other.runtimeType == HoverParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

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

  HoverParamsPosition({
    required this.character,
    required this.line,
  });
  static HoverParamsPosition fromJson(Map<String, Object?> json) {
    final characterJson = json['character'];
    final character = characterJson as int;
    final lineJson = json['line'];
    final line = lineJson as int;
    return HoverParamsPosition(
      character: character,
      line: line,
    );
  }

  final int character;
  final int line;

  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 HoverParamsPosition');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is HoverParamsPosition &&
        other.runtimeType == HoverParamsPosition) {
      return character == other.character && line == other.line && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        character,
        line,
      );

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

class HoverRegistrationOptions
    implements TextDocumentRegistrationOptions, HoverOptions, 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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is HoverRegistrationOptions &&
        other.runtimeType == HoverRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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

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

  final String value;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['value'] = value;
    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 (!(value is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type HoverResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is HoverResult && other.runtimeType == HoverResult) {
      return value == other.value && true;
    }
    return false;
  }

  @override
  int get hashCode => value.hashCode;

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

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;

  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) {
    if (other is ImplementationClientCapabilities &&
        other.runtimeType == ImplementationClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          linkSupport == other.linkSupport &&
          true;
    }
    return false;
  }

  @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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is ImplementationOptions &&
        other.runtimeType == ImplementationOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class ImplementationParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        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.
  final Either2<int, String>? partialResultToken;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is ImplementationParams &&
        other.runtimeType == ImplementationParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class ImplementationRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        ImplementationOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is ImplementationRegistrationOptions &&
        other.runtimeType == ImplementationRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

/// Known error codes for an `InitializeErrorCodes`;
class InitializeErrorCodes {
  const InitializeErrorCodes(this._value);
  const InitializeErrorCodes.fromJson(this._value);

  final int _value;

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is InitializeErrorCodes && o._value == _value;
}

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', 'verbose'}.contains(traceJson)
        ? traceJson as String?
        : throw '''$traceJson was not one of (null, 'off', 'messages', '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 (see exit notification) its
  /// process.
  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.
  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;

  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 == 'verbose'))) {
          reporter.reportError(
              'must be one of the literals \'off\', \'messages\', \'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.every(
                    (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) {
    if (other is InitializeParams && other.runtimeType == InitializeParams) {
      return 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) &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is InitializeParamsClientInfo &&
        other.runtimeType == InitializeParamsClientInfo) {
      return name == other.name && version == other.version && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        name,
        version,
      );

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

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;

  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) {
    if (other is InitializeResult && other.runtimeType == InitializeResult) {
      return capabilities == other.capabilities &&
          serverInfo == other.serverInfo &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is InitializeResultServerInfo &&
        other.runtimeType == InitializeResultServerInfo) {
      return name == other.name && version == other.version && true;
    }
    return false;
  }

  @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();
  }

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    return __result;
  }

  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) {
    if (other is InitializedParams && other.runtimeType == InitializedParams) {
      return true;
    }
    return false;
  }

  @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 a 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.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final List<TextEdit>? textEdits;

  /// The tooltip text when you hover over this item.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final Either2<MarkupContent, String>? tooltip;

  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.every(
                    (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
                    .every((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) {
    if (other is InlayHint && other.runtimeType == InlayHint) {
      return 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 &&
          true;
    }
    return false;
  }

  @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 a inlay hint.
  final InlayHintClientCapabilitiesResolveSupport? resolveSupport;

  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) {
    if (other is InlayHintClientCapabilities &&
        other.runtimeType == InlayHintClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          resolveSupport == other.resolveSupport &&
          true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is InlayHintClientCapabilitiesResolveSupport &&
        other.runtimeType == InlayHintClientCapabilitiesResolveSupport) {
      return listEqual(
              properties, other.properties, (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

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

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

/// Inlay hint kinds.
///  @since 3.17.0
class InlayHintKind {
  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 for a type annotation.
  static const Type = InlayHintKind(1);

  /// An inlay hint that is for a parameter.
  static const Parameter = InlayHintKind(2);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is InlayHintKind && o._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;

  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) {
    if (other is InlayHintLabelPart &&
        other.runtimeType == InlayHintLabelPart) {
      return command == other.command &&
          location == other.location &&
          tooltip == other.tooltip &&
          value == other.value &&
          true;
    }
    return false;
  }

  @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;
  final bool? workDoneProgress;

  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) {
    if (other is InlayHintOptions && other.runtimeType == InlayHintOptions) {
      return resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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 visible 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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is InlayHintParams && other.runtimeType == InlayHintParams) {
      return range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @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,
        TextDocumentRegistrationOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  /// The server provides support to resolve additional information for an inlay
  /// hint item.
  final bool? resolveProvider;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is InlayHintRegistrationOptions &&
        other.runtimeType == InlayHintRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is InlayHintWorkspaceClientCapabilities &&
        other.runtimeType == InlayHintWorkspaceClientCapabilities) {
      return refreshSupport == other.refreshSupport && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is InlineValueClientCapabilities &&
        other.runtimeType == InlineValueClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @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.stoppedLocation,
  });
  static InlineValueContext fromJson(Map<String, Object?> json) {
    final stoppedLocationJson = json['stoppedLocation'];
    final stoppedLocation =
        Range.fromJson(stoppedLocationJson as Map<String, Object?>);
    return InlineValueContext(
      stoppedLocation: stoppedLocation,
    );
  }

  /// 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;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['stoppedLocation'] = stoppedLocation.toJson();
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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) {
    if (other is InlineValueContext &&
        other.runtimeType == InlineValueContext) {
      return stoppedLocation == other.stoppedLocation && true;
    }
    return false;
  }

  @override
  int get hashCode => stoppedLocation.hashCode;

  @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;

  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) {
    if (other is InlineValueEvaluatableExpression &&
        other.runtimeType == InlineValueEvaluatableExpression) {
      return expression == other.expression && range == other.range && true;
    }
    return false;
  }

  @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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is InlineValueOptions &&
        other.runtimeType == InlineValueOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is InlineValueParams && other.runtimeType == InlineValueParams) {
      return context == other.context &&
          range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @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,
        TextDocumentRegistrationOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is InlineValueRegistrationOptions &&
        other.runtimeType == InlineValueRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is InlineValueText && other.runtimeType == InlineValueText) {
      return range == other.range && text == other.text && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is InlineValueVariableLookup &&
        other.runtimeType == InlineValueVariableLookup) {
      return caseSensitiveLookup == other.caseSensitiveLookup &&
          range == other.range &&
          variableName == other.variableName &&
          true;
    }
    return false;
  }

  @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 detect a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  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) {
    if (other is InlineValueWorkspaceClientCapabilities &&
        other.runtimeType == InlineValueWorkspaceClientCapabilities) {
      return refreshSupport == other.refreshSupport && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is InsertReplaceEdit && other.runtimeType == InsertReplaceEdit) {
      return insert == other.insert &&
          newText == other.newText &&
          replace == other.replace &&
          true;
    }
    return false;
  }

  @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 {
  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.
  static const Snippet = InsertTextFormat._(2);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is InsertTextFormat && o._value == _value;
}

/// How whitespace and indentation is handled during completion item insertion.
///  @since 3.16.0
class InsertTextMode {
  const InsertTextMode(this._value);
  const InsertTextMode.fromJson(this._value);

  final int _value;

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

  /// 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);

  /// 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);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is InsertTextMode && o._value == _value;
}

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;

  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) {
    if (other is LinkedEditingRangeClientCapabilities &&
        other.runtimeType == LinkedEditingRangeClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is LinkedEditingRangeOptions &&
        other.runtimeType == LinkedEditingRangeOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @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.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is LinkedEditingRangeParams &&
        other.runtimeType == LinkedEditingRangeParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class LinkedEditingRangeRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        LinkedEditingRangeOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is LinkedEditingRangeRegistrationOptions &&
        other.runtimeType == LinkedEditingRangeRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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 renamed 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;

  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.every((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) {
    if (other is LinkedEditingRanges &&
        other.runtimeType == LinkedEditingRanges) {
      return listEqual(ranges, other.ranges, (Range a, Range b) => a == b) &&
          wordPattern == other.wordPattern &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(ranges),
        wordPattern,
      );

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

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;

  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) {
    if (other is Location && other.runtimeType == Location) {
      return range == other.range && uri == other.uri && true;
    }
    return false;
  }

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

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

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 mouse 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 the
  /// `targetRange`. See also `DocumentSymbol#range`
  final Range targetSelectionRange;

  /// The target resource identifier of this link.
  final String targetUri;

  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) {
    if (other is LocationLink && other.runtimeType == LocationLink) {
      return originSelectionRange == other.originSelectionRange &&
          targetRange == other.targetRange &&
          targetSelectionRange == other.targetSelectionRange &&
          targetUri == other.targetUri &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        originSelectionRange,
        targetRange,
        targetSelectionRange,
        targetUri,
      );

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

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.
  final MessageType type;

  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) {
    if (other is LogMessageParams && other.runtimeType == LogMessageParams) {
      return message == other.message && type == other.type && true;
    }
    return false;
  }

  @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,
    );
  }

  /// The message to be logged.
  final String message;

  /// Additional information that can be computed if the `trace` configuration
  /// is set to `'verbose'`
  final String? verbose;

  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) {
    if (other is LogTraceParams && other.runtimeType == LogTraceParams) {
      return message == other.message && verbose == other.verbose && true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is MarkdownClientCapabilities &&
        other.runtimeType == MarkdownClientCapabilities) {
      return listEqual(
              allowedTags, other.allowedTags, (String a, String b) => a == b) &&
          parser == other.parser &&
          version == other.version &&
          true;
    }
    return false;
  }

  @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.
///
/// Here is an example how such a string can be constructed using JavaScript /
/// TypeScript: ```typescript 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;

  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) {
    if (other is MarkupContent && other.runtimeType == MarkupContent) {
      return kind == other.kind && value == other.value && true;
    }
    return false;
  }

  @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 {
  const MarkupKind._(this._value);
  const MarkupKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'plaintext':
      case 'markdown':
        return true;
    }
    return false;
  }

  /// Plain text is supported as a content format
  static const PlainText = MarkupKind._('plaintext');

  /// Markdown is supported as a content format
  static const Markdown = MarkupKind._('markdown');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is MarkupKind && o._value == _value;
}

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

  Message({
    this.clientRequestTime,
    required this.jsonrpc,
  });
  static Message fromJson(Map<String, Object?> json) {
    if (RequestMessage.canParse(json, nullLspJsonReporter)) {
      return RequestMessage.fromJson(json);
    }
    if (ResponseMessage.canParse(json, nullLspJsonReporter)) {
      return ResponseMessage.fromJson(json);
    }
    if (NotificationMessage.canParse(json, nullLspJsonReporter)) {
      return NotificationMessage.fromJson(json);
    }
    final clientRequestTimeJson = json['clientRequestTime'];
    final clientRequestTime = clientRequestTimeJson as int?;
    final jsonrpcJson = json['jsonrpc'];
    final jsonrpc = jsonrpcJson as String;
    return Message(
      clientRequestTime: clientRequestTime,
      jsonrpc: jsonrpc,
    );
  }

  final int? clientRequestTime;
  final String jsonrpc;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (clientRequestTime != null) {
      __result['clientRequestTime'] = clientRequestTime;
    }
    __result['jsonrpc'] = jsonrpc;
    return __result;
  }

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

  @override
  bool operator ==(Object other) {
    if (other is Message && other.runtimeType == Message) {
      return clientRequestTime == other.clientRequestTime &&
          jsonrpc == other.jsonrpc &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        clientRequestTime,
        jsonrpc,
      );

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

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;

  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) {
    if (other is MessageActionItem && other.runtimeType == MessageActionItem) {
      return title == other.title && true;
    }
    return false;
  }

  @override
  int get hashCode => title.hashCode;

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

class MessageType {
  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);

  /// A warning message.
  static const Warning = MessageType(2);

  /// An information message.
  static const Info = MessageType(3);

  /// A log message.
  static const Log = MessageType(4);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is MessageType && o._value == _value;
}

/// Valid LSP methods known at the time of code generation from the spec.
class Method {
  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 '$/cancelRequest' method.
  static const cancelRequest = Method(r'$/cancelRequest');

  /// Constant for the '$/progress' method.
  static const progress = Method(r'$/progress');

  /// Constant for the 'initialize' method.
  static const initialize = Method('initialize');

  /// Constant for the 'initialized' method.
  static const initialized = Method('initialized');

  /// 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 '$/setTrace' method.
  static const setTrace = Method(r'$/setTrace');

  /// Constant for the '$/logTrace' method.
  static const logTrace = Method(r'$/logTrace');

  /// Constant for the 'shutdown' method.
  static const shutdown = Method('shutdown');

  /// Constant for the 'exit' method.
  static const exit = Method('exit');

  /// Constant for the 'textDocument/didOpen' method.
  static const textDocument_didOpen = Method('textDocument/didOpen');

  /// Constant for the 'textDocument/didChange' method.
  static const textDocument_didChange = Method('textDocument/didChange');

  /// 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 'textDocument/didSave' method.
  static const textDocument_didSave = Method('textDocument/didSave');

  /// Constant for the 'textDocument/didClose' method.
  static const textDocument_didClose = Method('textDocument/didClose');

  /// Constant for the 'notebookDocument/didOpen' method.
  static const notebookDocument_didOpen = Method('notebookDocument/didOpen');

  /// Constant for the 'notebookDocument/didChange' method.
  static const notebookDocument_didChange =
      Method('notebookDocument/didChange');

  /// Constant for the 'notebookDocument/didSave' method.
  static const notebookDocument_didSave = Method('notebookDocument/didSave');

  /// Constant for the 'notebookDocument/didClose' method.
  static const notebookDocument_didClose = Method('notebookDocument/didClose');

  /// 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/typeDefinition' method.
  static const textDocument_typeDefinition =
      Method('textDocument/typeDefinition');

  /// Constant for the 'textDocument/implementation' method.
  static const textDocument_implementation =
      Method('textDocument/implementation');

  /// Constant for the 'textDocument/references' method.
  static const textDocument_references = Method('textDocument/references');

  /// Constant for the 'textDocument/prepareCallHierarchy' method.
  static const textDocument_prepareCallHierarchy =
      Method('textDocument/prepareCallHierarchy');

  /// 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 'textDocument/prepareTypeHierarchy' method.
  static const textDocument_prepareTypeHierarchy =
      Method('textDocument/prepareTypeHierarchy');

  /// Constant for the 'typeHierarchy/supertypes' method.
  static const typeHierarchy_supertypes = Method('typeHierarchy/supertypes');

  /// Constant for the 'typeHierarchy/subtypes' method.
  static const typeHierarchy_subtypes = Method('typeHierarchy/subtypes');

  /// 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 'documentLink/resolve' method.
  static const documentLink_resolve = Method('documentLink/resolve');

  /// Constant for the 'textDocument/hover' method.
  static const textDocument_hover = Method('textDocument/hover');

  /// Constant for the 'textDocument/codeLens' method.
  static const textDocument_codeLens = Method('textDocument/codeLens');

  /// Constant for the 'codeLens/resolve' method.
  static const codeLens_resolve = Method('codeLens/resolve');

  /// Constant for the 'workspace/codeLens/refresh' method.
  static const workspace_codeLens_refresh =
      Method('workspace/codeLens/refresh');

  /// Constant for the 'textDocument/foldingRange' method.
  static const textDocument_foldingRange = Method('textDocument/foldingRange');

  /// Constant for the 'textDocument/selectionRange' method.
  static const textDocument_selectionRange =
      Method('textDocument/selectionRange');

  /// Constant for the 'textDocument/documentSymbol' method.
  static const textDocument_documentSymbol =
      Method('textDocument/documentSymbol');

  /// 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 'workspace/semanticTokens/refresh' method.
  static const workspace_semanticTokens_refresh =
      Method('workspace/semanticTokens/refresh');

  /// Constant for the 'textDocument/inlayHint' method.
  static const textDocument_inlayHint = Method('textDocument/inlayHint');

  /// Constant for the 'inlayHint/resolve' method.
  static const inlayHint_resolve = Method('inlayHint/resolve');

  /// Constant for the 'workspace/inlayHint/refresh' method.
  static const workspace_inlayHint_refresh =
      Method('workspace/inlayHint/refresh');

  /// Constant for the 'textDocument/inlineValue' method.
  static const textDocument_inlineValue = Method('textDocument/inlineValue');

  /// Constant for the 'workspace/inlineValue/refresh' method.
  static const workspace_inlineValue_refresh =
      Method('workspace/inlineValue/refresh');

  /// Constant for the 'textDocument/moniker' method.
  static const textDocument_moniker = Method('textDocument/moniker');

  /// Constant for the 'textDocument/completion' method.
  static const textDocument_completion = Method('textDocument/completion');

  /// Constant for the 'completionItem/resolve' method.
  static const completionItem_resolve = Method('completionItem/resolve');

  /// Constant for the 'textDocument/publishDiagnostics' method.
  static const textDocument_publishDiagnostics =
      Method('textDocument/publishDiagnostics');

  /// Constant for the 'workspace/diagnostic/refresh' method.
  static const workspace_diagnostic_refresh =
      Method('workspace/diagnostic/refresh');

  /// Constant for the 'textDocument/signatureHelp' method.
  static const textDocument_signatureHelp =
      Method('textDocument/signatureHelp');

  /// Constant for the 'textDocument/codeAction' method.
  static const textDocument_codeAction = Method('textDocument/codeAction');

  /// Constant for the 'codeAction/resolve' method.
  static const codeAction_resolve = Method('codeAction/resolve');

  /// Constant for the 'textDocument/documentColor' method.
  static const textDocument_documentColor =
      Method('textDocument/documentColor');

  /// Constant for the 'textDocument/colorPresentation' method.
  static const textDocument_colorPresentation =
      Method('textDocument/colorPresentation');

  /// Constant for the 'textDocument/formatting' method.
  static const textDocument_formatting = Method('textDocument/formatting');

  /// Constant for the 'textDocument/rangeFormatting' method.
  static const textDocument_rangeFormatting =
      Method('textDocument/rangeFormatting');

  /// Constant for the 'textDocument/onTypeFormatting' method.
  static const textDocument_onTypeFormatting =
      Method('textDocument/onTypeFormatting');

  /// Constant for the 'textDocument/rename' method.
  static const textDocument_rename = Method('textDocument/rename');

  /// Constant for the 'textDocument/prepareRename' method.
  static const textDocument_prepareRename =
      Method('textDocument/prepareRename');

  /// Constant for the 'textDocument/linkedEditingRange' method.
  static const textDocument_linkedEditingRange =
      Method('textDocument/linkedEditingRange');

  /// Constant for the 'workspace/symbol' method.
  static const workspace_symbol = Method('workspace/symbol');

  /// Constant for the 'workspaceSymbol/resolve' method.
  static const workspaceSymbol_resolve = Method('workspaceSymbol/resolve');

  /// Constant for the 'workspace/configuration' method.
  static const workspace_configuration = Method('workspace/configuration');

  /// Constant for the 'workspace/didChangeConfiguration' method.
  static const workspace_didChangeConfiguration =
      Method('workspace/didChangeConfiguration');

  /// Constant for the 'workspace/workspaceFolders' method.
  static const workspace_workspaceFolders =
      Method('workspace/workspaceFolders');

  /// Constant for the 'workspace/didChangeWorkspaceFolders' method.
  static const workspace_didChangeWorkspaceFolders =
      Method('workspace/didChangeWorkspaceFolders');

  /// Constant for the 'workspace/willCreateFiles' method.
  static const workspace_willCreateFiles = Method('workspace/willCreateFiles');

  /// Constant for the 'workspace/didCreateFiles' method.
  static const workspace_didCreateFiles = Method('workspace/didCreateFiles');

  /// Constant for the 'workspace/willRenameFiles' method.
  static const workspace_willRenameFiles = Method('workspace/willRenameFiles');

  /// Constant for the 'workspace/didRenameFiles' method.
  static const workspace_didRenameFiles = Method('workspace/didRenameFiles');

  /// Constant for the 'workspace/willDeleteFiles' method.
  static const workspace_willDeleteFiles = Method('workspace/willDeleteFiles');

  /// Constant for the 'workspace/didDeleteFiles' method.
  static const workspace_didDeleteFiles = Method('workspace/didDeleteFiles');

  /// Constant for the 'workspace/didChangeWatchedFiles' method.
  static const workspace_didChangeWatchedFiles =
      Method('workspace/didChangeWatchedFiles');

  /// Constant for the 'workspace/executeCommand' method.
  static const workspace_executeCommand = Method('workspace/executeCommand');

  /// Constant for the 'workspace/applyEdit' method.
  static const workspace_applyEdit = Method('workspace/applyEdit');

  /// 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/showDocument' method.
  static const window_showDocument = Method('window/showDocument');

  /// Constant for the 'window/logMessage' method.
  static const window_logMessage = Method('window/logMessage');

  /// Constant for the 'window/workDoneProgress/create' method.
  static const window_workDoneProgress_create =
      Method('window/workDoneProgress/create');

  /// Constant for the 'window/workDoneProgress/cancel' method.
  static const window_workDoneProgress_cancel =
      Method('window/workDoneProgress/cancel');

  /// Constant for the 'telemetry/event' method.
  static const telemetry_event = Method('telemetry/event');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is Method && o._value == _value;
}

/// Moniker definition to match LSIF 0.5 moniker definition.
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;

  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) {
    if (other is Moniker && other.runtimeType == Moniker) {
      return identifier == other.identifier &&
          kind == other.kind &&
          scheme == other.scheme &&
          unique == other.unique &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        identifier,
        kind,
        scheme,
        unique,
      );

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

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 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;

  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) {
    if (other is MonikerClientCapabilities &&
        other.runtimeType == MonikerClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

/// The moniker kind.
class MonikerKind {
  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 represent a symbol that is imported into a project
  static const import = MonikerKind('import');

  /// The moniker represents a symbol that is exported from a project
  static const export = MonikerKind('export');

  /// 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');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is MonikerKind && o._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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is MonikerOptions && other.runtimeType == MonikerOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class MonikerParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        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.
  final Either2<int, String>? partialResultToken;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is MonikerParams && other.runtimeType == MonikerParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class MonikerRegistrationOptions
    implements TextDocumentRegistrationOptions, MonikerOptions, 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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is MonikerRegistrationOptions &&
        other.runtimeType == MonikerRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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.
  final Object? metadata;

  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) {
    if (other is NotebookCell && other.runtimeType == NotebookCell) {
      return document == other.document &&
          executionSummary == other.executionSummary &&
          kind == other.kind &&
          metadata == other.metadata &&
          true;
    }
    return false;
  }

  @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;

  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.every(
                    (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) {
    if (other is NotebookCellArrayChange &&
        other.runtimeType == NotebookCellArrayChange) {
      return listEqual(
              cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
          deleteCount == other.deleteCount &&
          start == other.start &&
          true;
    }
    return false;
  }

  @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 {
  const NotebookCellKind(this._value);
  const NotebookCellKind.fromJson(this._value);

  final int _value;

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

  /// A markup-cell is formatted source that is used for display.
  static const Markup = NotebookCellKind(1);

  /// A code-cell is source code.
  static const Code = NotebookCellKind(2);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is NotebookCellKind && o._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;

  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) {
    if (other is NotebookCellTextDocumentFilter &&
        other.runtimeType == NotebookCellTextDocumentFilter) {
      return language == other.language && notebook == other.notebook && true;
    }
    return false;
  }

  @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.
  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;

  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.every((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) {
    if (other is NotebookDocument && other.runtimeType == NotebookDocument) {
      return listEqual(
              cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
          metadata == other.metadata &&
          notebookType == other.notebookType &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

  @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.
  final Object? metadata;

  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) {
    if (other is NotebookDocumentChangeEvent &&
        other.runtimeType == NotebookDocumentChangeEvent) {
      return cells == other.cells && metadata == other.metadata && true;
    }
    return false;
  }

  @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
        ? NotebookDocumentChangeEventStructure.fromJson(
            structureJson as Map<String, Object?>)
        : null;
    final textContentJson = json['textContent'];
    final textContent = (textContentJson as List<Object?>?)
        ?.map((item) => NotebookDocumentChangeEventTextContent.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 NotebookDocumentChangeEventStructure? structure;

  /// Changes to the text content of notebook cells.
  final List<NotebookDocumentChangeEventTextContent>? textContent;

  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.every(
                    (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 &&
            !(NotebookDocumentChangeEventStructure.canParse(
                structure, reporter))) {
          reporter.reportError(
              'must be of type NotebookDocumentChangeEventStructure');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textContent');
      try {
        final textContent = obj['textContent'];
        if (textContent != null &&
            !((textContent is List<Object?> &&
                (textContent.every((item) =>
                    NotebookDocumentChangeEventTextContent.canParse(
                        item, reporter)))))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentChangeEventTextContent>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentChangeEventCells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentChangeEventCells &&
        other.runtimeType == NotebookDocumentChangeEventCells) {
      return listEqual(
              data, other.data, (NotebookCell a, NotebookCell b) => a == b) &&
          structure == other.structure &&
          listEqual(
              textContent,
              other.textContent,
              (NotebookDocumentChangeEventTextContent a,
                      NotebookDocumentChangeEventTextContent b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        structure,
        lspHashCode(textContent),
      );

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

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

  NotebookDocumentChangeEventStructure({
    required this.array,
    this.didClose,
    this.didOpen,
  });
  static NotebookDocumentChangeEventStructure 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 NotebookDocumentChangeEventStructure(
      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;

  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.every((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.every(
                    (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 NotebookDocumentChangeEventStructure');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentChangeEventStructure &&
        other.runtimeType == NotebookDocumentChangeEventStructure) {
      return array == other.array &&
          listEqual(didClose, other.didClose,
              (TextDocumentIdentifier a, TextDocumentIdentifier b) => a == b) &&
          listEqual(didOpen, other.didOpen,
              (TextDocumentItem a, TextDocumentItem b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        array,
        lspHashCode(didClose),
        lspHashCode(didOpen),
      );

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

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

  NotebookDocumentChangeEventTextContent({
    required this.changes,
    required this.document,
  });
  static NotebookDocumentChangeEventTextContent 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 NotebookDocumentChangeEventTextContent(
      changes: changes,
      document: document,
    );
  }

  final List<
      Either2<TextDocumentContentChangeEvent1,
          TextDocumentContentChangeEvent2>> changes;
  final VersionedTextDocumentIdentifier document;

  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.every((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 NotebookDocumentChangeEventTextContent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentChangeEventTextContent &&
        other.runtimeType == NotebookDocumentChangeEventTextContent) {
      return listEqual(
              changes,
              other.changes,
              (Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          a,
                      Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          b) =>
                  a == b) &&
          document == other.document &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is NotebookDocumentClientCapabilities &&
        other.runtimeType == NotebookDocumentClientCapabilities) {
      return synchronization == other.synchronization && true;
    }
    return false;
  }

  @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](#Uri.scheme), like `file` or `untitled`.
  final String? scheme;

  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) {
    if (other is NotebookDocumentFilter1 &&
        other.runtimeType == NotebookDocumentFilter1) {
      return notebookType == other.notebookType &&
          pattern == other.pattern &&
          scheme == other.scheme &&
          true;
    }
    return false;
  }

  @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](#Uri.scheme), like `file` or `untitled`.
  final String scheme;

  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) {
    if (other is NotebookDocumentFilter2 &&
        other.runtimeType == NotebookDocumentFilter2) {
      return notebookType == other.notebookType &&
          pattern == other.pattern &&
          scheme == other.scheme &&
          true;
    }
    return false;
  }

  @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](#Uri.scheme), like `file` or `untitled`.
  final String? scheme;

  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) {
    if (other is NotebookDocumentFilter3 &&
        other.runtimeType == NotebookDocumentFilter3) {
      return notebookType == other.notebookType &&
          pattern == other.pattern &&
          scheme == other.scheme &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is NotebookDocumentIdentifier &&
        other.runtimeType == NotebookDocumentIdentifier) {
      return uri == other.uri && true;
    }
    return false;
  }

  @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,
  });
  static NotebookDocumentSyncClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return NotebookDocumentSyncClientCapabilities(
      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;

  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 NotebookDocumentSyncClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncClientCapabilities &&
        other.runtimeType == NotebookDocumentSyncClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

/// Options specific to a notebook plus its cells to be synced to the server.
///
/// If a selector provider 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.fromJson(
            item as Map<String, Object?>))
        .toList();
    final saveJson = json['save'];
    final save = saveJson as bool?;
    return NotebookDocumentSyncOptions(
      notebookSelector: notebookSelector,
      save: save,
    );
  }

  /// The notebooks to be synced
  final List<NotebookDocumentSyncOptionsNotebookSelector> notebookSelector;

  /// Whether save notification should be forwarded to the server. Will only be
  /// honored if mode === `notebook`.
  final bool? save;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['notebookSelector'] =
        notebookSelector.map((item) => item.toJson()).toList();
    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.every((item) =>
                NotebookDocumentSyncOptionsNotebookSelector.canParse(
                    item, reporter)))))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentSyncOptionsNotebookSelector>');
          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) {
    if (other is NotebookDocumentSyncOptions &&
        other.runtimeType == NotebookDocumentSyncOptions) {
      return listEqual(
              notebookSelector,
              other.notebookSelector,
              (NotebookDocumentSyncOptionsNotebookSelector a,
                      NotebookDocumentSyncOptionsNotebookSelector b) =>
                  a == b) &&
          save == other.save &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(notebookSelector),
        save,
      );

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

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

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

  final String language;

  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 NotebookDocumentSyncOptionsCells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncOptionsCells &&
        other.runtimeType == NotebookDocumentSyncOptionsCells) {
      return language == other.language && true;
    }
    return false;
  }

  @override
  int get hashCode => language.hashCode;

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

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

  NotebookDocumentSyncOptionsNotebookSelector({
    required this.cells,
    this.notebookDocument,
  });
  static NotebookDocumentSyncOptionsNotebookSelector fromJson(
      Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>)
        .map((item) => NotebookDocumentSyncOptionsCells.fromJson(
            item as Map<String, Object?>))
        .toList();
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument = notebookDocumentJson == null
        ? null
        : ((NotebookDocumentFilter1.canParse(notebookDocumentJson, nullLspJsonReporter) ||
                NotebookDocumentFilter2.canParse(
                    notebookDocumentJson, nullLspJsonReporter) ||
                NotebookDocumentFilter3.canParse(
                    notebookDocumentJson, nullLspJsonReporter))
            ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t1(
                NotebookDocumentFilter1.canParse(notebookDocumentJson, nullLspJsonReporter)
                    ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t1(
                        NotebookDocumentFilter1.fromJson(
                            notebookDocumentJson as Map<String, Object?>))
                    : (NotebookDocumentFilter2.canParse(notebookDocumentJson, nullLspJsonReporter)
                        ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t2(
                            NotebookDocumentFilter2.fromJson(notebookDocumentJson as Map<String, Object?>))
                        : (NotebookDocumentFilter3.canParse(notebookDocumentJson, nullLspJsonReporter) ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t3(NotebookDocumentFilter3.fromJson(notebookDocumentJson as Map<String, Object?>)) : (throw '''$notebookDocumentJson was not one of (NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3)'''))))
            : (notebookDocumentJson is String ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t2(notebookDocumentJson) : (throw '''$notebookDocumentJson was not one of (Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String)''')));
    return NotebookDocumentSyncOptionsNotebookSelector(
      cells: cells,
      notebookDocument: notebookDocument,
    );
  }

  /// The cells of the matching notebook to be synced.
  final List<NotebookDocumentSyncOptionsCells> 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>? notebookDocument;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['cells'] = cells.map((item) => item.toJson()).toList();
    if (notebookDocument != null) {
      __result['notebookDocument'] = notebookDocument;
    }
    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.every((item) =>
                NotebookDocumentSyncOptionsCells.canParse(item, reporter)))))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentSyncOptionsCells>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookDocument');
      try {
        final notebookDocument = obj['notebookDocument'];
        if (notebookDocument != null &&
            !(((NotebookDocumentFilter1.canParse(notebookDocument, reporter) ||
                    NotebookDocumentFilter2.canParse(
                        notebookDocument, reporter) ||
                    NotebookDocumentFilter3.canParse(
                        notebookDocument, reporter)) ||
                notebookDocument 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) {
    if (other is NotebookDocumentSyncOptionsNotebookSelector &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelector) {
      return listEqual(
              cells,
              other.cells,
              (NotebookDocumentSyncOptionsCells a,
                      NotebookDocumentSyncOptionsCells b) =>
                  a == b) &&
          notebookDocument == other.notebookDocument &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        notebookDocument,
      );

  @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.fromJson(
            item as Map<String, Object?>))
        .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.
  final String? id;

  /// The notebooks to be synced
  final List<NotebookDocumentSyncOptionsNotebookSelector> notebookSelector;

  /// Whether save notification should be forwarded to the server. Will only be
  /// honored if mode === `notebook`.
  final bool? save;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (id != null) {
      __result['id'] = id;
    }
    __result['notebookSelector'] =
        notebookSelector.map((item) => item.toJson()).toList();
    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.every((item) =>
                NotebookDocumentSyncOptionsNotebookSelector.canParse(
                    item, reporter)))))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentSyncOptionsNotebookSelector>');
          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) {
    if (other is NotebookDocumentSyncRegistrationOptions &&
        other.runtimeType == NotebookDocumentSyncRegistrationOptions) {
      return id == other.id &&
          listEqual(
              notebookSelector,
              other.notebookSelector,
              (NotebookDocumentSyncOptionsNotebookSelector a,
                      NotebookDocumentSyncOptionsNotebookSelector b) =>
                  a == b) &&
          save == other.save &&
          true;
    }
    return false;
  }

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

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

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

  NotificationMessage({
    this.clientRequestTime,
    required this.jsonrpc,
    required this.method,
    this.params,
  });
  static NotificationMessage fromJson(Map<String, Object?> json) {
    final clientRequestTimeJson = json['clientRequestTime'];
    final clientRequestTime = clientRequestTimeJson as int?;
    final jsonrpcJson = json['jsonrpc'];
    final jsonrpc = jsonrpcJson as String;
    final methodJson = json['method'];
    final method = Method.fromJson(methodJson as String);
    final paramsJson = json['params'];
    final params = paramsJson;
    return NotificationMessage(
      clientRequestTime: clientRequestTime,
      jsonrpc: jsonrpc,
      method: method,
      params: params,
    );
  }

  final int? clientRequestTime;
  final String jsonrpc;

  /// The method to be invoked.
  final Method method;

  /// The notification's params.
  final Object? params;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (clientRequestTime != null) {
      __result['clientRequestTime'] = clientRequestTime;
    }
    __result['jsonrpc'] = jsonrpc;
    __result['method'] = method.toJson();
    if (params != null) {
      __result['params'] = params;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('clientRequestTime');
      try {
        final clientRequestTime = obj['clientRequestTime'];
        if (clientRequestTime != null && !(clientRequestTime is int)) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('jsonrpc');
      try {
        if (!obj.containsKey('jsonrpc')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final jsonrpc = obj['jsonrpc'];
        if (jsonrpc == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(jsonrpc 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.canParse(method, reporter))) {
          reporter.reportError('must be of type Method');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotificationMessage');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotificationMessage &&
        other.runtimeType == NotificationMessage) {
      return clientRequestTime == other.clientRequestTime &&
          jsonrpc == other.jsonrpc &&
          method == other.method &&
          params == other.params &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        clientRequestTime,
        jsonrpc,
        method,
        params,
      );

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

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.
  final String uri;

  /// The version number of this document. If an optional 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 known
  /// and the content on disk is the master (as specified with document content
  /// ownership).
  ///
  /// The version number of a document will increase after each change,
  /// including undo/redo. The number doesn't need to be consecutive.
  final int? version;

  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) {
    if (other is OptionalVersionedTextDocumentIdentifier &&
        other.runtimeType == OptionalVersionedTextDocumentIdentifier) {
      return uri == other.uri && version == other.version && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is ParameterInformation &&
        other.runtimeType == ParameterInformation) {
      return documentation == other.documentation &&
          label == other.label &&
          true;
    }
    return false;
  }

  @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 (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (TypeHierarchySupertypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySupertypesParams.fromJson(json);
    }
    if (TypeHierarchySubtypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySubtypesParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (DocumentDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return DocumentDiagnosticParams.fromJson(json);
    }
    if (WorkspaceDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceDiagnosticParams.fromJson(json);
    }
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.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;

  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) {
    if (other is PartialResultParams &&
        other.runtimeType == PartialResultParams) {
      return partialResultToken == other.partialResultToken && true;
    }
    return false;
  }

  @override
  int get hashCode => partialResultToken.hashCode;

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

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).
  final int line;

  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) {
    if (other is Position && other.runtimeType == Position) {
      return character == other.character && line == other.line && true;
    }
    return false;
  }

  @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 {
  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-8 code units.
  static const UTF8 = PositionEncodingKind('utf-8');

  /// 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');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is PositionEncodingKind && o._value == _value;
}

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

  PrepareRenameParams({
    required this.position,
    required this.textDocument,
  });
  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?>);
    return PrepareRenameParams(
      position: position,
      textDocument: textDocument,
    );
  }

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

  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 PrepareRenameParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PrepareRenameParams &&
        other.runtimeType == PrepareRenameParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

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

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

class PrepareSupportDefaultBehavior {
  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);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is PrepareSupportDefaultBehavior && o._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;

  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) {
    if (other is PreviousResultId && other.runtimeType == PreviousResultId) {
      return uri == other.uri && value == other.value && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        value,
      );

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

class ProgressParams<T> implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ProgressParams.canParse,
    ProgressParams.fromJson,
  );

  ProgressParams({
    required this.token,
    this.value,
  });
  static ProgressParams<T> fromJson<T>(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<T>(
      token: token,
      value: value,
    );
  }

  /// The progress token provided by the client or server.
  final Either2<int, String> token;

  /// The progress data.
  final Object? value;

  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<T>');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ProgressParams && other.runtimeType == ProgressParams) {
      return token == other.token && value == other.value && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        token,
        value,
      );

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

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;

  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) {
    if (other is PublishDiagnosticsClientCapabilities &&
        other.runtimeType == PublishDiagnosticsClientCapabilities) {
      return codeDescriptionSupport == other.codeDescriptionSupport &&
          dataSupport == other.dataSupport &&
          relatedInformation == other.relatedInformation &&
          tagSupport == other.tagSupport &&
          versionSupport == other.versionSupport &&
          true;
    }
    return false;
  }

  @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;

  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
                .every((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) {
    if (other is PublishDiagnosticsClientCapabilitiesTagSupport &&
        other.runtimeType == PublishDiagnosticsClientCapabilitiesTagSupport) {
      return listEqual(valueSet, other.valueSet,
              (DiagnosticTag a, DiagnosticTag b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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;

  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
                .every((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) {
    if (other is PublishDiagnosticsParams &&
        other.runtimeType == PublishDiagnosticsParams) {
      return listEqual(diagnostics, other.diagnostics,
              (Diagnostic a, Diagnostic b) => a == b) &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is Range && other.runtimeType == Range) {
      return end == other.end && start == other.start && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        end,
        start,
      );

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

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

  RangeAndPlaceholder({
    required this.placeholder,
    required this.range,
  });
  static RangeAndPlaceholder 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 RangeAndPlaceholder(
      placeholder: placeholder,
      range: range,
    );
  }

  final String placeholder;
  final Range range;

  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 RangeAndPlaceholder');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RangeAndPlaceholder &&
        other.runtimeType == RangeAndPlaceholder) {
      return placeholder == other.placeholder && range == other.range && true;
    }
    return false;
  }

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

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

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;

  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) {
    if (other is ReferenceClientCapabilities &&
        other.runtimeType == ReferenceClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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;

  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) {
    if (other is ReferenceContext && other.runtimeType == ReferenceContext) {
      return includeDeclaration == other.includeDeclaration && true;
    }
    return false;
  }

  @override
  int get hashCode => includeDeclaration.hashCode;

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

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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is ReferenceOptions && other.runtimeType == ReferenceOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class ReferenceParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        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.
  final Either2<int, String>? partialResultToken;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is ReferenceParams && other.runtimeType == ReferenceParams) {
      return context == other.context &&
          partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class ReferenceRegistrationOptions
    implements TextDocumentRegistrationOptions, ReferenceOptions, 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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is ReferenceRegistrationOptions &&
        other.runtimeType == ReferenceRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

/// General parameters to register for a capability.
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;

  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) {
    if (other is Registration && other.runtimeType == Registration) {
      return id == other.id &&
          method == other.method &&
          registerOptions == other.registerOptions &&
          true;
    }
    return false;
  }

  @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;

  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
                .every((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) {
    if (other is RegistrationParams &&
        other.runtimeType == RegistrationParams) {
      return listEqual(registrations, other.registrations,
              (Registration a, Registration b) => a == b) &&
          true;
    }
    return false;
  }

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

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

/// Client capabilities specific to regular expressions.
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;

  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) {
    if (other is RegularExpressionsClientCapabilities &&
        other.runtimeType == RegularExpressionsClientCapabilities) {
      return engine == other.engine && version == other.version && true;
    }
    return false;
  }

  @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.
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  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.
  final String? resultId;

  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.every((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.every((item) =>
                    item is String &&
                    relatedDocuments.values.every((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) {
    if (other is RelatedFullDocumentDiagnosticReport &&
        other.runtimeType == RelatedFullDocumentDiagnosticReport) {
      return 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 &&
          true;
    }
    return false;
  }

  @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.
  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.
  final String resultId;

  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.every((item) =>
                    item is String &&
                    relatedDocuments.values.every((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) {
    if (other is RelatedUnchangedDocumentDiagnosticReport &&
        other.runtimeType == RelatedUnchangedDocumentDiagnosticReport) {
      return kind == other.kind &&
          mapEqual(
              relatedDocuments,
              other.relatedDocuments,
              (Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          a,
                      Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is RelativePattern && other.runtimeType == RelativePattern) {
      return baseUri == other.baseUri && pattern == other.pattern && true;
    }
    return false;
  }

  @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 th 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 version 3.12.0
  final bool? prepareSupport;

  /// Client supports the default behavior result (`{ defaultBehavior: boolean
  /// }`).
  ///
  /// The value indicates the default behavior used by the client.
  ///  @since version 3.16.0
  final PrepareSupportDefaultBehavior? prepareSupportDefaultBehavior;

  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) {
    if (other is RenameClientCapabilities &&
        other.runtimeType == RenameClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          honorsChangeAnnotations == other.honorsChangeAnnotations &&
          prepareSupport == other.prepareSupport &&
          prepareSupportDefaultBehavior ==
              other.prepareSupportDefaultBehavior &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        honorsChangeAnnotations,
        prepareSupport,
        prepareSupportDefaultBehavior,
      );

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

/// Rename file operation
class RenameFile implements 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
  final String? annotationId;

  /// A rename
  final String kind;

  /// The new location.
  final String newUri;

  /// The old (existing) location.
  final String oldUri;

  /// Rename options.
  final RenameFileOptions? options;

  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) {
    if (other is RenameFile && other.runtimeType == RenameFile) {
      return annotationId == other.annotationId &&
          kind == other.kind &&
          newUri == other.newUri &&
          oldUri == other.oldUri &&
          options == other.options &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is RenameFileOptions && other.runtimeType == RenameFileOptions) {
      return ignoreIfExists == other.ignoreIfExists &&
          overwrite == other.overwrite &&
          true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is RenameFilesParams && other.runtimeType == RenameFilesParams) {
      return listEqual(
              files, other.files, (FileRename a, FileRename b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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.
  final bool? prepareProvider;
  final bool? workDoneProgress;

  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) {
    if (other is RenameOptions && other.runtimeType == RenameOptions) {
      return prepareProvider == other.prepareProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

class RenameParams
    implements TextDocumentPositionParams, 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 inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is RenameParams && other.runtimeType == RenameParams) {
      return newName == other.newName &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class RenameRegistrationOptions
    implements TextDocumentRegistrationOptions, RenameOptions, 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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

  /// Renames should be checked and tested before being executed.
  final bool? prepareProvider;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is RenameRegistrationOptions &&
        other.runtimeType == RenameRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          prepareProvider == other.prepareProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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

  RequestMessage({
    this.clientRequestTime,
    required this.id,
    required this.jsonrpc,
    required this.method,
    this.params,
  });
  static RequestMessage fromJson(Map<String, Object?> json) {
    final clientRequestTimeJson = json['clientRequestTime'];
    final clientRequestTime = clientRequestTimeJson as int?;
    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)'''));
    final jsonrpcJson = json['jsonrpc'];
    final jsonrpc = jsonrpcJson as String;
    final methodJson = json['method'];
    final method = Method.fromJson(methodJson as String);
    final paramsJson = json['params'];
    final params = paramsJson;
    return RequestMessage(
      clientRequestTime: clientRequestTime,
      id: id,
      jsonrpc: jsonrpc,
      method: method,
      params: params,
    );
  }

  final int? clientRequestTime;

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

  /// The method to be invoked.
  final Method method;

  /// The method's params.
  final Object? params;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (clientRequestTime != null) {
      __result['clientRequestTime'] = clientRequestTime;
    }
    __result['id'] = id;
    __result['jsonrpc'] = jsonrpc;
    __result['method'] = method.toJson();
    if (params != null) {
      __result['params'] = params;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('clientRequestTime');
      try {
        final clientRequestTime = obj['clientRequestTime'];
        if (clientRequestTime != null && !(clientRequestTime is int)) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      reporter.push('jsonrpc');
      try {
        if (!obj.containsKey('jsonrpc')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final jsonrpc = obj['jsonrpc'];
        if (jsonrpc == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(jsonrpc 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.canParse(method, reporter))) {
          reporter.reportError('must be of type Method');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RequestMessage');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RequestMessage && other.runtimeType == RequestMessage) {
      return clientRequestTime == other.clientRequestTime &&
          id == other.id &&
          jsonrpc == other.jsonrpc &&
          method == other.method &&
          params == other.params &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        clientRequestTime,
        id,
        jsonrpc,
        method,
        params,
      );

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

class ResourceOperationKind {
  const ResourceOperationKind._(this._value);
  const ResourceOperationKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'create':
      case 'rename':
      case 'delete':
        return true;
    }
    return false;
  }

  /// Supports creating new files and folders.
  static const Create = ResourceOperationKind._('create');

  /// Supports renaming existing files and folders.
  static const Rename = ResourceOperationKind._('rename');

  /// Supports deleting existing files and folders.
  static const Delete = ResourceOperationKind._('delete');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is ResourceOperationKind && o._value == _value;
}

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

  ResponseError({
    required this.code,
    this.data,
    required this.message,
  });
  static ResponseError fromJson(Map<String, Object?> json) {
    final codeJson = json['code'];
    final code = ErrorCodes.fromJson(codeJson as int);
    final dataJson = json['data'];
    final data = dataJson as String?;
    final messageJson = json['message'];
    final message = messageJson as String;
    return ResponseError(
      code: code,
      data: data,
      message: message,
    );
  }

  /// A number indicating the error type that occurred.
  final ErrorCodes code;

  /// A string that contains additional information about the error. Can be
  /// omitted.
  final String? data;

  /// A string providing a short description of the error.
  final String message;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['code'] = code.toJson();
    if (data != null) {
      __result['data'] = data;
    }
    __result['message'] = message;
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('code');
      try {
        if (!obj.containsKey('code')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final code = obj['code'];
        if (code == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(ErrorCodes.canParse(code, reporter))) {
          reporter.reportError('must be of type ErrorCodes');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('data');
      try {
        final data = obj['data'];
        if (data != null && !(data is String)) {
          reporter.reportError('must be of type String');
          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 ResponseError');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ResponseError && other.runtimeType == ResponseError) {
      return code == other.code &&
          data == other.data &&
          message == other.message &&
          true;
    }
    return false;
  }

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

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

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

  ResponseMessage({
    this.clientRequestTime,
    this.error,
    this.id,
    required this.jsonrpc,
    this.result,
  });
  static ResponseMessage fromJson(Map<String, Object?> json) {
    final clientRequestTimeJson = json['clientRequestTime'];
    final clientRequestTime = clientRequestTimeJson as int?;
    final errorJson = json['error'];
    final error = errorJson != null
        ? ResponseError.fromJson(errorJson as Map<String, Object?>)
        : null;
    final idJson = json['id'];
    final id = idJson == null
        ? null
        : (idJson is int
            ? Either2<int, String>.t1(idJson)
            : (idJson is String
                ? Either2<int, String>.t2(idJson)
                : (throw '''$idJson was not one of (int, String)''')));
    final jsonrpcJson = json['jsonrpc'];
    final jsonrpc = jsonrpcJson as String;
    final resultJson = json['result'];
    final result = resultJson;
    return ResponseMessage(
      clientRequestTime: clientRequestTime,
      error: error,
      id: id,
      jsonrpc: jsonrpc,
      result: result,
    );
  }

  final int? clientRequestTime;

  /// The error object in case a request fails.
  final ResponseError? error;

  /// The request id.
  final Either2<int, String>? id;
  final String jsonrpc;

  /// The result of a request. This member is REQUIRED on success. This member
  /// MUST NOT exist if there was an error invoking the method.
  final Object? result;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (clientRequestTime != null) {
      __result['clientRequestTime'] = clientRequestTime;
    }
    __result['id'] = id;
    __result['jsonrpc'] = jsonrpc;
    if (error != null && result != null) {
      throw 'result and error cannot both be set';
    } else if (error != null) {
      __result['error'] = error;
    } else {
      __result['result'] = result;
    }
    return __result;
  }

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

  @override
  bool operator ==(Object other) {
    if (other is ResponseMessage && other.runtimeType == ResponseMessage) {
      return clientRequestTime == other.clientRequestTime &&
          error == other.error &&
          id == other.id &&
          jsonrpc == other.jsonrpc &&
          result == other.result &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        clientRequestTime,
        error,
        id,
        jsonrpc,
        result,
      );

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

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

  SaveOptions({
    this.includeText,
  });
  static SaveOptions fromJson(Map<String, Object?> 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;

  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) {
    if (other is SaveOptions && other.runtimeType == SaveOptions) {
      return includeText == other.includeText && true;
    }
    return false;
  }

  @override
  int get hashCode => includeText.hashCode;

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

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 ([Range]) of this selection range.
  final Range range;

  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) {
    if (other is SelectionRange && other.runtimeType == SelectionRange) {
      return parent == other.parent && range == other.range && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is SelectionRangeClientCapabilities &&
        other.runtimeType == SelectionRangeClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is SelectionRangeOptions &&
        other.runtimeType == SelectionRangeOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class SelectionRangeParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  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.
  final Either2<int, String>? workDoneToken;

  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.every((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) {
    if (other is SelectionRangeParams &&
        other.runtimeType == SelectionRangeParams) {
      return partialResultToken == other.partialResultToken &&
          listEqual(
              positions, other.positions, (Position a, Position b) => a == b) &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class SelectionRangeRegistrationOptions
    implements
        SelectionRangeOptions,
        TextDocumentRegistrationOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is SelectionRangeRegistrationOptions &&
        other.runtimeType == SelectionRangeRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

class SemanticTokenModifiers {
  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 declaration = SemanticTokenModifiers('declaration');
  static const definition = SemanticTokenModifiers('definition');
  static const readonly = SemanticTokenModifiers('readonly');
  static const static = SemanticTokenModifiers('static');
  static const deprecated = SemanticTokenModifiers('deprecated');
  static const abstract = SemanticTokenModifiers('abstract');
  static const async = SemanticTokenModifiers('async');
  static const modification = SemanticTokenModifiers('modification');
  static const documentation = SemanticTokenModifiers('documentation');
  static const defaultLibrary = SemanticTokenModifiers('defaultLibrary');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is SemanticTokenModifiers && o._value == _value;
}

class SemanticTokenTypes {
  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 namespace = SemanticTokenTypes('namespace');

  /// 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 class_ = SemanticTokenTypes('class');
  static const enum_ = SemanticTokenTypes('enum');
  static const interface = SemanticTokenTypes('interface');
  static const struct = SemanticTokenTypes('struct');
  static const typeParameter = SemanticTokenTypes('typeParameter');
  static const parameter = SemanticTokenTypes('parameter');
  static const variable = SemanticTokenTypes('variable');
  static const property = SemanticTokenTypes('property');
  static const enumMember = SemanticTokenTypes('enumMember');
  static const event = SemanticTokenTypes('event');
  static const function = SemanticTokenTypes('function');
  static const method = SemanticTokenTypes('method');
  static const macro = SemanticTokenTypes('macro');
  static const keyword = SemanticTokenTypes('keyword');
  static const modifier = SemanticTokenTypes('modifier');
  static const comment = SemanticTokenTypes('comment');
  static const string = SemanticTokenTypes('string');
  static const number = SemanticTokenTypes('number');
  static const regexp = SemanticTokenTypes('regexp');
  static const operator = SemanticTokenTypes('operator');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is SemanticTokenTypes && o._value == _value;
}

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;

  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.every((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) {
    if (other is SemanticTokens && other.runtimeType == SemanticTokens) {
      return listEqual(data, other.data, (int a, int b) => a == b) &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        resultId,
      );

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

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 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 ErrorCodes.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;

  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.every((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.every((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.every((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) {
    if (other is SemanticTokensClientCapabilities &&
        other.runtimeType == SemanticTokensClientCapabilities) {
      return 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) &&
          true;
    }
    return false;
  }

  @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 SemanticTokensClientCapabilitiesFull implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesFull.canParse,
    SemanticTokensClientCapabilitiesFull.fromJson,
  );

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

  /// The client will send the `textDocument/semanticTokens/full/delta` request
  /// if the server provides a corresponding handler.
  final bool? delta;

  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 SemanticTokensClientCapabilitiesFull');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilitiesFull &&
        other.runtimeType == SemanticTokensClientCapabilitiesFull) {
      return delta == other.delta && true;
    }
    return false;
  }

  @override
  int get hashCode => delta.hashCode;

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

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

  static SemanticTokensClientCapabilitiesRange fromJson(
      Map<String, Object?> json) {
    return SemanticTokensClientCapabilitiesRange();
  }

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter
          .reportError('must be of type SemanticTokensClientCapabilitiesRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilitiesRange &&
        other.runtimeType == SemanticTokensClientCapabilitiesRange) {
      return true;
    }
    return false;
  }

  @override
  int get hashCode => 42;

  @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, SemanticTokensClientCapabilitiesFull>.t1(fullJson)
            : (SemanticTokensClientCapabilitiesFull.canParse(
                    fullJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensClientCapabilitiesFull>.t2(
                    SemanticTokensClientCapabilitiesFull.fromJson(
                        fullJson as Map<String, Object?>))
                : (throw '''$fullJson was not one of (bool, SemanticTokensClientCapabilitiesFull)''')));
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : (rangeJson is bool
            ? Either2<bool, SemanticTokensClientCapabilitiesRange>.t1(rangeJson)
            : (SemanticTokensClientCapabilitiesRange.canParse(
                    rangeJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensClientCapabilitiesRange>.t2(
                    SemanticTokensClientCapabilitiesRange.fromJson(
                        rangeJson as Map<String, Object?>))
                : (throw '''$rangeJson was not one of (bool, SemanticTokensClientCapabilitiesRange)''')));
    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, SemanticTokensClientCapabilitiesFull>? full;

  /// The client will send the `textDocument/semanticTokens/range` request if
  /// the server provides a corresponding handler.
  final Either2<bool, SemanticTokensClientCapabilitiesRange>? range;

  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 ||
                SemanticTokensClientCapabilitiesFull.canParse(
                    full, reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensClientCapabilitiesFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        final range = obj['range'];
        if (range != null &&
            !((range is bool ||
                SemanticTokensClientCapabilitiesRange.canParse(
                    range, reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensClientCapabilitiesRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequests');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilitiesRequests &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequests) {
      return full == other.full && range == other.range && true;
    }
    return false;
  }

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

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

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;

  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.every(
                (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) {
    if (other is SemanticTokensDelta &&
        other.runtimeType == SemanticTokensDelta) {
      return listEqual(edits, other.edits,
              (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(edits),
        resultId,
      );

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

class SemanticTokensDeltaParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is SemanticTokensDeltaParams &&
        other.runtimeType == SemanticTokensDeltaParams) {
      return partialResultToken == other.partialResultToken &&
          previousResultId == other.previousResultId &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

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;

  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.every(
                (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) {
    if (other is SemanticTokensDeltaPartialResult &&
        other.runtimeType == SemanticTokensDeltaPartialResult) {
      return listEqual(edits, other.edits,
              (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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;

  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.every((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) {
    if (other is SemanticTokensEdit &&
        other.runtimeType == SemanticTokensEdit) {
      return listEqual(data, other.data, (int a, int b) => a == b) &&
          deleteCount == other.deleteCount &&
          start == other.start &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        deleteCount,
        start,
      );

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

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;

  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.every((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.every((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) {
    if (other is SemanticTokensLegend &&
        other.runtimeType == SemanticTokensLegend) {
      return listEqual(tokenModifiers, other.tokenModifiers,
              (String a, String b) => a == b) &&
          listEqual(
              tokenTypes, other.tokenTypes, (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(tokenModifiers),
        lspHashCode(tokenTypes),
      );

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

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;
  final bool? workDoneProgress;

  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) {
    if (other is SemanticTokensOptions &&
        other.runtimeType == SemanticTokensOptions) {
      return full == other.full &&
          legend == other.legend &&
          range == other.range &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is SemanticTokensOptionsFull &&
        other.runtimeType == SemanticTokensOptionsFull) {
      return delta == other.delta && true;
    }
    return false;
  }

  @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();
  }

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    return __result;
  }

  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) {
    if (other is SemanticTokensOptionsRange &&
        other.runtimeType == SemanticTokensOptionsRange) {
      return true;
    }
    return false;
  }

  @override
  int get hashCode => 42;

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

class SemanticTokensParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is SemanticTokensParams &&
        other.runtimeType == SemanticTokensParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

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;

  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.every((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) {
    if (other is SemanticTokensPartialResult &&
        other.runtimeType == SemanticTokensPartialResult) {
      return listEqual(data, other.data, (int a, int b) => a == b) && true;
    }
    return false;
  }

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

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

class SemanticTokensRangeParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is SemanticTokensRangeParams &&
        other.runtimeType == SemanticTokensRangeParams) {
      return partialResultToken == other.partialResultToken &&
          range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class SemanticTokensRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        SemanticTokensOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

  /// Server supports providing semantic tokens for a full document.
  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.
  final String? id;

  /// 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;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is SemanticTokensRegistrationOptions &&
        other.runtimeType == SemanticTokensRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          full == other.full &&
          id == other.id &&
          legend == other.legend &&
          range == other.range &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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 detect a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  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) {
    if (other is SemanticTokensWorkspaceClientCapabilities &&
        other.runtimeType == SemanticTokensWorkspaceClientCapabilities) {
      return refreshSupport == other.refreshSupport && true;
    }
    return false;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

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

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. The `CodeActionOptions` return type is
  /// only valid if the client signals code action literal support via the
  /// property `textDocument.codeAction.codeActionLiteralSupport`.
  final Either2<bool, CodeActionOptions>? codeActionProvider;

  /// The server provides code lens.
  final CodeLensOptions? codeLensProvider;

  /// The server provides color provider support.
  ///  @since 3.6.0
  final Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>?
      colorProvider;

  /// The server provides completion support.
  final CompletionOptions? completionProvider;

  /// The server provides go to declaration support.
  ///  @since 3.14.0
  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.
  ///  @since 3.10.0
  final Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>?
      foldingRangeProvider;

  /// The server provides hover support.
  final Either2<bool, HoverOptions>? hoverProvider;

  /// The server provides goto implementation support.
  ///  @since 3.6.0
  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;

  /// Whether 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.
  ///  @since 3.15.0
  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. If omitted it defaults to
  /// `TextDocumentSyncKind.None`.
  final Either2<TextDocumentSyncKind, TextDocumentSyncOptions>?
      textDocumentSync;

  /// The server provides goto type definition support.
  ///  @since 3.6.0
  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;

  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) {
    if (other is ServerCapabilities &&
        other.runtimeType == ServerCapabilities) {
      return 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 &&
          true;
    }
    return false;
  }

  @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 ServerCapabilitiesFileOperations implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ServerCapabilitiesFileOperations.canParse,
    ServerCapabilitiesFileOperations.fromJson,
  );

  ServerCapabilitiesFileOperations({
    this.didCreate,
    this.didDelete,
    this.didRename,
    this.willCreate,
    this.willDelete,
    this.willRename,
  });
  static ServerCapabilitiesFileOperations 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 ServerCapabilitiesFileOperations(
      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;

  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 ServerCapabilitiesFileOperations');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ServerCapabilitiesFileOperations &&
        other.runtimeType == ServerCapabilitiesFileOperations) {
      return didCreate == other.didCreate &&
          didDelete == other.didDelete &&
          didRename == other.didRename &&
          willCreate == other.willCreate &&
          willDelete == other.willDelete &&
          willRename == other.willRename &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        didCreate,
        didDelete,
        didRename,
        willCreate,
        willDelete,
        willRename,
      );

  @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
        ? ServerCapabilitiesFileOperations.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 file notifications/requests.
  ///  @since 3.16.0
  final ServerCapabilitiesFileOperations? fileOperations;

  /// The server supports workspace folder.
  ///  @since 3.6.0
  final WorkspaceFoldersServerCapabilities? workspaceFolders;

  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 &&
            !(ServerCapabilitiesFileOperations.canParse(
                fileOperations, reporter))) {
          reporter
              .reportError('must be of type ServerCapabilitiesFileOperations');
          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) {
    if (other is ServerCapabilitiesWorkspace &&
        other.runtimeType == ServerCapabilitiesWorkspace) {
      return fileOperations == other.fileOperations &&
          workspaceFolders == other.workspaceFolders &&
          true;
    }
    return false;
  }

  @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 = const {'off', 'messages', 'verbose'}.contains(valueJson)
        ? valueJson as String
        : throw '''$valueJson was not one of ('off', 'messages', 'verbose')''';
    return SetTraceParams(
      value: value,
    );
  }

  /// The new value that should be assigned to the trace setting.
  final String value;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['value'] = value;
    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 (!((value == 'off' || value == 'messages' || value == 'verbose'))) {
          reporter.reportError(
              'must be one of the literals \'off\', \'messages\', \'verbose\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SetTraceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SetTraceParams && other.runtimeType == SetTraceParams) {
      return value == other.value && true;
    }
    return false;
  }

  @override
  int get hashCode => value.hashCode;

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

/// Client capabilities for the show document 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 show document request.
  final bool support;

  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) {
    if (other is ShowDocumentClientCapabilities &&
        other.runtimeType == ShowDocumentClientCapabilities) {
      return support == other.support && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is ShowDocumentParams &&
        other.runtimeType == ShowDocumentParams) {
      return external == other.external &&
          selection == other.selection &&
          takeFocus == other.takeFocus &&
          uri == other.uri &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        external,
        selection,
        takeFocus,
        uri,
      );

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

/// The result of an show document 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;

  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) {
    if (other is ShowDocumentResult &&
        other.runtimeType == ShowDocumentResult) {
      return success == other.success && true;
    }
    return false;
  }

  @override
  int get hashCode => success.hashCode;

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

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.
  final MessageType type;

  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) {
    if (other is ShowMessageParams && other.runtimeType == ShowMessageParams) {
      return message == other.message && type == other.type && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is ShowMessageRequestClientCapabilities &&
        other.runtimeType == ShowMessageRequestClientCapabilities) {
      return messageActionItem == other.messageActionItem && true;
    }
    return false;
  }

  @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
  /// sent back to the server in the request's response.
  final bool? additionalPropertiesSupport;

  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) {
    if (other is ShowMessageRequestClientCapabilitiesMessageActionItem &&
        other.runtimeType ==
            ShowMessageRequestClientCapabilitiesMessageActionItem) {
      return additionalPropertiesSupport == other.additionalPropertiesSupport &&
          true;
    }
    return false;
  }

  @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.
  final MessageType type;

  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.every(
                    (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) {
    if (other is ShowMessageRequestParams &&
        other.runtimeType == ShowMessageRequestParams) {
      return listEqual(actions, other.actions,
              (MessageActionItem a, MessageActionItem b) => a == b) &&
          message == other.message &&
          type == other.type &&
          true;
    }
    return false;
  }

  @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 ignore if the
  /// `SignatureHelp` as 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. If no signatures are available the signature help
  /// request should return `null`.
  final List<SignatureInformation> signatures;

  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.every(
                (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) {
    if (other is SignatureHelp && other.runtimeType == SignatureHelp) {
      return activeParameter == other.activeParameter &&
          activeSignature == other.activeSignature &&
          listEqual(signatures, other.signatures,
              (SignatureInformation a, SignatureInformation b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        activeParameter,
        activeSignature,
        lspHashCode(signatures),
      );

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

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;

  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) {
    if (other is SignatureHelpClientCapabilities &&
        other.runtimeType == SignatureHelpClientCapabilities) {
      return contextSupport == other.contextSupport &&
          dynamicRegistration == other.dynamicRegistration &&
          signatureInformation == other.signatureInformation &&
          true;
    }
    return false;
  }

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

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

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

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

  /// The client supports processing label offsets instead of a simple label
  /// string.
  ///  @since 3.14.0
  final bool? labelOffsetSupport;

  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 SignatureHelpClientCapabilitiesParameterInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpClientCapabilitiesParameterInformation &&
        other.runtimeType ==
            SignatureHelpClientCapabilitiesParameterInformation) {
      return labelOffsetSupport == other.labelOffsetSupport && true;
    }
    return false;
  }

  @override
  int get hashCode => labelOffsetSupport.hashCode;

  @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
        ? SignatureHelpClientCapabilitiesParameterInformation.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 follow 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 SignatureHelpClientCapabilitiesParameterInformation?
      parameterInformation;

  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
                    .every((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 &&
            !(SignatureHelpClientCapabilitiesParameterInformation.canParse(
                parameterInformation, reporter))) {
          reporter.reportError(
              'must be of type SignatureHelpClientCapabilitiesParameterInformation');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpClientCapabilitiesSignatureInformation &&
        other.runtimeType ==
            SignatureHelpClientCapabilitiesSignatureInformation) {
      return activeParameterSupport == other.activeParameterSupport &&
          listEqual(documentationFormat, other.documentationFormat,
              (MarkupKind a, MarkupKind b) => a == b) &&
          parameterInformation == other.parameterInformation &&
          true;
    }
    return false;
  }

  @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 occur 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;

  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) {
    if (other is SignatureHelpContext &&
        other.runtimeType == SignatureHelpContext) {
      return activeSignatureHelp == other.activeSignatureHelp &&
          isRetrigger == other.isRetrigger &&
          triggerCharacter == other.triggerCharacter &&
          triggerKind == other.triggerKind &&
          true;
    }
    return false;
  }

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

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

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;

  /// The characters that trigger signature help automatically.
  final List<String>? triggerCharacters;
  final bool? workDoneProgress;

  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.every((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.every((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) {
    if (other is SignatureHelpOptions &&
        other.runtimeType == SignatureHelpOptions) {
      return listEqual(retriggerCharacters, other.retriggerCharacters,
              (String a, String b) => a == b) &&
          listEqual(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is SignatureHelpParams &&
        other.runtimeType == SignatureHelpParams) {
      return context == other.context &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class SignatureHelpRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        SignatureHelpOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? 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
  final List<String>? retriggerCharacters;

  /// The characters that trigger signature help automatically.
  final List<String>? triggerCharacters;
  final bool? workDoneProgress;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('retriggerCharacters');
      try {
        final retriggerCharacters = obj['retriggerCharacters'];
        if (retriggerCharacters != null &&
            !((retriggerCharacters is List<Object?> &&
                (retriggerCharacters.every((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.every((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) {
    if (other is SignatureHelpRegistrationOptions &&
        other.runtimeType == SignatureHelpRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter 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 &&
          true;
    }
    return false;
  }

  @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 {
  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 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);

  /// Signature help was triggered by the cursor moving or by the document
  /// content changing.
  static const ContentChange = SignatureHelpTriggerKind(3);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is SignatureHelpTriggerKind && o._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;

  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.every((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) {
    if (other is SignatureInformation &&
        other.runtimeType == SignatureInformation) {
      return activeParameter == other.activeParameter &&
          documentation == other.documentation &&
          label == other.label &&
          listEqual(parameters, other.parameters,
              (ParameterInformation a, ParameterInformation b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        activeParameter,
        documentation,
        label,
        lspHashCode(parameters),
      );

  @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 (NotebookDocumentSyncRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return NotebookDocumentSyncRegistrationOptions.fromJson(json);
    }
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    if (DiagnosticRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.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;

  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) {
    if (other is StaticRegistrationOptions &&
        other.runtimeType == StaticRegistrationOptions) {
      return id == other.id && true;
    }
    return false;
  }

  @override
  int get hashCode => id.hashCode;

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

/// Represents information about programming constructs like variables, classes,
/// interfaces etc.
///  @deprecated use DocumentSymbol or WorkspaceSymbol instead.
class SymbolInformation implements 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.
  final String? containerName;

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

  /// The kind of this symbol.
  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 then 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 a 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.
  final String name;

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

  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.every((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) {
    if (other is SymbolInformation && other.runtimeType == SymbolInformation) {
      return 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) &&
          true;
    }
    return false;
  }

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

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

/// A symbol kind.
class SymbolKind {
  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 File = SymbolKind(1);
  static const Module = SymbolKind(2);
  static const Namespace = SymbolKind(3);
  static const Package = SymbolKind(4);
  static const Class = SymbolKind(5);
  static const Method = SymbolKind(6);
  static const Property = SymbolKind(7);
  static const Field = SymbolKind(8);
  static const Constructor = SymbolKind(9);
  static const Enum = SymbolKind(10);
  static const Interface = SymbolKind(11);
  static const Function = SymbolKind(12);
  static const Variable = SymbolKind(13);
  static const Constant = SymbolKind(14);
  static const Str = SymbolKind(15);
  static const Number = SymbolKind(16);
  static const Boolean = SymbolKind(17);
  static const Array = SymbolKind(18);
  static const Obj = SymbolKind(19);
  static const Key = SymbolKind(20);
  static const Null = SymbolKind(21);
  static const EnumMember = SymbolKind(22);
  static const Struct = SymbolKind(23);
  static const Event = SymbolKind(24);
  static const Operator = SymbolKind(25);
  static const TypeParameter = SymbolKind(26);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is SymbolKind && o._value == _value;
}

/// Symbol tags are extra annotations that tweak the rendering of a symbol.
///  @since 3.16
class SymbolTag {
  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);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is SymbolTag && o._value == _value;
}

/// Describe options to be used when registering 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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

  /// How documents are synced to the server. See TextDocumentSyncKind.Full and
  /// TextDocumentSyncKind.Incremental.
  final TextDocumentSyncKind syncKind;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is TextDocumentChangeRegistrationOptions &&
        other.runtimeType == TextDocumentChangeRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          syncKind == other.syncKind &&
          true;
    }
    return false;
  }

  @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
        ? TypeHierarchyClientCapabilities1.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;

  /// Capabilities specific to the `textDocument/moniker` request.
  ///  @since 3.16.0
  final MonikerClientCapabilities? moniker;

  /// request. 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 requests.
  ///  @since 3.16.0
  final SemanticTokensClientCapabilities? semanticTokens;

  /// Capabilities specific to the `textDocument/signatureHelp` request.
  final SignatureHelpClientCapabilities? signatureHelp;
  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 TypeHierarchyClientCapabilities1? typeHierarchy;

  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 &&
            !(TypeHierarchyClientCapabilities1.canParse(
                typeHierarchy, reporter))) {
          reporter
              .reportError('must be of type TypeHierarchyClientCapabilities1');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentClientCapabilities &&
        other.runtimeType == TextDocumentClientCapabilities) {
      return 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 &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is TextDocumentContentChangeEvent1 &&
        other.runtimeType == TextDocumentContentChangeEvent1) {
      return range == other.range &&
          rangeLength == other.rangeLength &&
          text == other.text &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is TextDocumentContentChangeEvent2 &&
        other.runtimeType == TextDocumentContentChangeEvent2) {
      return text == other.text && true;
    }
    return false;
  }

  @override
  int get hashCode => text.hashCode;

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

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 by the
  /// client capability `workspace.workspaceEdit.changeAnnotationSupport`
  final List<Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>> edits;

  /// The text document to change.
  final OptionalVersionedTextDocumentIdentifier textDocument;

  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.every((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) {
    if (other is TextDocumentEdit && other.runtimeType == TextDocumentEdit) {
      return listEqual(
              edits,
              other.edits,
              (Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit> a,
                      Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>
                          b) =>
                  a == b) &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(edits),
        textDocument,
      );

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

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

  TextDocumentFilter({
    this.language,
    this.pattern,
    this.scheme,
  });
  static TextDocumentFilter 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 TextDocumentFilter(
      language: language,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// A language id, like `typescript`.
  final String? language;

  /// A glob pattern, like `*.{ts,js}`.
  ///
  /// 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? pattern;

  /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
  final String? scheme;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (language != null) {
      __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 {
        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 {
        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 TextDocumentFilter');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentFilter &&
        other.runtimeType == TextDocumentFilter) {
      return language == other.language &&
          pattern == other.pattern &&
          scheme == other.scheme &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        language,
        pattern,
        scheme,
      );

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

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;

  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) {
    if (other is TextDocumentIdentifier &&
        other.runtimeType == TextDocumentIdentifier) {
      return uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => uri.hashCode;

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

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;

  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) {
    if (other is TextDocumentItem && other.runtimeType == TextDocumentItem) {
      return languageId == other.languageId &&
          text == other.text &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        languageId,
        text,
        uri,
        version,
      );

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

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 (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (TypeHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyPrepareParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (RenameParams.canParse(json, nullLspJsonReporter)) {
      return RenameParams.fromJson(json);
    }
    if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
      return PrepareRenameParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.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;

  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) {
    if (other is TextDocumentPositionParams &&
        other.runtimeType == TextDocumentPositionParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

  @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 (TextDocumentSaveRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentSaveRegistrationOptions.fromJson(json);
    }
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (DefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (ReferenceRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceRegistrationOptions.fromJson(json);
    }
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    if (DocumentHighlightRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentHighlightRegistrationOptions.fromJson(json);
    }
    if (DocumentLinkRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkRegistrationOptions.fromJson(json);
    }
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    if (CodeLensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.fromJson(json);
    }
    if (CompletionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionRegistrationOptions.fromJson(json);
    }
    if (DiagnosticRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticRegistrationOptions.fromJson(json);
    }
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    if (CodeActionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (DocumentFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentRangeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentRangeFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentOnTypeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingRegistrationOptions.fromJson(json);
    }
    if (RenameRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return RenameRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map(
            (item) => TextDocumentFilter.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<TextDocumentFilter>? documentSelector;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentRegistrationOptions &&
        other.runtimeType == TextDocumentRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          true;
    }
    return false;
  }

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

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

/// Represents reasons why a text document is saved.
class TextDocumentSaveReason {
  const TextDocumentSaveReason(this._value);
  const TextDocumentSaveReason.fromJson(this._value);

  final int _value;

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

  /// Manually triggered, e.g. by the user pressing save, by starting debugging,
  /// or by an API call.
  static const Manual = TextDocumentSaveReason(1);

  /// Automatic after a delay.
  static const AfterDelay = TextDocumentSaveReason(2);

  /// When the editor lost focus.
  static const FocusOut = TextDocumentSaveReason(3);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is TextDocumentSaveReason && o._value == _value;
}

class TextDocumentSaveRegistrationOptions
    implements 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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

  /// The client is supposed to include the content on save.
  final bool? includeText;

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is TextDocumentSaveRegistrationOptions &&
        other.runtimeType == TextDocumentSaveRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          includeText == other.includeText &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is TextDocumentSyncClientCapabilities &&
        other.runtimeType == TextDocumentSyncClientCapabilities) {
      return didSave == other.didSave &&
          dynamicRegistration == other.dynamicRegistration &&
          willSave == other.willSave &&
          willSaveWaitUntil == other.willSaveWaitUntil &&
          true;
    }
    return false;
  }

  @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 {
  const TextDocumentSyncKind(this._value);
  const TextDocumentSyncKind.fromJson(this._value);

  final int _value;

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

  /// Documents should not be synced at all.
  static const None = TextDocumentSyncKind(0);

  /// 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);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is TextDocumentSyncKind && o._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;

  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) {
    if (other is TextDocumentSyncOptions &&
        other.runtimeType == TextDocumentSyncOptions) {
      return change == other.change &&
          openClose == other.openClose &&
          save == other.save &&
          willSave == other.willSave &&
          willSaveWaitUntil == other.willSaveWaitUntil &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        change,
        openClose,
        save,
        willSave,
        willSaveWaitUntil,
      );

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

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;

  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) {
    if (other is TextEdit && other.runtimeType == TextEdit) {
      return newText == other.newText && range == other.range && true;
    }
    return false;
  }

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

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

class TokenFormat {
  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');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is TokenFormat && o._value == _value;
}

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;

  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) {
    if (other is TypeDefinitionClientCapabilities &&
        other.runtimeType == TypeDefinitionClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          linkSupport == other.linkSupport &&
          true;
    }
    return false;
  }

  @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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is TypeDefinitionOptions &&
        other.runtimeType == TypeDefinitionOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

class TypeDefinitionParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        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.
  final Either2<int, String>? partialResultToken;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is TypeDefinitionParams &&
        other.runtimeType == TypeDefinitionParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class TypeDefinitionRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        TypeDefinitionOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is TypeDefinitionRegistrationOptions &&
        other.runtimeType == TypeDefinitionRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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

  TypeHierarchyClientCapabilities1({
    this.dynamicRegistration,
  });
  static TypeHierarchyClientCapabilities1 fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return TypeHierarchyClientCapabilities1(
      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;

  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 TypeHierarchyClientCapabilities1');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchyClientCapabilities1 &&
        other.runtimeType == TypeHierarchyClientCapabilities1) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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`](#TypeHierarchyItem.range).
  final Range selectionRange;

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

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

  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.every((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) {
    if (other is TypeHierarchyItem && other.runtimeType == TypeHierarchyItem) {
      return 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 &&
          true;
    }
    return false;
  }

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

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

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,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is TypeHierarchyOptions &&
        other.runtimeType == TypeHierarchyOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

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.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  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) {
    if (other is TypeHierarchyPrepareParams &&
        other.runtimeType == TypeHierarchyPrepareParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class TypeHierarchyRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        TypeHierarchyOptions,
        StaticRegistrationOptions,
        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) => TextDocumentFilter.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.
  final List<TextDocumentFilter>? documentSelector;

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

  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.every(
                    (item) => TextDocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TextDocumentFilter>');
          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) {
    if (other is TypeHierarchyRegistrationOptions &&
        other.runtimeType == TypeHierarchyRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (TextDocumentFilter a, TextDocumentFilter b) => a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

class TypeHierarchySubtypesParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  final Either2<int, String>? partialResultToken;

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

  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) {
    if (other is TypeHierarchySubtypesParams &&
        other.runtimeType == TypeHierarchySubtypesParams) {
      return item == other.item &&
          partialResultToken == other.partialResultToken &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

class TypeHierarchySupertypesParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  final Either2<int, String>? partialResultToken;

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

  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) {
    if (other is TypeHierarchySupertypesParams &&
        other.runtimeType == TypeHierarchySupertypesParams) {
      return item == other.item &&
          partialResultToken == other.partialResultToken &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @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 (RelatedUnchangedDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return RelatedUnchangedDocumentDiagnosticReport.fromJson(json);
    }
    if (WorkspaceUnchangedDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceUnchangedDocumentDiagnosticReport.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;

  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) {
    if (other is UnchangedDocumentDiagnosticReport &&
        other.runtimeType == UnchangedDocumentDiagnosticReport) {
      return kind == other.kind && resultId == other.resultId && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        resultId,
      );

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

/// Moniker uniqueness level to define scope of the moniker.
class UniquenessLevel {
  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 unique inside a project for which a dump got created
  static const project = UniquenessLevel('project');

  /// The moniker is unique inside the group to which a project belongs
  static const group = UniquenessLevel('group');

  /// The moniker is unique inside the moniker scheme.
  static const scheme = UniquenessLevel('scheme');

  /// The moniker is globally unique
  static const global = UniquenessLevel('global');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is UniquenessLevel && o._value == _value;
}

/// General parameters to unregister a capability.
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 / capability to unregister for.
  final String method;

  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) {
    if (other is Unregistration && other.runtimeType == Unregistration) {
      return id == other.id && method == other.method && true;
    }
    return false;
  }

  @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,
    );
  }

  /// This should correctly be named `unregistrations`. However changing this //
  /// is a breaking change and needs to wait until we deliver a 4.x version //
  /// of the specification.
  final List<Unregistration> unregisterations;

  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
                .every((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) {
    if (other is UnregistrationParams &&
        other.runtimeType == UnregistrationParams) {
      return listEqual(unregisterations, other.unregisterations,
              (Unregistration a, Unregistration b) => a == b) &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is VersionedNotebookDocumentIdentifier &&
        other.runtimeType == VersionedNotebookDocumentIdentifier) {
      return uri == other.uri && version == other.version && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

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

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.
  final String uri;

  /// The version number of this document.
  ///
  /// The version number of a document will increase after each change,
  /// including undo/redo. The number doesn't need to be consecutive.
  final int version;

  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) {
    if (other is VersionedTextDocumentIdentifier &&
        other.runtimeType == VersionedTextDocumentIdentifier) {
      return uri == other.uri && version == other.version && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

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

class WatchKind {
  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 create events.
  static const Create = WatchKind(1);

  /// Interested in change events
  static const Change = WatchKind(2);

  /// Interested in delete events
  static const Delete = WatchKind(4);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is WatchKind && o._value == _value;
}

/// The parameters send 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;

  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) {
    if (other is WillSaveTextDocumentParams &&
        other.runtimeType == WillSaveTextDocumentParams) {
      return reason == other.reason &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

  @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,
    );
  }

  /// Client capabilities for the show document 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;

  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) {
    if (other is WindowClientCapabilities &&
        other.runtimeType == WindowClientCapabilities) {
      return showDocument == other.showDocument &&
          showMessage == other.showMessage &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is WorkDoneProgressBegin &&
        other.runtimeType == WorkDoneProgressBegin) {
      return cancellable == other.cancellable &&
          kind == other.kind &&
          message == other.message &&
          percentage == other.percentage &&
          title == other.title &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is WorkDoneProgressCancelParams &&
        other.runtimeType == WorkDoneProgressCancelParams) {
      return token == other.token && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is WorkDoneProgressCreateParams &&
        other.runtimeType == WorkDoneProgressCreateParams) {
      return token == other.token && true;
    }
    return false;
  }

  @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;

  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) {
    if (other is WorkDoneProgressEnd &&
        other.runtimeType == WorkDoneProgressEnd) {
      return kind == other.kind && message == other.message && true;
    }
    return false;
  }

  @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 (DeclarationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationOptions.fromJson(json);
    }
    if (DefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionOptions.fromJson(json);
    }
    if (TypeDefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionOptions.fromJson(json);
    }
    if (ImplementationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationOptions.fromJson(json);
    }
    if (ReferenceOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceOptions.fromJson(json);
    }
    if (CallHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOptions.fromJson(json);
    }
    if (TypeHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyOptions.fromJson(json);
    }
    if (DocumentHighlightOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightOptions.fromJson(json);
    }
    if (DocumentLinkOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkOptions.fromJson(json);
    }
    if (HoverOptions.canParse(json, nullLspJsonReporter)) {
      return HoverOptions.fromJson(json);
    }
    if (CodeLensOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensOptions.fromJson(json);
    }
    if (FoldingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeOptions.fromJson(json);
    }
    if (SelectionRangeOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeOptions.fromJson(json);
    }
    if (DocumentSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolOptions.fromJson(json);
    }
    if (SemanticTokensOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensOptions.fromJson(json);
    }
    if (InlayHintOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintOptions.fromJson(json);
    }
    if (InlineValueOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueOptions.fromJson(json);
    }
    if (MonikerOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerOptions.fromJson(json);
    }
    if (CompletionOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionOptions.fromJson(json);
    }
    if (DiagnosticOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticOptions.fromJson(json);
    }
    if (SignatureHelpOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpOptions.fromJson(json);
    }
    if (CodeActionOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionOptions.fromJson(json);
    }
    if (DocumentColorOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorOptions.fromJson(json);
    }
    if (DocumentFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingOptions.fromJson(json);
    }
    if (DocumentRangeFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingOptions.fromJson(json);
    }
    if (RenameOptions.canParse(json, nullLspJsonReporter)) {
      return RenameOptions.fromJson(json);
    }
    if (LinkedEditingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeOptions.fromJson(json);
    }
    if (WorkspaceSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolOptions.fromJson(json);
    }
    if (ExecuteCommandOptions.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkDoneProgressOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  final bool? workDoneProgress;

  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) {
    if (other is WorkDoneProgressOptions &&
        other.runtimeType == WorkDoneProgressOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @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 (InitializeParams.canParse(json, nullLspJsonReporter)) {
      return InitializeParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (TypeHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyPrepareParams.fromJson(json);
    }
    if (TypeHierarchySupertypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySupertypesParams.fromJson(json);
    }
    if (TypeHierarchySubtypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySubtypesParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (InlayHintParams.canParse(json, nullLspJsonReporter)) {
      return InlayHintParams.fromJson(json);
    }
    if (InlineValueParams.canParse(json, nullLspJsonReporter)) {
      return InlineValueParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (DocumentDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return DocumentDiagnosticParams.fromJson(json);
    }
    if (WorkspaceDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceDiagnosticParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (DocumentFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingParams.fromJson(json);
    }
    if (DocumentRangeFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingParams.fromJson(json);
    }
    if (RenameParams.canParse(json, nullLspJsonReporter)) {
      return RenameParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (ExecuteCommandParams.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandParams.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;

  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) {
    if (other is WorkDoneProgressParams &&
        other.runtimeType == WorkDoneProgressParams) {
      return workDoneToken == other.workDoneToken && true;
    }
    return false;
  }

  @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. This property is only valid
  /// if a cancel button got requested in the `WorkDoneProgressBegin` payload.
  ///
  /// Clients that don't support cancellation or don't support control the
  /// button's enablement state 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;

  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) {
    if (other is WorkDoneProgressReport &&
        other.runtimeType == WorkDoneProgressReport) {
      return cancellable == other.cancellable &&
          kind == other.kind &&
          message == other.message &&
          percentage == other.percentage &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        cancellable,
        kind,
        message,
        percentage,
      );

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

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
        ? ClientCapabilitiesFileOperations.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;

  /// Client workspace capabilities specific to diagnostics.
  ///  @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 requests/notifications.
  ///  @since 3.16.0
  final ClientCapabilitiesFileOperations? fileOperations;

  /// Client workspace capabilities specific to inlay hints.
  ///  @since 3.17.0
  final InlayHintWorkspaceClientCapabilities? inlayHint;

  /// Client workspace capabilities specific to inline values.
  ///  @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;

  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 &&
            !(ClientCapabilitiesFileOperations.canParse(
                fileOperations, reporter))) {
          reporter
              .reportError('must be of type ClientCapabilitiesFileOperations');
          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) {
    if (other is WorkspaceClientCapabilities &&
        other.runtimeType == WorkspaceClientCapabilities) {
      return 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 &&
          true;
    }
    return false;
  }

  @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 WorkDoneProgressParams, PartialResultParams, 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.
  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.
  final Either2<int, String>? workDoneToken;

  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.every(
                (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) {
    if (other is WorkspaceDiagnosticParams &&
        other.runtimeType == WorkspaceDiagnosticParams) {
      return identifier == other.identifier &&
          partialResultToken == other.partialResultToken &&
          listEqual(previousResultIds, other.previousResultIds,
              (PreviousResultId a, PreviousResultId b) => a == b) &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is WorkspaceDiagnosticReport &&
        other.runtimeType == WorkspaceDiagnosticReport) {
      return listEqual(
              items,
              other.items,
              (Either2<WorkspaceFullDocumentDiagnosticReport,
                              WorkspaceUnchangedDocumentDiagnosticReport>
                          a,
                      Either2<WorkspaceFullDocumentDiagnosticReport,
                              WorkspaceUnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is WorkspaceDiagnosticReportPartialResult &&
        other.runtimeType == WorkspaceDiagnosticReportPartialResult) {
      return listEqual(
              items,
              other.items,
              (Either2<WorkspaceFullDocumentDiagnosticReport,
                              WorkspaceUnchangedDocumentDiagnosticReport>
                          a,
                      Either2<WorkspaceFullDocumentDiagnosticReport,
                              WorkspaceUnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

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

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

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 == null
        ? null
        : ((documentChangesJson is List<Object?> &&
                (documentChangesJson.every((item) =>
                    (CreateFile.canParse(item, nullLspJsonReporter) ||
                        DeleteFile.canParse(item, nullLspJsonReporter) ||
                        RenameFile.canParse(item, nullLspJsonReporter) ||
                        TextDocumentEdit.canParse(item, nullLspJsonReporter)))))
            ? Either2<List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>, List<TextDocumentEdit>>.t1((documentChangesJson)
                .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())
            : ((documentChangesJson is List<Object?> && (documentChangesJson.every((item) => TextDocumentEdit.canParse(item, nullLspJsonReporter)))) ? Either2<List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>, List<TextDocumentEdit>>.t2((documentChangesJson).map((item) => TextDocumentEdit.fromJson(item as Map<String, Object?>)).toList()) : (throw '''$documentChangesJson was not one of (List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>, List<TextDocumentEdit>)''')));
    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 Either2<
      List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>,
      List<TextDocumentEdit>>? documentChanges;

  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.every((item) =>
                    item is String &&
                    changeAnnotations.values.every((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.every((item) =>
                    item is String &&
                    changes.values.every((item) => (item is List<Object?> &&
                        (item.every((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.every((item) =>
                        (CreateFile.canParse(item, reporter) ||
                            DeleteFile.canParse(item, reporter) ||
                            RenameFile.canParse(item, reporter) ||
                            TextDocumentEdit.canParse(item, reporter))))) ||
                (documentChanges is List<Object?> &&
                    (documentChanges.every((item) =>
                        TextDocumentEdit.canParse(item, reporter))))))) {
          reporter.reportError(
              'must be of type Either2<List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>, List<TextDocumentEdit>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceEdit && other.runtimeType == WorkspaceEdit) {
      return 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)) &&
          documentChanges == other.documentChanges &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(changeAnnotations),
        lspHashCode(changes),
        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 specific new line character(s).
  ///  @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;

  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.every((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) {
    if (other is WorkspaceEditClientCapabilities &&
        other.runtimeType == WorkspaceEditClientCapabilities) {
      return changeAnnotationSupport == other.changeAnnotationSupport &&
          documentChanges == other.documentChanges &&
          failureHandling == other.failureHandling &&
          normalizesLineEndings == other.normalizesLineEndings &&
          listEqual(resourceOperations, other.resourceOperations,
              (ResourceOperationKind a, ResourceOperationKind b) => a == b) &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is WorkspaceEditClientCapabilitiesChangeAnnotationSupport &&
        other.runtimeType ==
            WorkspaceEditClientCapabilitiesChangeAnnotationSupport) {
      return groupsOnLabel == other.groupsOnLabel && true;
    }
    return false;
  }

  @override
  int get hashCode => groupsOnLabel.hashCode;

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

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;

  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) {
    if (other is WorkspaceFolder && other.runtimeType == WorkspaceFolder) {
      return name == other.name && uri == other.uri && true;
    }
    return false;
  }

  @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;

  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
                .every((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
                .every((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) {
    if (other is WorkspaceFoldersChangeEvent &&
        other.runtimeType == WorkspaceFoldersChangeEvent) {
      return listEqual(added, other.added,
              (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
          listEqual(removed, other.removed,
              (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is WorkspaceFoldersServerCapabilities &&
        other.runtimeType == WorkspaceFoldersServerCapabilities) {
      return changeNotifications == other.changeNotifications &&
          supported == other.supported &&
          true;
    }
    return false;
  }

  @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.
  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;

  /// 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;

  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.every((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) {
    if (other is WorkspaceFullDocumentDiagnosticReport &&
        other.runtimeType == WorkspaceFullDocumentDiagnosticReport) {
      return listEqual(
              items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
          kind == other.kind &&
          resultId == other.resultId &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

  @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
///  @since 3.17.0
class WorkspaceSymbol implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbol.canParse,
    WorkspaceSymbol.fromJson,
  );

  WorkspaceSymbol({
    this.containerName,
    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 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,
      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.
  final String? containerName;

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

  /// The location of this symbol. Whether a server is allowed to return a
  /// location without a range depends on the client capability
  /// `workspace.symbol.resolveSupport`.
  ///
  /// See also `SymbolInformation.location`.
  final Either2<Location, WorkspaceSymbolLocation> location;

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

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

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (containerName != null) {
      __result['containerName'] = containerName;
    }
    __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.every((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) {
    if (other is WorkspaceSymbol && other.runtimeType == WorkspaceSymbol) {
      return containerName == other.containerName &&
          kind == other.kind &&
          location == other.location &&
          name == other.name &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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 - proposedState
  final WorkspaceSymbolClientCapabilitiesResolveSupport? resolveSupport;

  /// Specific capabilities for the `SymbolKind` in the `workspace/symbol`
  /// request.
  final WorkspaceSymbolClientCapabilitiesSymbolKind? symbolKind;

  /// The client supports tags on `SymbolInformation` and `WorkspaceSymbol`.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///  @since 3.16.0
  final WorkspaceSymbolClientCapabilitiesTagSupport? tagSupport;

  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) {
    if (other is WorkspaceSymbolClientCapabilities &&
        other.runtimeType == WorkspaceSymbolClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          resolveSupport == other.resolveSupport &&
          symbolKind == other.symbolKind &&
          tagSupport == other.tagSupport &&
          true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is WorkspaceSymbolClientCapabilitiesResolveSupport &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesResolveSupport) {
      return listEqual(
              properties, other.properties, (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @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;

  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
                    .every((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) {
    if (other is WorkspaceSymbolClientCapabilitiesSymbolKind &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesSymbolKind) {
      return listEqual(valueSet, other.valueSet,
              (SymbolKind a, SymbolKind b) => a == b) &&
          true;
    }
    return false;
  }

  @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;

  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.every((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) {
    if (other is WorkspaceSymbolClientCapabilitiesTagSupport &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesTagSupport) {
      return listEqual(
              valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b) &&
          true;
    }
    return false;
  }

  @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;

  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) {
    if (other is WorkspaceSymbolLocation &&
        other.runtimeType == WorkspaceSymbolLocation) {
      return uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => uri.hashCode;

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

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;
  final bool? workDoneProgress;

  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) {
    if (other is WorkspaceSymbolOptions &&
        other.runtimeType == WorkspaceSymbolOptions) {
      return resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

/// The parameters of a Workspace Symbol Request.
class WorkspaceSymbolParams
    implements WorkDoneProgressParams, PartialResultParams, 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.
  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.
  final Either2<int, String>? workDoneToken;

  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) {
    if (other is WorkspaceSymbolParams &&
        other.runtimeType == WorkspaceSymbolParams) {
      return partialResultToken == other.partialResultToken &&
          query == other.query &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

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
  final bool? resolveProvider;
  final bool? workDoneProgress;

  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) {
    if (other is WorkspaceSymbolRegistrationOptions &&
        other.runtimeType == WorkspaceSymbolRegistrationOptions) {
      return resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @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.
  final String kind;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  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;

  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) {
    if (other is WorkspaceUnchangedDocumentDiagnosticReport &&
        other.runtimeType == WorkspaceUnchangedDocumentDiagnosticReport) {
      return kind == other.kind &&
          resultId == other.resultId &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

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

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