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

  /// 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['range'] = range.toJson();
    __result['newText'] = newText;
    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('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('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();
      }
      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 &&
          range == other.range &&
          newText == other.newText &&
          true;
    }
    return false;
  }

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

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

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

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

  /// 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?>{};
    if (label != null) {
      __result['label'] = label;
    }
    __result['edit'] = edit.toJson();
    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('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();
      }
      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 label == other.label && edit == other.edit && true;
    }
    return false;
  }

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

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

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

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

  /// 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 (failureReason != null) {
      __result['failureReason'] = failureReason;
    }
    if (failedChange != null) {
      __result['failedChange'] = failedChange;
    }
    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('failureReason');
      try {
        final failureReason = obj['failureReason'];
        if (failureReason != null && !(failureReason is String)) {
          reporter.reportError('must be of type String');
          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();
      }
      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 &&
          failureReason == other.failureReason &&
          failedChange == other.failedChange &&
          true;
    }
    return false;
  }

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

  @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.workDoneToken,
    this.partialResultToken,
  });
  static CallHierarchyIncomingCallsParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = CallHierarchyItem.fromJson(itemJson 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)''')));
    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 CallHierarchyIncomingCallsParams(
      item: item,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  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 (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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('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('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 CallHierarchyIncomingCallsParams');
      return false;
    }
  }

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

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

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

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

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

  /// 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?>{};
    __result['name'] = name;
    __result['kind'] = kind.toJson();
    if (tags != null) {
      __result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    if (detail != null) {
      __result['detail'] = detail;
    }
    __result['uri'] = uri;
    __result['range'] = range.toJson();
    __result['selectionRange'] = selectionRange.toJson();
    if (data != null) {
      __result['data'] = data;
    }
    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('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('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('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('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('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();
      }
      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 name == other.name &&
          kind == other.kind &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          detail == other.detail &&
          uri == other.uri &&
          range == other.range &&
          selectionRange == other.selectionRange &&
          data == other.data &&
          true;
    }
    return false;
  }

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

  @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.to,
    required this.fromRanges,
  });
  static CallHierarchyOutgoingCall fromJson(Map<String, Object?> json) {
    final toJson = json['to'];
    final to = CallHierarchyItem.fromJson(toJson 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 CallHierarchyOutgoingCall(
      to: to,
      fromRanges: fromRanges,
    );
  }

  /// 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['to'] = to.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('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();
      }
      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 CallHierarchyOutgoingCall');
      return false;
    }
  }

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

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

  @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.workDoneToken,
    this.partialResultToken,
  });
  static CallHierarchyOutgoingCallsParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = CallHierarchyItem.fromJson(itemJson 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)''')));
    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 CallHierarchyOutgoingCallsParams(
      item: item,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  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 (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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('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('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 CallHierarchyOutgoingCallsParams');
      return false;
    }
  }

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

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

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

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

  CallHierarchyPrepareParams({
    required this.textDocument,
    required this.position,
    this.workDoneToken,
  });
  static CallHierarchyPrepareParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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(
      textDocument: textDocument,
      position: position,
      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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    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();
      }
      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('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 textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        textDocument,
        position,
        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.workDoneProgress,
    this.id,
  });
  static CallHierarchyRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final idJson = json['id'];
    final id = idJson as String?;
    return CallHierarchyRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
      id: id,
    );
  }

  /// 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<DocumentFilter>? 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 (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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 CallHierarchyRegistrationOptions');
      return false;
    }
  }

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

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

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

  /// 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?>{};
    __result['label'] = label;
    if (needsConfirmation != null) {
      __result['needsConfirmation'] = needsConfirmation;
    }
    if (description != null) {
      __result['description'] = description;
    }
    return __result;
  }

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

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

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

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

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

  /// 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 ClientCapabilitiesWindow? window;

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workspace');
      try {
        final workspace = obj['workspace'];
        if (workspace != null &&
            !(ClientCapabilitiesWorkspace.canParse(workspace, reporter))) {
          reporter.reportError('must be of type ClientCapabilitiesWorkspace');
          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('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('window');
      try {
        final window = obj['window'];
        if (window != null &&
            !(ClientCapabilitiesWindow.canParse(window, reporter))) {
          reporter.reportError('must be of type ClientCapabilitiesWindow');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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 workspace == other.workspace &&
          textDocument == other.textDocument &&
          notebookDocument == other.notebookDocument &&
          window == other.window &&
          general == other.general &&
          experimental == other.experimental &&
          true;
    }
    return false;
  }

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

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

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

  ClientCapabilitiesFileOperations({
    this.dynamicRegistration,
    this.didCreate,
    this.willCreate,
    this.didRename,
    this.willRename,
    this.didDelete,
    this.willDelete,
  });
  static ClientCapabilitiesFileOperations fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final didCreateJson = json['didCreate'];
    final didCreate = didCreateJson as bool?;
    final willCreateJson = json['willCreate'];
    final willCreate = willCreateJson as bool?;
    final didRenameJson = json['didRename'];
    final didRename = didRenameJson as bool?;
    final willRenameJson = json['willRename'];
    final willRename = willRenameJson as bool?;
    final didDeleteJson = json['didDelete'];
    final didDelete = didDeleteJson as bool?;
    final willDeleteJson = json['willDelete'];
    final willDelete = willDeleteJson as bool?;
    return ClientCapabilitiesFileOperations(
      dynamicRegistration: dynamicRegistration,
      didCreate: didCreate,
      willCreate: willCreate,
      didRename: didRename,
      willRename: willRename,
      didDelete: didDelete,
      willDelete: willDelete,
    );
  }

  /// 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 (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (didCreate != null) {
      __result['didCreate'] = didCreate;
    }
    if (willCreate != null) {
      __result['willCreate'] = willCreate;
    }
    if (didRename != null) {
      __result['didRename'] = didRename;
    }
    if (willRename != null) {
      __result['willRename'] = willRename;
    }
    if (didDelete != null) {
      __result['didDelete'] = didDelete;
    }
    if (willDelete != null) {
      __result['willDelete'] = willDelete;
    }
    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('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('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('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('willRename');
      try {
        final willRename = obj['willRename'];
        if (willRename != null && !(willRename 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('willDelete');
      try {
        final willDelete = obj['willDelete'];
        if (willDelete != null && !(willDelete 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 dynamicRegistration == other.dynamicRegistration &&
          didCreate == other.didCreate &&
          willCreate == other.willCreate &&
          didRename == other.didRename &&
          willRename == other.willRename &&
          didDelete == other.didDelete &&
          willDelete == other.willDelete &&
          true;
    }
    return false;
  }

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

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

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

  ClientCapabilitiesGeneral({
    this.staleRequestSupport,
    this.regularExpressions,
    this.markdown,
    this.positionEncodings,
  });
  static ClientCapabilitiesGeneral fromJson(Map<String, Object?> json) {
    final staleRequestSupportJson = json['staleRequestSupport'];
    final staleRequestSupport = staleRequestSupportJson != null
        ? ClientCapabilitiesStaleRequestSupport.fromJson(
            staleRequestSupportJson as Map<String, Object?>)
        : null;
    final regularExpressionsJson = json['regularExpressions'];
    final regularExpressions = regularExpressionsJson != null
        ? RegularExpressionsClientCapabilities.fromJson(
            regularExpressionsJson as Map<String, Object?>)
        : null;
    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();
    return ClientCapabilitiesGeneral(
      staleRequestSupport: staleRequestSupport,
      regularExpressions: regularExpressions,
      markdown: markdown,
      positionEncodings: positionEncodings,
    );
  }

  /// 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 (staleRequestSupport != null) {
      __result['staleRequestSupport'] = staleRequestSupport?.toJson();
    }
    if (regularExpressions != null) {
      __result['regularExpressions'] = regularExpressions?.toJson();
    }
    if (markdown != null) {
      __result['markdown'] = markdown?.toJson();
    }
    if (positionEncodings != null) {
      __result['positionEncodings'] =
          positionEncodings?.map((item) => item.toJson()).toList();
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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('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();
      }
      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 staleRequestSupport == other.staleRequestSupport &&
          regularExpressions == other.regularExpressions &&
          markdown == other.markdown &&
          listEqual(positionEncodings, other.positionEncodings,
              (PositionEncodingKind a, PositionEncodingKind b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

  ClientCapabilitiesWindow({
    this.workDoneProgress,
    this.showMessage,
    this.showDocument,
  });
  static ClientCapabilitiesWindow fromJson(Map<String, Object?> json) {
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final showMessageJson = json['showMessage'];
    final showMessage = showMessageJson != null
        ? ShowMessageRequestClientCapabilities.fromJson(
            showMessageJson as Map<String, Object?>)
        : null;
    final showDocumentJson = json['showDocument'];
    final showDocument = showDocumentJson != null
        ? ShowDocumentClientCapabilities.fromJson(
            showDocumentJson as Map<String, Object?>)
        : null;
    return ClientCapabilitiesWindow(
      workDoneProgress: workDoneProgress,
      showMessage: showMessage,
      showDocument: showDocument,
    );
  }

  /// 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 (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (showMessage != null) {
      __result['showMessage'] = showMessage?.toJson();
    }
    if (showDocument != null) {
      __result['showDocument'] = showDocument?.toJson();
    }
    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();
      }
      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('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();
      }
      return true;
    } else {
      reporter.reportError('must be of type ClientCapabilitiesWindow');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ClientCapabilitiesWindow &&
        other.runtimeType == ClientCapabilitiesWindow) {
      return workDoneProgress == other.workDoneProgress &&
          showMessage == other.showMessage &&
          showDocument == other.showDocument &&
          true;
    }
    return false;
  }

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

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

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

  ClientCapabilitiesWorkspace({
    this.applyEdit,
    this.workspaceEdit,
    this.didChangeConfiguration,
    this.didChangeWatchedFiles,
    this.symbol,
    this.executeCommand,
    this.workspaceFolders,
    this.configuration,
    this.semanticTokens,
    this.codeLens,
    this.fileOperations,
    this.inlineValue,
    this.inlayHint,
    this.diagnostics,
  });
  static ClientCapabilitiesWorkspace fromJson(Map<String, Object?> json) {
    final applyEditJson = json['applyEdit'];
    final applyEdit = applyEditJson as bool?;
    final workspaceEditJson = json['workspaceEdit'];
    final workspaceEdit = workspaceEditJson != null
        ? WorkspaceEditClientCapabilities.fromJson(
            workspaceEditJson 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 symbolJson = json['symbol'];
    final symbol = symbolJson != null
        ? WorkspaceSymbolClientCapabilities.fromJson(
            symbolJson as Map<String, Object?>)
        : null;
    final executeCommandJson = json['executeCommand'];
    final executeCommand = executeCommandJson != null
        ? ExecuteCommandClientCapabilities.fromJson(
            executeCommandJson as Map<String, Object?>)
        : null;
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = workspaceFoldersJson as bool?;
    final configurationJson = json['configuration'];
    final configuration = configurationJson as bool?;
    final semanticTokensJson = json['semanticTokens'];
    final semanticTokens = semanticTokensJson != null
        ? SemanticTokensWorkspaceClientCapabilities.fromJson(
            semanticTokensJson as Map<String, Object?>)
        : null;
    final codeLensJson = json['codeLens'];
    final codeLens = codeLensJson != null
        ? CodeLensWorkspaceClientCapabilities.fromJson(
            codeLensJson as Map<String, Object?>)
        : null;
    final fileOperationsJson = json['fileOperations'];
    final fileOperations = fileOperationsJson != null
        ? ClientCapabilitiesFileOperations.fromJson(
            fileOperationsJson as Map<String, Object?>)
        : null;
    final inlineValueJson = json['inlineValue'];
    final inlineValue = inlineValueJson != null
        ? InlineValueWorkspaceClientCapabilities.fromJson(
            inlineValueJson as Map<String, Object?>)
        : null;
    final inlayHintJson = json['inlayHint'];
    final inlayHint = inlayHintJson != null
        ? InlayHintWorkspaceClientCapabilities.fromJson(
            inlayHintJson as Map<String, Object?>)
        : null;
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = diagnosticsJson != null
        ? DiagnosticWorkspaceClientCapabilities.fromJson(
            diagnosticsJson as Map<String, Object?>)
        : null;
    return ClientCapabilitiesWorkspace(
      applyEdit: applyEdit,
      workspaceEdit: workspaceEdit,
      didChangeConfiguration: didChangeConfiguration,
      didChangeWatchedFiles: didChangeWatchedFiles,
      symbol: symbol,
      executeCommand: executeCommand,
      workspaceFolders: workspaceFolders,
      configuration: configuration,
      semanticTokens: semanticTokens,
      codeLens: codeLens,
      fileOperations: fileOperations,
      inlineValue: inlineValue,
      inlayHint: inlayHint,
      diagnostics: diagnostics,
    );
  }

  /// 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 (workspaceEdit != null) {
      __result['workspaceEdit'] = workspaceEdit?.toJson();
    }
    if (didChangeConfiguration != null) {
      __result['didChangeConfiguration'] = didChangeConfiguration?.toJson();
    }
    if (didChangeWatchedFiles != null) {
      __result['didChangeWatchedFiles'] = didChangeWatchedFiles?.toJson();
    }
    if (symbol != null) {
      __result['symbol'] = symbol?.toJson();
    }
    if (executeCommand != null) {
      __result['executeCommand'] = executeCommand?.toJson();
    }
    if (workspaceFolders != null) {
      __result['workspaceFolders'] = workspaceFolders;
    }
    if (configuration != null) {
      __result['configuration'] = configuration;
    }
    if (semanticTokens != null) {
      __result['semanticTokens'] = semanticTokens?.toJson();
    }
    if (codeLens != null) {
      __result['codeLens'] = codeLens?.toJson();
    }
    if (fileOperations != null) {
      __result['fileOperations'] = fileOperations?.toJson();
    }
    if (inlineValue != null) {
      __result['inlineValue'] = inlineValue?.toJson();
    }
    if (inlayHint != null) {
      __result['inlayHint'] = inlayHint?.toJson();
    }
    if (diagnostics != null) {
      __result['diagnostics'] = diagnostics?.toJson();
    }
    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('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('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('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('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('workspaceFolders');
      try {
        final workspaceFolders = obj['workspaceFolders'];
        if (workspaceFolders != null && !(workspaceFolders is bool)) {
          reporter.reportError('must be of type bool');
          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('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('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('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('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('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('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();
      }
      return true;
    } else {
      reporter.reportError('must be of type ClientCapabilitiesWorkspace');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ClientCapabilitiesWorkspace &&
        other.runtimeType == ClientCapabilitiesWorkspace) {
      return applyEdit == other.applyEdit &&
          workspaceEdit == other.workspaceEdit &&
          didChangeConfiguration == other.didChangeConfiguration &&
          didChangeWatchedFiles == other.didChangeWatchedFiles &&
          symbol == other.symbol &&
          executeCommand == other.executeCommand &&
          workspaceFolders == other.workspaceFolders &&
          configuration == other.configuration &&
          semanticTokens == other.semanticTokens &&
          codeLens == other.codeLens &&
          fileOperations == other.fileOperations &&
          inlineValue == other.inlineValue &&
          inlayHint == other.inlayHint &&
          diagnostics == other.diagnostics &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        applyEdit,
        workspaceEdit,
        didChangeConfiguration,
        didChangeWatchedFiles,
        symbol,
        executeCommand,
        workspaceFolders,
        configuration,
        semanticTokens,
        codeLens,
        fileOperations,
        inlineValue,
        inlayHint,
        diagnostics,
      );

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

  /// 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?>{};
    __result['title'] = title;
    if (kind != null) {
      __result['kind'] = kind?.toJson();
    }
    if (diagnostics != null) {
      __result['diagnostics'] =
          diagnostics?.map((item) => item.toJson()).toList();
    }
    if (isPreferred != null) {
      __result['isPreferred'] = isPreferred;
    }
    if (disabled != null) {
      __result['disabled'] = disabled?.toJson();
    }
    if (edit != null) {
      __result['edit'] = edit?.toJson();
    }
    if (command != null) {
      __result['command'] = command?.toJson();
    }
    if (data != null) {
      __result['data'] = data;
    }
    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();
      }
      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('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('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('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('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();
      }
      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 title == other.title &&
          kind == other.kind &&
          listEqual(diagnostics, other.diagnostics,
              (Diagnostic a, Diagnostic b) => a == b) &&
          isPreferred == other.isPreferred &&
          disabled == other.disabled &&
          edit == other.edit &&
          command == other.command &&
          data == other.data &&
          true;
    }
    return false;
  }

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

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

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

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

  /// 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 (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (codeActionLiteralSupport != null) {
      __result['codeActionLiteralSupport'] = codeActionLiteralSupport?.toJson();
    }
    if (isPreferredSupport != null) {
      __result['isPreferredSupport'] = isPreferredSupport;
    }
    if (disabledSupport != null) {
      __result['disabledSupport'] = disabledSupport;
    }
    if (dataSupport != null) {
      __result['dataSupport'] = dataSupport;
    }
    if (resolveSupport != null) {
      __result['resolveSupport'] = resolveSupport?.toJson();
    }
    if (honorsChangeAnnotations != null) {
      __result['honorsChangeAnnotations'] = honorsChangeAnnotations;
    }
    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('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('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('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('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('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();
      }
      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();
      }
      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 dynamicRegistration == other.dynamicRegistration &&
          codeActionLiteralSupport == other.codeActionLiteralSupport &&
          isPreferredSupport == other.isPreferredSupport &&
          disabledSupport == other.disabledSupport &&
          dataSupport == other.dataSupport &&
          resolveSupport == other.resolveSupport &&
          honorsChangeAnnotations == other.honorsChangeAnnotations &&
          true;
    }
    return false;
  }

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

  @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.textDocument,
    required this.range,
    required this.context,
    this.workDoneToken,
    this.partialResultToken,
  });
  static CodeActionParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final contextJson = json['context'];
    final context =
        CodeActionContext.fromJson(contextJson 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)''')));
    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 CodeActionParams(
      textDocument: textDocument,
      range: range,
      context: context,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  /// 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['textDocument'] = textDocument.toJson();
    __result['range'] = range.toJson();
    __result['context'] = context.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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('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 CodeActionParams');
      return false;
    }
  }

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

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

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

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

  CodeActionRegistrationOptions({
    this.documentSelector,
    this.codeActionKinds,
    this.resolveProvider,
    this.workDoneProgress,
  });
  static CodeActionRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    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 CodeActionRegistrationOptions(
      documentSelector: documentSelector,
      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;

  /// 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<DocumentFilter>? 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?>{};
    __result['documentSelector'] = documentSelector;
    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('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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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 CodeActionRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is CodeActionRegistrationOptions &&
        other.runtimeType == CodeActionRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          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(documentSelector),
        lspHashCode(codeActionKinds),
        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({
    required this.range,
    this.command,
    this.data,
  });
  static CodeLens fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final commandJson = json['command'];
    final command = commandJson != null
        ? Command.fromJson(commandJson as Map<String, Object?>)
        : null;
    final dataJson = json['data'];
    final data = dataJson;
    return CodeLens(
      range: range,
      command: command,
      data: data,
    );
  }

  /// 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?>{};
    __result['range'] = range.toJson();
    if (command != null) {
      __result['command'] = command?.toJson();
    }
    if (data != null) {
      __result['data'] = data;
    }
    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('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();
      }
      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 range == other.range &&
          command == other.command &&
          data == other.data &&
          true;
    }
    return false;
  }

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

  @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({
    required this.textDocument,
    this.workDoneToken,
    this.partialResultToken,
  });
  static CodeLensParams fromJson(Map<String, Object?> json) {
    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)''')));
    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 CodeLensParams(
      textDocument: textDocument,
      workDoneToken: workDoneToken,
      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;

  /// 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?>{};
    __result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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 CodeLensParams');
      return false;
    }
  }

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

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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.red,
    required this.green,
    required this.blue,
    required this.alpha,
  });
  static Color fromJson(Map<String, Object?> json) {
    final redJson = json['red'];
    final red = redJson as num;
    final greenJson = json['green'];
    final green = greenJson as num;
    final blueJson = json['blue'];
    final blue = blueJson as num;
    final alphaJson = json['alpha'];
    final alpha = alphaJson as num;
    return Color(
      red: red,
      green: green,
      blue: blue,
      alpha: alpha,
    );
  }

  /// 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['red'] = red;
    __result['green'] = green;
    __result['blue'] = blue;
    __result['alpha'] = alpha;
    return __result;
  }

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

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

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

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

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

  /// 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['range'] = range.toJson();
    __result['color'] = color.toJson();
    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('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();
      }
      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 range == other.range && color == other.color && true;
    }
    return false;
  }

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

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

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

  ColorPresentation({
    required this.label,
    this.textEdit,
    this.additionalTextEdits,
  });
  static ColorPresentation fromJson(Map<String, Object?> json) {
    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;
    final additionalTextEditsJson = json['additionalTextEdits'];
    final additionalTextEdits = (additionalTextEditsJson as List<Object?>?)
        ?.map((item) => TextEdit.fromJson(item as Map<String, Object?>))
        .toList();
    return ColorPresentation(
      label: label,
      textEdit: textEdit,
      additionalTextEdits: additionalTextEdits,
    );
  }

  /// 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?>{};
    __result['label'] = label;
    if (textEdit != null) {
      __result['textEdit'] = textEdit?.toJson();
    }
    if (additionalTextEdits != null) {
      __result['additionalTextEdits'] =
          additionalTextEdits?.map((item) => item.toJson()).toList();
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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();
      }
      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 label == other.label &&
          textEdit == other.textEdit &&
          listEqual(additionalTextEdits, other.additionalTextEdits,
              (TextEdit a, TextEdit b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

  ColorPresentationParams({
    required this.textDocument,
    required this.color,
    required this.range,
    this.workDoneToken,
    this.partialResultToken,
  });
  static ColorPresentationParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    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?>);
    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 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 ColorPresentationParams(
      textDocument: textDocument,
      color: color,
      range: range,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  /// 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['textDocument'] = textDocument.toJson();
    __result['color'] = color.toJson();
    __result['range'] = range.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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();
      }
      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('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 ColorPresentationParams');
      return false;
    }
  }

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

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

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

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

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

  /// 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?>{};
    __result['title'] = title;
    __result['command'] = command;
    if (arguments != null) {
      __result['arguments'] = arguments;
    }
    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();
      }
      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('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();
      }
      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 title == other.title &&
          command == other.command &&
          listEqual(
              arguments, other.arguments, (Object? a, Object? b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

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

  /// 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 (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (completionItem != null) {
      __result['completionItem'] = completionItem?.toJson();
    }
    if (completionItemKind != null) {
      __result['completionItemKind'] = completionItemKind?.toJson();
    }
    if (contextSupport != null) {
      __result['contextSupport'] = contextSupport;
    }
    if (insertTextMode != null) {
      __result['insertTextMode'] = insertTextMode?.toJson();
    }
    if (completionList != null) {
      __result['completionList'] = completionList?.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('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('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('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('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();
      }
      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 dynamicRegistration == other.dynamicRegistration &&
          completionItem == other.completionItem &&
          completionItemKind == other.completionItemKind &&
          contextSupport == other.contextSupport &&
          insertTextMode == other.insertTextMode &&
          completionList == other.completionList &&
          true;
    }
    return false;
  }

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

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

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

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

  /// 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 (snippetSupport != null) {
      __result['snippetSupport'] = snippetSupport;
    }
    if (commitCharactersSupport != null) {
      __result['commitCharactersSupport'] = commitCharactersSupport;
    }
    if (documentationFormat != null) {
      __result['documentationFormat'] =
          documentationFormat?.map((item) => item.toJson()).toList();
    }
    if (deprecatedSupport != null) {
      __result['deprecatedSupport'] = deprecatedSupport;
    }
    if (preselectSupport != null) {
      __result['preselectSupport'] = preselectSupport;
    }
    if (tagSupport != null) {
      __result['tagSupport'] = tagSupport?.toJson();
    }
    if (insertReplaceSupport != null) {
      __result['insertReplaceSupport'] = insertReplaceSupport;
    }
    if (resolveSupport != null) {
      __result['resolveSupport'] = resolveSupport?.toJson();
    }
    if (insertTextModeSupport != null) {
      __result['insertTextModeSupport'] = insertTextModeSupport?.toJson();
    }
    if (labelDetailsSupport != null) {
      __result['labelDetailsSupport'] = labelDetailsSupport;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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('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('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('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('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();
      }
      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('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('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();
      }
      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 snippetSupport == other.snippetSupport &&
          commitCharactersSupport == other.commitCharactersSupport &&
          listEqual(documentationFormat, other.documentationFormat,
              (MarkupKind a, MarkupKind b) => a == b) &&
          deprecatedSupport == other.deprecatedSupport &&
          preselectSupport == other.preselectSupport &&
          tagSupport == other.tagSupport &&
          insertReplaceSupport == other.insertReplaceSupport &&
          resolveSupport == other.resolveSupport &&
          insertTextModeSupport == other.insertTextModeSupport &&
          labelDetailsSupport == other.labelDetailsSupport &&
          true;
    }
    return false;
  }

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

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

  /// 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?>{};
    __result['triggerKind'] = triggerKind.toJson();
    if (triggerCharacter != null) {
      __result['triggerCharacter'] = triggerCharacter;
    }
    return __result;
  }

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

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

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

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

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

  /// 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<String, MarkupContent>? 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<TextEdit, InsertReplaceEdit>? 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?>{};
    __result['label'] = label;
    if (labelDetails != null) {
      __result['labelDetails'] = labelDetails?.toJson();
    }
    if (kind != null) {
      __result['kind'] = kind?.toJson();
    }
    if (tags != null) {
      __result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    if (detail != null) {
      __result['detail'] = detail;
    }
    if (documentation != null) {
      __result['documentation'] = documentation;
    }
    if (deprecated != null) {
      __result['deprecated'] = deprecated;
    }
    if (preselect != null) {
      __result['preselect'] = preselect;
    }
    if (sortText != null) {
      __result['sortText'] = sortText;
    }
    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 (textEdit != null) {
      __result['textEdit'] = textEdit;
    }
    if (textEditText != null) {
      __result['textEditText'] = textEditText;
    }
    if (additionalTextEdits != null) {
      __result['additionalTextEdits'] =
          additionalTextEdits?.map((item) => item.toJson()).toList();
    }
    if (commitCharacters != null) {
      __result['commitCharacters'] = commitCharacters;
    }
    if (command != null) {
      __result['command'] = command?.toJson();
    }
    if (data != null) {
      __result['data'] = data?.toJson();
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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('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('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 &&
            !((documentation is String ||
                MarkupContent.canParse(documentation, reporter)))) {
          reporter
              .reportError('must be of type Either2<String, MarkupContent>');
          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('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('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('textEdit');
      try {
        final textEdit = obj['textEdit'];
        if (textEdit != null &&
            !((TextEdit.canParse(textEdit, reporter) ||
                InsertReplaceEdit.canParse(textEdit, reporter)))) {
          reporter.reportError(
              'must be of type Either2<TextEdit, InsertReplaceEdit>');
          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();
      }
      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('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('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('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();
      }
      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 label == other.label &&
          labelDetails == other.labelDetails &&
          kind == other.kind &&
          listEqual(tags, other.tags,
              (CompletionItemTag a, CompletionItemTag b) => a == b) &&
          detail == other.detail &&
          documentation == other.documentation &&
          deprecated == other.deprecated &&
          preselect == other.preselect &&
          sortText == other.sortText &&
          filterText == other.filterText &&
          insertText == other.insertText &&
          insertTextFormat == other.insertTextFormat &&
          insertTextMode == other.insertTextMode &&
          textEdit == other.textEdit &&
          textEditText == other.textEditText &&
          listEqual(additionalTextEdits, other.additionalTextEdits,
              (TextEdit a, TextEdit b) => a == b) &&
          listEqual(commitCharacters, other.commitCharacters,
              (String a, String b) => a == b) &&
          command == other.command &&
          data == other.data &&
          true;
    }
    return false;
  }

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

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

  /// 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 (detail != null) {
      __result['detail'] = detail;
    }
    if (description != null) {
      __result['description'] = description;
    }
    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('description');
      try {
        final description = obj['description'];
        if (description != null && !(description 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 detail == other.detail && description == other.description && true;
    }
    return false;
  }

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

  @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
        : (Range.canParse(editRangeJson, nullLspJsonReporter)
            ? Either2<Range, CompletionListEditRange>.t1(
                Range.fromJson(editRangeJson as Map<String, Object?>))
            : (CompletionListEditRange.canParse(
                    editRangeJson, nullLspJsonReporter)
                ? Either2<Range, CompletionListEditRange>.t2(
                    CompletionListEditRange.fromJson(
                        editRangeJson as Map<String, Object?>))
                : (throw '''$editRangeJson was not one of (Range, CompletionListEditRange)''')));
    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<Range, CompletionListEditRange>? 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 &&
            !((Range.canParse(editRange, reporter) ||
                CompletionListEditRange.canParse(editRange, reporter)))) {
          reporter.reportError(
              'must be of type Either2<Range, CompletionListEditRange>');
          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.triggerCharacters,
    this.allCommitCharacters,
    this.resolveProvider,
    this.completionItem,
    this.workDoneProgress,
  });
  static CompletionOptions fromJson(Map<String, Object?> json) {
    if (CompletionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionRegistrationOptions.fromJson(json);
    }
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final allCommitCharactersJson = json['allCommitCharacters'];
    final allCommitCharacters = (allCommitCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final completionItemJson = json['completionItem'];
    final completionItem = completionItemJson != null
        ? CompletionOptionsCompletionItem.fromJson(
            completionItemJson as Map<String, Object?>)
        : null;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CompletionOptions(
      triggerCharacters: triggerCharacters,
      allCommitCharacters: allCommitCharacters,
      resolveProvider: resolveProvider,
      completionItem: completionItem,
      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 (triggerCharacters != null) {
      __result['triggerCharacters'] = triggerCharacters;
    }
    if (allCommitCharacters != null) {
      __result['allCommitCharacters'] = allCommitCharacters;
    }
    if (resolveProvider != null) {
      __result['resolveProvider'] = resolveProvider;
    }
    if (completionItem != null) {
      __result['completionItem'] = completionItem?.toJson();
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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('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('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('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(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          listEqual(allCommitCharacters, other.allCommitCharacters,
              (String a, String b) => a == b) &&
          resolveProvider == other.resolveProvider &&
          completionItem == other.completionItem &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(triggerCharacters),
        lspHashCode(allCommitCharacters),
        resolveProvider,
        completionItem,
        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,
    required this.textDocument,
    required this.position,
    this.workDoneToken,
    this.partialResultToken,
  });
  static CompletionParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context = contextJson != null
        ? CompletionContext.fromJson(contextJson as Map<String, Object?>)
        : null;
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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)''')));
    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 CompletionParams(
      context: context,
      textDocument: textDocument,
      position: position,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  /// 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();
    }
    __result['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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('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('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('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('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 CompletionParams');
      return false;
    }
  }

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

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

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

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

  CompletionRegistrationOptions({
    this.documentSelector,
    this.triggerCharacters,
    this.allCommitCharacters,
    this.resolveProvider,
    this.completionItem,
    this.workDoneProgress,
  });
  static CompletionRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final allCommitCharactersJson = json['allCommitCharacters'];
    final allCommitCharacters = (allCommitCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final completionItemJson = json['completionItem'];
    final completionItem = completionItemJson != null
        ? CompletionOptionsCompletionItem.fromJson(
            completionItemJson as Map<String, Object?>)
        : null;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CompletionRegistrationOptions(
      documentSelector: documentSelector,
      triggerCharacters: triggerCharacters,
      allCommitCharacters: allCommitCharacters,
      resolveProvider: resolveProvider,
      completionItem: completionItem,
      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<DocumentFilter>? 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?>{};
    __result['documentSelector'] = documentSelector;
    if (triggerCharacters != null) {
      __result['triggerCharacters'] = triggerCharacters;
    }
    if (allCommitCharacters != null) {
      __result['allCommitCharacters'] = allCommitCharacters;
    }
    if (resolveProvider != null) {
      __result['resolveProvider'] = resolveProvider;
    }
    if (completionItem != null) {
      __result['completionItem'] = completionItem?.toJson();
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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('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('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('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(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          listEqual(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          listEqual(allCommitCharacters, other.allCommitCharacters,
              (String a, String b) => a == b) &&
          resolveProvider == other.resolveProvider &&
          completionItem == other.completionItem &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        lspHashCode(triggerCharacters),
        lspHashCode(allCommitCharacters),
        resolveProvider,
        completionItem,
        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.kind = 'create',
    required this.uri,
    this.options,
    this.annotationId,
  }) {
    if (kind != 'create') {
      throw 'kind may only be the literal \'create\'';
    }
  }
  static CreateFile fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? CreateFileOptions.fromJson(optionsJson as Map<String, Object?>)
        : null;
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    return CreateFile(
      kind: kind,
      uri: uri,
      options: options,
      annotationId: annotationId,
    );
  }

  /// 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?>{};
    __result['kind'] = kind;
    __result['uri'] = uri;
    if (options != null) {
      __result['options'] = options?.toJson();
    }
    if (annotationId != null) {
      __result['annotationId'] = annotationId;
    }
    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 == 'create')) {
          reporter.reportError('must be the literal \'create\'');
          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('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('annotationId');
      try {
        final annotationId = obj['annotationId'];
        if (annotationId != null && !(annotationId 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 kind == other.kind &&
          uri == other.uri &&
          options == other.options &&
          annotationId == other.annotationId &&
          true;
    }
    return false;
  }

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

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

  /// 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 (overwrite != null) {
      __result['overwrite'] = overwrite;
    }
    if (ignoreIfExists != null) {
      __result['ignoreIfExists'] = ignoreIfExists;
    }
    return __result;
  }

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

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

  @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({
    required this.textDocument,
    required this.position,
    this.workDoneToken,
    this.partialResultToken,
  });
  static DeclarationParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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)''')));
    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 DeclarationParams(
      textDocument: textDocument,
      position: position,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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 DeclarationParams');
      return false;
    }
  }

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

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

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

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

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

  /// 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<DocumentFilter>? 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?>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    __result['documentSelector'] = documentSelector;
    if (id != null) {
      __result['id'] = id;
    }
    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();
      }
      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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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();
      }
      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 workDoneProgress == other.workDoneProgress &&
          listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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({
    required this.textDocument,
    required this.position,
    this.workDoneToken,
    this.partialResultToken,
  });
  static DefinitionParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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)''')));
    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 DefinitionParams(
      textDocument: textDocument,
      position: position,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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 DefinitionParams');
      return false;
    }
  }

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

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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.kind = 'delete',
    required this.uri,
    this.options,
    this.annotationId,
  }) {
    if (kind != 'delete') {
      throw 'kind may only be the literal \'delete\'';
    }
  }
  static DeleteFile fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? DeleteFileOptions.fromJson(optionsJson as Map<String, Object?>)
        : null;
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    return DeleteFile(
      kind: kind,
      uri: uri,
      options: options,
      annotationId: annotationId,
    );
  }

  /// 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?>{};
    __result['kind'] = kind;
    __result['uri'] = uri;
    if (options != null) {
      __result['options'] = options?.toJson();
    }
    if (annotationId != null) {
      __result['annotationId'] = annotationId;
    }
    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 == 'delete')) {
          reporter.reportError('must be the literal \'delete\'');
          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('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('annotationId');
      try {
        final annotationId = obj['annotationId'];
        if (annotationId != null && !(annotationId 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 kind == other.kind &&
          uri == other.uri &&
          options == other.options &&
          annotationId == other.annotationId &&
          true;
    }
    return false;
  }

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

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

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

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

  /// 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 (recursive != null) {
      __result['recursive'] = recursive;
    }
    if (ignoreIfNotExists != null) {
      __result['ignoreIfNotExists'] = ignoreIfNotExists;
    }
    return __result;
  }

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

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

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

  /// 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?>{};
    __result['range'] = range.toJson();
    if (severity != null) {
      __result['severity'] = severity?.toJson();
    }
    if (code != null) {
      __result['code'] = code;
    }
    if (codeDescription != null) {
      __result['codeDescription'] = codeDescription?.toJson();
    }
    if (source != null) {
      __result['source'] = source;
    }
    __result['message'] = message;
    if (tags != null) {
      __result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    if (relatedInformation != null) {
      __result['relatedInformation'] =
          relatedInformation?.map((item) => item.toJson()).toList();
    }
    if (data != null) {
      __result['data'] = data;
    }
    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('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('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('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('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('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();
      }
      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();
      }
      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 range == other.range &&
          severity == other.severity &&
          code == other.code &&
          codeDescription == other.codeDescription &&
          source == other.source &&
          message == other.message &&
          listEqual(
              tags, other.tags, (DiagnosticTag a, DiagnosticTag b) => a == b) &&
          listEqual(
              relatedInformation,
              other.relatedInformation,
              (DiagnosticRelatedInformation a,
                      DiagnosticRelatedInformation b) =>
                  a == b) &&
          data == other.data &&
          true;
    }
    return false;
  }

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

  @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,
    required this.workspaceDiagnostics,
    this.workDoneProgress,
  });
  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 workspaceDiagnosticsJson = json['workspaceDiagnostics'];
    final workspaceDiagnostics = workspaceDiagnosticsJson as bool;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DiagnosticOptions(
      identifier: identifier,
      interFileDependencies: interFileDependencies,
      workspaceDiagnostics: workspaceDiagnostics,
      workDoneProgress: workDoneProgress,
    );
  }

  /// 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;
    __result['workspaceDiagnostics'] = workspaceDiagnostics;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    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('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();
      }
      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 DiagnosticOptions');
      return false;
    }
  }

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

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

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

  /// 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<DocumentFilter>? 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 (identifier != null) {
      __result['identifier'] = identifier;
    }
    __result['interFileDependencies'] = interFileDependencies;
    __result['workspaceDiagnostics'] = workspaceDiagnostics;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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();
      }
      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('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 DiagnosticRegistrationOptions');
      return false;
    }
  }

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

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

  @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.notebookDocument,
    required this.change,
  });
  static DidChangeNotebookDocumentParams fromJson(Map<String, Object?> json) {
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument = VersionedNotebookDocumentIdentifier.fromJson(
        notebookDocumentJson as Map<String, Object?>);
    final changeJson = json['change'];
    final change = NotebookDocumentChangeEvent.fromJson(
        changeJson as Map<String, Object?>);
    return DidChangeNotebookDocumentParams(
      notebookDocument: notebookDocument,
      change: change,
    );
  }

  /// 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['notebookDocument'] = notebookDocument.toJson();
    __result['change'] = change.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 (!(VersionedNotebookDocumentIdentifier.canParse(
            notebookDocument, reporter))) {
          reporter.reportError(
              'must be of type VersionedNotebookDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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 notebookDocument == other.notebookDocument &&
          change == other.change &&
          true;
    }
    return false;
  }

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

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

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

  DidChangeTextDocumentParams({
    required this.textDocument,
    required this.contentChanges,
  });
  static DidChangeTextDocumentParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = VersionedTextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    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();
    return DidChangeTextDocumentParams(
      textDocument: textDocument,
      contentChanges: contentChanges,
    );
  }

  /// 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['textDocument'] = textDocument.toJson();
    __result['contentChanges'] = contentChanges;
    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 (!(VersionedTextDocumentIdentifier.canParse(
            textDocument, reporter))) {
          reporter
              .reportError('must be of type VersionedTextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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 textDocument == other.textDocument &&
          listEqual(
              contentChanges,
              other.contentChanges,
              (Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          a,
                      Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        textDocument,
        lspHashCode(contentChanges),
      );

  @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.notebookDocument,
    required this.cellTextDocuments,
  });
  static DidCloseNotebookDocumentParams fromJson(Map<String, Object?> json) {
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument = NotebookDocumentIdentifier.fromJson(
        notebookDocumentJson as Map<String, Object?>);
    final cellTextDocumentsJson = json['cellTextDocuments'];
    final cellTextDocuments = (cellTextDocumentsJson as List<Object?>)
        .map((item) =>
            TextDocumentIdentifier.fromJson(item as Map<String, Object?>))
        .toList();
    return DidCloseNotebookDocumentParams(
      notebookDocument: notebookDocument,
      cellTextDocuments: cellTextDocuments,
    );
  }

  /// 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['notebookDocument'] = notebookDocument.toJson();
    __result['cellTextDocuments'] =
        cellTextDocuments.map((item) => item.toJson()).toList();
    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();
      }
      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();
      }
      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 notebookDocument == other.notebookDocument &&
          listEqual(cellTextDocuments, other.cellTextDocuments,
              (TextDocumentIdentifier a, TextDocumentIdentifier b) => a == b) &&
          true;
    }
    return false;
  }

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

  @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.notebookDocument,
    required this.cellTextDocuments,
  });
  static DidOpenNotebookDocumentParams fromJson(Map<String, Object?> json) {
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument =
        NotebookDocument.fromJson(notebookDocumentJson as Map<String, Object?>);
    final cellTextDocumentsJson = json['cellTextDocuments'];
    final cellTextDocuments = (cellTextDocumentsJson as List<Object?>)
        .map((item) => TextDocumentItem.fromJson(item as Map<String, Object?>))
        .toList();
    return DidOpenNotebookDocumentParams(
      notebookDocument: notebookDocument,
      cellTextDocuments: cellTextDocuments,
    );
  }

  /// 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['notebookDocument'] = notebookDocument.toJson();
    __result['cellTextDocuments'] =
        cellTextDocuments.map((item) => item.toJson()).toList();
    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 (!(NotebookDocument.canParse(notebookDocument, reporter))) {
          reporter.reportError('must be of type NotebookDocument');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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 notebookDocument == other.notebookDocument &&
          listEqual(cellTextDocuments, other.cellTextDocuments,
              (TextDocumentItem a, TextDocumentItem b) => a == b) &&
          true;
    }
    return false;
  }

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

  @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({
    required this.textDocument,
    this.text,
  });
  static DidSaveTextDocumentParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final textJson = json['text'];
    final text = textJson as String?;
    return DidSaveTextDocumentParams(
      textDocument: textDocument,
      text: text,
    );
  }

  /// 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?>{};
    __result['textDocument'] = textDocument.toJson();
    if (text != null) {
      __result['text'] = text;
    }
    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();
      }
      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();
      }
      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 textDocument == other.textDocument && text == other.text && true;
    }
    return false;
  }

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

  @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({
    required this.textDocument,
    this.workDoneToken,
    this.partialResultToken,
  });
  static DocumentColorParams fromJson(Map<String, Object?> json) {
    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)''')));
    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 DocumentColorParams(
      textDocument: textDocument,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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 DocumentColorParams');
      return false;
    }
  }

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

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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({
    required this.textDocument,
    this.identifier,
    this.previousResultId,
    this.workDoneToken,
    this.partialResultToken,
  });
  static DocumentDiagnosticParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String?;
    final previousResultIdJson = json['previousResultId'];
    final previousResultId = previousResultIdJson 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)''')));
    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 DocumentDiagnosticParams(
      textDocument: textDocument,
      identifier: identifier,
      previousResultId: previousResultId,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  /// 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?>{};
    __result['textDocument'] = textDocument.toJson();
    if (identifier != null) {
      __result['identifier'] = identifier;
    }
    if (previousResultId != null) {
      __result['previousResultId'] = previousResultId;
    }
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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('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 DocumentDiagnosticParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentDiagnosticParams &&
        other.runtimeType == DocumentDiagnosticParams) {
      return textDocument == other.textDocument &&
          identifier == other.identifier &&
          previousResultId == other.previousResultId &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

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

  @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 DocumentFilter implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFilter.canParse,
    DocumentFilter.fromJson,
  );

  DocumentFilter({
    this.language,
    this.scheme,
    this.pattern,
  });
  static DocumentFilter fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    return DocumentFilter(
      language: language,
      scheme: scheme,
      pattern: pattern,
    );
  }

  /// 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 (scheme != null) {
      __result['scheme'] = scheme;
    }
    if (pattern != null) {
      __result['pattern'] = pattern;
    }
    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('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && !(scheme 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();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentFilter');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentFilter && other.runtimeType == DocumentFilter) {
      return language == other.language &&
          scheme == other.scheme &&
          pattern == other.pattern &&
          true;
    }
    return false;
  }

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

  @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.textDocument,
    required this.options,
    this.workDoneToken,
  });
  static DocumentFormattingParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson 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(
      textDocument: textDocument,
      options: options,
      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['textDocument'] = textDocument.toJson();
    __result['options'] = options.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    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();
      }
      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('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 textDocument == other.textDocument &&
          options == other.options &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        textDocument,
        options,
        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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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({
    required this.range,
    this.kind,
  });
  static DocumentHighlight fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final kindJson = json['kind'];
    final kind = kindJson != null
        ? DocumentHighlightKind.fromJson(kindJson as int)
        : null;
    return DocumentHighlight(
      range: range,
      kind: kind,
    );
  }

  /// 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?>{};
    __result['range'] = range.toJson();
    if (kind != null) {
      __result['kind'] = kind?.toJson();
    }
    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('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();
      }
      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 range == other.range && kind == other.kind && true;
    }
    return false;
  }

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

  @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({
    required this.textDocument,
    required this.position,
    this.workDoneToken,
    this.partialResultToken,
  });
  static DocumentHighlightParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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)''')));
    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 DocumentHighlightParams(
      textDocument: textDocument,
      position: position,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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 DocumentHighlightParams');
      return false;
    }
  }

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

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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({
    required this.range,
    this.target,
    this.tooltip,
    this.data,
  });
  static DocumentLink fromJson(Map<String, Object?> json) {
    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?;
    final dataJson = json['data'];
    final data = dataJson;
    return DocumentLink(
      range: range,
      target: target,
      tooltip: tooltip,
      data: data,
    );
  }

  /// 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?>{};
    __result['range'] = range.toJson();
    if (target != null) {
      __result['target'] = target;
    }
    if (tooltip != null) {
      __result['tooltip'] = tooltip;
    }
    if (data != null) {
      __result['data'] = data;
    }
    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 range == other.range &&
          target == other.target &&
          tooltip == other.tooltip &&
          data == other.data &&
          true;
    }
    return false;
  }

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

  @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({
    required this.textDocument,
    this.workDoneToken,
    this.partialResultToken,
  });
  static DocumentLinkParams fromJson(Map<String, Object?> json) {
    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)''')));
    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 DocumentLinkParams(
      textDocument: textDocument,
      workDoneToken: workDoneToken,
      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;

  /// 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?>{};
    __result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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 DocumentLinkParams');
      return false;
    }
  }

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

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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.textDocument,
    required this.position,
    required this.ch,
    required this.options,
  });
  static DocumentOnTypeFormattingParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final chJson = json['ch'];
    final ch = chJson as String;
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    return DocumentOnTypeFormattingParams(
      textDocument: textDocument,
      position: position,
      ch: ch,
      options: options,
    );
  }

  /// 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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    __result['ch'] = ch;
    __result['options'] = options.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();
      }
      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('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();
      }
      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 textDocument == other.textDocument &&
          position == other.position &&
          ch == other.ch &&
          options == other.options &&
          true;
    }
    return false;
  }

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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.textDocument,
    required this.range,
    required this.options,
    this.workDoneToken,
  });
  static DocumentRangeFormattingParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson 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(
      textDocument: textDocument,
      range: range,
      options: options,
      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['textDocument'] = textDocument.toJson();
    __result['range'] = range.toJson();
    __result['options'] = options.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    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();
      }
      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('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('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 textDocument == other.textDocument &&
          range == other.range &&
          options == other.options &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        textDocument,
        range,
        options,
        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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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({
    required this.name,
    this.detail,
    required this.kind,
    this.tags,
    this.deprecated,
    required this.range,
    required this.selectionRange,
    this.children,
  });
  static DocumentSymbol fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    final deprecatedJson = json['deprecated'];
    final deprecated = deprecatedJson as bool?;
    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 childrenJson = json['children'];
    final children = (childrenJson as List<Object?>?)
        ?.map((item) => DocumentSymbol.fromJson(item as Map<String, Object?>))
        .toList();
    return DocumentSymbol(
      name: name,
      detail: detail,
      kind: kind,
      tags: tags,
      deprecated: deprecated,
      range: range,
      selectionRange: selectionRange,
      children: children,
    );
  }

  /// 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?>{};
    __result['name'] = name;
    if (detail != null) {
      __result['detail'] = detail;
    }
    __result['kind'] = kind.toJson();
    if (tags != null) {
      __result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    if (deprecated != null) {
      __result['deprecated'] = deprecated;
    }
    __result['range'] = range.toJson();
    __result['selectionRange'] = selectionRange.toJson();
    if (children != null) {
      __result['children'] = children?.map((item) => item.toJson()).toList();
    }
    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('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('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('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('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('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();
      }
      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 name == other.name &&
          detail == other.detail &&
          kind == other.kind &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          deprecated == other.deprecated &&
          range == other.range &&
          selectionRange == other.selectionRange &&
          listEqual(children, other.children,
              (DocumentSymbol a, DocumentSymbol b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

  DocumentSymbolClientCapabilities({
    this.dynamicRegistration,
    this.symbolKind,
    this.hierarchicalDocumentSymbolSupport,
    this.tagSupport,
    this.labelSupport,
  });
  static DocumentSymbolClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final symbolKindJson = json['symbolKind'];
    final symbolKind = symbolKindJson != null
        ? DocumentSymbolClientCapabilitiesSymbolKind.fromJson(
            symbolKindJson as Map<String, Object?>)
        : null;
    final hierarchicalDocumentSymbolSupportJson =
        json['hierarchicalDocumentSymbolSupport'];
    final hierarchicalDocumentSymbolSupport =
        hierarchicalDocumentSymbolSupportJson as bool?;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? DocumentSymbolClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    final labelSupportJson = json['labelSupport'];
    final labelSupport = labelSupportJson as bool?;
    return DocumentSymbolClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      symbolKind: symbolKind,
      hierarchicalDocumentSymbolSupport: hierarchicalDocumentSymbolSupport,
      tagSupport: tagSupport,
      labelSupport: labelSupport,
    );
  }

  /// 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 (symbolKind != null) {
      __result['symbolKind'] = symbolKind?.toJson();
    }
    if (hierarchicalDocumentSymbolSupport != null) {
      __result['hierarchicalDocumentSymbolSupport'] =
          hierarchicalDocumentSymbolSupport;
    }
    if (tagSupport != null) {
      __result['tagSupport'] = tagSupport?.toJson();
    }
    if (labelSupport != null) {
      __result['labelSupport'] = labelSupport;
    }
    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('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('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('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();
      }
      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();
      }
      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 &&
          symbolKind == other.symbolKind &&
          hierarchicalDocumentSymbolSupport ==
              other.hierarchicalDocumentSymbolSupport &&
          tagSupport == other.tagSupport &&
          labelSupport == other.labelSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        symbolKind,
        hierarchicalDocumentSymbolSupport,
        tagSupport,
        labelSupport,
      );

  @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({
    required this.textDocument,
    this.workDoneToken,
    this.partialResultToken,
  });
  static DocumentSymbolParams fromJson(Map<String, Object?> json) {
    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)''')));
    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 DocumentSymbolParams(
      textDocument: textDocument,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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 DocumentSymbolParams');
      return false;
    }
  }

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

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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({
    required this.command,
    this.arguments,
    this.workDoneToken,
  });
  static ExecuteCommandParams fromJson(Map<String, Object?> json) {
    final commandJson = json['command'];
    final command = commandJson as String;
    final argumentsJson = json['arguments'];
    final arguments =
        (argumentsJson as List<Object?>?)?.map((item) => item).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 ExecuteCommandParams(
      command: command,
      arguments: arguments,
      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?>{};
    __result['command'] = command;
    if (arguments != null) {
      __result['arguments'] = arguments;
    }
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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('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 command == other.command &&
          listEqual(
              arguments, other.arguments, (Object? a, Object? b) => a == b) &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        command,
        lspHashCode(arguments),
        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.uri,
    required this.type,
  });
  static FileEvent fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final typeJson = json['type'];
    final type = typeJson as int;
    return FileEvent(
      uri: uri,
      type: type,
    );
  }

  /// The change type.
  final int type;

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

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['uri'] = uri;
    __result['type'] = type;
    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('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();
      }
      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 uri == other.uri && type == other.type && true;
    }
    return false;
  }

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

  @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({
    this.scheme,
    required this.pattern,
  });
  static FileOperationFilter fromJson(Map<String, Object?> json) {
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    final patternJson = json['pattern'];
    final pattern =
        FileOperationPattern.fromJson(patternJson as Map<String, Object?>);
    return FileOperationFilter(
      scheme: scheme,
      pattern: pattern,
    );
  }

  /// 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?>{};
    if (scheme != null) {
      __result['scheme'] = scheme;
    }
    __result['pattern'] = pattern.toJson();
    return __result;
  }

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

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

  @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.oldUri,
    required this.newUri,
  });
  static FileRename fromJson(Map<String, Object?> json) {
    final oldUriJson = json['oldUri'];
    final oldUri = oldUriJson as String;
    final newUriJson = json['newUri'];
    final newUri = newUriJson as String;
    return FileRename(
      oldUri: oldUri,
      newUri: newUri,
    );
  }

  /// 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['oldUri'] = oldUri;
    __result['newUri'] = newUri;
    return __result;
  }

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

  @override
  int get hashCode => Object.hash(
        oldUri,
        newUri,
      );

  @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({
    required this.startLine,
    this.startCharacter,
    required this.endLine,
    this.endCharacter,
    this.kind,
    this.collapsedText,
  });
  static FoldingRange fromJson(Map<String, Object?> json) {
    final startLineJson = json['startLine'];
    final startLine = startLineJson as int;
    final startCharacterJson = json['startCharacter'];
    final startCharacter = startCharacterJson as int?;
    final endLineJson = json['endLine'];
    final endLine = endLineJson as int;
    final endCharacterJson = json['endCharacter'];
    final endCharacter = endCharacterJson as int?;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? FoldingRangeKind.fromJson(kindJson as String) : null;
    final collapsedTextJson = json['collapsedText'];
    final collapsedText = collapsedTextJson as String?;
    return FoldingRange(
      startLine: startLine,
      startCharacter: startCharacter,
      endLine: endLine,
      endCharacter: endCharacter,
      kind: kind,
      collapsedText: collapsedText,
    );
  }

  /// 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?>{};
    __result['startLine'] = startLine;
    if (startCharacter != null) {
      __result['startCharacter'] = startCharacter;
    }
    __result['endLine'] = endLine;
    if (endCharacter != null) {
      __result['endCharacter'] = endCharacter;
    }
    if (kind != null) {
      __result['kind'] = kind?.toJson();
    }
    if (collapsedText != null) {
      __result['collapsedText'] = collapsedText;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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('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('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('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('collapsedText');
      try {
        final collapsedText = obj['collapsedText'];
        if (collapsedText != null && !(collapsedText is String)) {
          reporter.reportError('must be of type String');
          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 startLine == other.startLine &&
          startCharacter == other.startCharacter &&
          endLine == other.endLine &&
          endCharacter == other.endCharacter &&
          kind == other.kind &&
          collapsedText == other.collapsedText &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        startLine,
        startCharacter,
        endLine,
        endCharacter,
        kind,
        collapsedText,
      );

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

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

  FoldingRangeClientCapabilities({
    this.dynamicRegistration,
    this.rangeLimit,
    this.lineFoldingOnly,
    this.foldingRangeKind,
    this.foldingRange,
  });
  static FoldingRangeClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final rangeLimitJson = json['rangeLimit'];
    final rangeLimit = rangeLimitJson as int?;
    final lineFoldingOnlyJson = json['lineFoldingOnly'];
    final lineFoldingOnly = lineFoldingOnlyJson as bool?;
    final foldingRangeKindJson = json['foldingRangeKind'];
    final foldingRangeKind = foldingRangeKindJson != null
        ? FoldingRangeClientCapabilitiesFoldingRangeKind.fromJson(
            foldingRangeKindJson as Map<String, Object?>)
        : null;
    final foldingRangeJson = json['foldingRange'];
    final foldingRange = foldingRangeJson != null
        ? FoldingRangeClientCapabilitiesFoldingRange.fromJson(
            foldingRangeJson as Map<String, Object?>)
        : null;
    return FoldingRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      rangeLimit: rangeLimit,
      lineFoldingOnly: lineFoldingOnly,
      foldingRangeKind: foldingRangeKind,
      foldingRange: foldingRange,
    );
  }

  /// 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 (rangeLimit != null) {
      __result['rangeLimit'] = rangeLimit;
    }
    if (lineFoldingOnly != null) {
      __result['lineFoldingOnly'] = lineFoldingOnly;
    }
    if (foldingRangeKind != null) {
      __result['foldingRangeKind'] = foldingRangeKind?.toJson();
    }
    if (foldingRange != null) {
      __result['foldingRange'] = foldingRange?.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('rangeLimit');
      try {
        final rangeLimit = obj['rangeLimit'];
        if (rangeLimit != null && !(rangeLimit is int)) {
          reporter.reportError('must be of type int');
          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('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('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();
      }
      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 &&
          rangeLimit == other.rangeLimit &&
          lineFoldingOnly == other.lineFoldingOnly &&
          foldingRangeKind == other.foldingRangeKind &&
          foldingRange == other.foldingRange &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        rangeLimit,
        lineFoldingOnly,
        foldingRangeKind,
        foldingRange,
      );

  @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({
    required this.textDocument,
    this.workDoneToken,
    this.partialResultToken,
  });
  static FoldingRangeParams fromJson(Map<String, Object?> json) {
    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)''')));
    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 FoldingRangeParams(
      textDocument: textDocument,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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 FoldingRangeParams');
      return false;
    }
  }

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

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

  @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.workDoneProgress,
    this.id,
  });
  static FoldingRangeRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final idJson = json['id'];
    final id = idJson as String?;
    return FoldingRangeRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
      id: id,
    );
  }

  /// 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<DocumentFilter>? 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 (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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 FoldingRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FoldingRangeRegistrationOptions &&
        other.runtimeType == FoldingRangeRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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({
    required this.tabSize,
    required this.insertSpaces,
    this.trimTrailingWhitespace,
    this.insertFinalNewline,
    this.trimFinalNewlines,
  });
  static FormattingOptions fromJson(Map<String, Object?> json) {
    final tabSizeJson = json['tabSize'];
    final tabSize = tabSizeJson as int;
    final insertSpacesJson = json['insertSpaces'];
    final insertSpaces = insertSpacesJson as bool;
    final trimTrailingWhitespaceJson = json['trimTrailingWhitespace'];
    final trimTrailingWhitespace = trimTrailingWhitespaceJson as bool?;
    final insertFinalNewlineJson = json['insertFinalNewline'];
    final insertFinalNewline = insertFinalNewlineJson as bool?;
    final trimFinalNewlinesJson = json['trimFinalNewlines'];
    final trimFinalNewlines = trimFinalNewlinesJson as bool?;
    return FormattingOptions(
      tabSize: tabSize,
      insertSpaces: insertSpaces,
      trimTrailingWhitespace: trimTrailingWhitespace,
      insertFinalNewline: insertFinalNewline,
      trimFinalNewlines: trimFinalNewlines,
    );
  }

  /// 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?>{};
    __result['tabSize'] = tabSize;
    __result['insertSpaces'] = insertSpaces;
    if (trimTrailingWhitespace != null) {
      __result['trimTrailingWhitespace'] = trimTrailingWhitespace;
    }
    if (insertFinalNewline != null) {
      __result['insertFinalNewline'] = insertFinalNewline;
    }
    if (trimFinalNewlines != null) {
      __result['trimFinalNewlines'] = trimFinalNewlines;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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('trimTrailingWhitespace');
      try {
        final trimTrailingWhitespace = obj['trimTrailingWhitespace'];
        if (trimTrailingWhitespace != null &&
            !(trimTrailingWhitespace is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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('trimFinalNewlines');
      try {
        final trimFinalNewlines = obj['trimFinalNewlines'];
        if (trimFinalNewlines != null && !(trimFinalNewlines 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 tabSize == other.tabSize &&
          insertSpaces == other.insertSpaces &&
          trimTrailingWhitespace == other.trimTrailingWhitespace &&
          insertFinalNewline == other.insertFinalNewline &&
          trimFinalNewlines == other.trimFinalNewlines &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        tabSize,
        insertSpaces,
        trimTrailingWhitespace,
        insertFinalNewline,
        trimFinalNewlines,
      );

  @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({
    this.kind = 'full',
    this.resultId,
    required this.items,
  }) {
    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 kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    return FullDocumentDiagnosticReport(
      kind: kind,
      resultId: resultId,
      items: items,
    );
  }

  /// 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['kind'] = kind;
    if (resultId != null) {
      __result['resultId'] = resultId;
    }
    __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('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('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();
      }
      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 kind == other.kind &&
          resultId == other.resultId &&
          listEqual(
              items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
          true;
    }
    return false;
  }

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

  @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 = contentsJson is String
        ? Either2<String, MarkupContent>.t1(contentsJson)
        : (MarkupContent.canParse(contentsJson, nullLspJsonReporter)
            ? Either2<String, MarkupContent>.t2(
                MarkupContent.fromJson(contentsJson as Map<String, Object?>))
            : (throw '''$contentsJson was not one of (String, MarkupContent)'''));
    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<String, MarkupContent> 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 (!((contents is String ||
            MarkupContent.canParse(contents, reporter)))) {
          reporter
              .reportError('must be of type Either2<String, MarkupContent>');
          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.dynamicRegistration,
    this.contentFormat,
  });
  static HoverClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final contentFormatJson = json['contentFormat'];
    final contentFormat = (contentFormatJson as List<Object?>?)
        ?.map((item) => MarkupKind.fromJson(item as String))
        .toList();
    return HoverClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      contentFormat: contentFormat,
    );
  }

  /// 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 (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (contentFormat != null) {
      __result['contentFormat'] =
          contentFormat?.map((item) => item.toJson()).toList();
    }
    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('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();
      }
      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 dynamicRegistration == other.dynamicRegistration &&
          listEqual(contentFormat, other.contentFormat,
              (MarkupKind a, MarkupKind b) => a == b) &&
          true;
    }
    return false;
  }

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

  @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.textDocument,
    required this.position,
    this.workDoneToken,
  });
  static HoverParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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(
      textDocument: textDocument,
      position: position,
      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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    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();
      }
      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('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 textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

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

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

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

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

  final int character;
  final int line;

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

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

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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({
    required this.textDocument,
    required this.position,
    this.workDoneToken,
    this.partialResultToken,
  });
  static ImplementationParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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)''')));
    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 ImplementationParams(
      textDocument: textDocument,
      position: position,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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 ImplementationParams');
      return false;
    }
  }

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

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

  @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.workDoneProgress,
    this.id,
  });
  static ImplementationRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final idJson = json['id'];
    final id = idJson as String?;
    return ImplementationRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
      id: id,
    );
  }

  /// 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<DocumentFilter>? 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 (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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 ImplementationRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ImplementationRegistrationOptions &&
        other.runtimeType == ImplementationRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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({
    this.processId,
    this.clientInfo,
    this.locale,
    this.rootPath,
    this.rootUri,
    this.initializationOptions,
    required this.capabilities,
    this.trace,
    this.workspaceFolders,
    this.workDoneToken,
  });
  static InitializeParams fromJson(Map<String, Object?> json) {
    final processIdJson = json['processId'];
    final processId = processIdJson as int?;
    final clientInfoJson = json['clientInfo'];
    final clientInfo = clientInfoJson != null
        ? InitializeParamsClientInfo.fromJson(
            clientInfoJson as Map<String, Object?>)
        : null;
    final localeJson = json['locale'];
    final locale = localeJson as String?;
    final rootPathJson = json['rootPath'];
    final rootPath = rootPathJson as String?;
    final rootUriJson = json['rootUri'];
    final rootUri = rootUriJson as String?;
    final initializationOptionsJson = json['initializationOptions'];
    final initializationOptions = initializationOptionsJson;
    final capabilitiesJson = json['capabilities'];
    final capabilities =
        ClientCapabilities.fromJson(capabilitiesJson as Map<String, Object?>);
    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 workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = (workspaceFoldersJson as List<Object?>?)
        ?.map((item) => WorkspaceFolder.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 InitializeParams(
      processId: processId,
      clientInfo: clientInfo,
      locale: locale,
      rootPath: rootPath,
      rootUri: rootUri,
      initializationOptions: initializationOptions,
      capabilities: capabilities,
      trace: trace,
      workspaceFolders: workspaceFolders,
      workDoneToken: workDoneToken,
    );
  }

  /// 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['processId'] = processId;
    if (clientInfo != null) {
      __result['clientInfo'] = clientInfo?.toJson();
    }
    if (locale != null) {
      __result['locale'] = locale;
    }
    if (rootPath != null) {
      __result['rootPath'] = rootPath;
    }
    __result['rootUri'] = rootUri;
    if (initializationOptions != null) {
      __result['initializationOptions'] = initializationOptions;
    }
    __result['capabilities'] = capabilities.toJson();
    if (trace != null) {
      __result['trace'] = trace;
    }
    if (workspaceFolders != null) {
      __result['workspaceFolders'] =
          workspaceFolders?.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('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('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('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('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('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('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();
      }
      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 InitializeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InitializeParams && other.runtimeType == InitializeParams) {
      return processId == other.processId &&
          clientInfo == other.clientInfo &&
          locale == other.locale &&
          rootPath == other.rootPath &&
          rootUri == other.rootUri &&
          initializationOptions == other.initializationOptions &&
          capabilities == other.capabilities &&
          trace == other.trace &&
          listEqual(workspaceFolders, other.workspaceFolders,
              (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        processId,
        clientInfo,
        locale,
        rootPath,
        rootUri,
        initializationOptions,
        capabilities,
        trace,
        lspHashCode(workspaceFolders),
        workDoneToken,
      );

  @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({
    required this.position,
    required this.label,
    this.kind,
    this.textEdits,
    this.tooltip,
    this.paddingLeft,
    this.paddingRight,
    this.data,
  });
  static InlayHint fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final labelJson = json['label'];
    final label = labelJson is String
        ? Either2<String, List<InlayHintLabelPart>>.t1(labelJson)
        : ((labelJson is List<Object?> &&
                (labelJson.every((item) =>
                    InlayHintLabelPart.canParse(item, nullLspJsonReporter))))
            ? Either2<String, List<InlayHintLabelPart>>.t2((labelJson)
                .map((item) =>
                    InlayHintLabelPart.fromJson(item as Map<String, Object?>))
                .toList())
            : (throw '''$labelJson was not one of (String, List<InlayHintLabelPart>)'''));
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? InlayHintKind.fromJson(kindJson as int) : null;
    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
        : (tooltipJson is String
            ? Either2<String, MarkupContent>.t1(tooltipJson)
            : (MarkupContent.canParse(tooltipJson, nullLspJsonReporter)
                ? Either2<String, MarkupContent>.t2(
                    MarkupContent.fromJson(tooltipJson as Map<String, Object?>))
                : (throw '''$tooltipJson was not one of (String, MarkupContent)''')));
    final paddingLeftJson = json['paddingLeft'];
    final paddingLeft = paddingLeftJson as bool?;
    final paddingRightJson = json['paddingRight'];
    final paddingRight = paddingRightJson as bool?;
    final dataJson = json['data'];
    final data = dataJson;
    return InlayHint(
      position: position,
      label: label,
      kind: kind,
      textEdits: textEdits,
      tooltip: tooltip,
      paddingLeft: paddingLeft,
      paddingRight: paddingRight,
      data: data,
    );
  }

  /// 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<String, List<InlayHintLabelPart>> 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<String, MarkupContent>? tooltip;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['position'] = position.toJson();
    __result['label'] = label;
    if (kind != null) {
      __result['kind'] = kind?.toJson();
    }
    if (textEdits != null) {
      __result['textEdits'] = textEdits?.map((item) => item.toJson()).toList();
    }
    if (tooltip != null) {
      __result['tooltip'] = tooltip;
    }
    if (paddingLeft != null) {
      __result['paddingLeft'] = paddingLeft;
    }
    if (paddingRight != null) {
      __result['paddingRight'] = paddingRight;
    }
    if (data != null) {
      __result['data'] = data;
    }
    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('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 ||
            (label is List<Object?> &&
                (label.every((item) =>
                    InlayHintLabelPart.canParse(item, reporter))))))) {
          reporter.reportError(
              'must be of type Either2<String, List<InlayHintLabelPart>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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('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 &&
            !((tooltip is String ||
                MarkupContent.canParse(tooltip, reporter)))) {
          reporter
              .reportError('must be of type Either2<String, MarkupContent>');
          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();
      }
      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 position == other.position &&
          label == other.label &&
          kind == other.kind &&
          listEqual(
              textEdits, other.textEdits, (TextEdit a, TextEdit b) => a == b) &&
          tooltip == other.tooltip &&
          paddingLeft == other.paddingLeft &&
          paddingRight == other.paddingRight &&
          data == other.data &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        position,
        label,
        kind,
        lspHashCode(textEdits),
        tooltip,
        paddingLeft,
        paddingRight,
        data,
      );

  @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({
    required this.value,
    this.tooltip,
    this.location,
    this.command,
  });
  static InlayHintLabelPart fromJson(Map<String, Object?> json) {
    final valueJson = json['value'];
    final value = valueJson as String;
    final tooltipJson = json['tooltip'];
    final tooltip = tooltipJson == null
        ? null
        : (tooltipJson is String
            ? Either2<String, MarkupContent>.t1(tooltipJson)
            : (MarkupContent.canParse(tooltipJson, nullLspJsonReporter)
                ? Either2<String, MarkupContent>.t2(
                    MarkupContent.fromJson(tooltipJson as Map<String, Object?>))
                : (throw '''$tooltipJson was not one of (String, MarkupContent)''')));
    final locationJson = json['location'];
    final location = locationJson != null
        ? Location.fromJson(locationJson as Map<String, Object?>)
        : null;
    final commandJson = json['command'];
    final command = commandJson != null
        ? Command.fromJson(commandJson as Map<String, Object?>)
        : null;
    return InlayHintLabelPart(
      value: value,
      tooltip: tooltip,
      location: location,
      command: command,
    );
  }

  /// 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<String, MarkupContent>? tooltip;

  /// The value of this label part.
  final String value;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['value'] = value;
    if (tooltip != null) {
      __result['tooltip'] = tooltip;
    }
    if (location != null) {
      __result['location'] = location?.toJson();
    }
    if (command != null) {
      __result['command'] = command?.toJson();
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final value = obj['value'];
        if (value == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(value 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 ||
                MarkupContent.canParse(tooltip, reporter)))) {
          reporter
              .reportError('must be of type Either2<String, MarkupContent>');
          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('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();
      }
      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 value == other.value &&
          tooltip == other.tooltip &&
          location == other.location &&
          command == other.command &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        value,
        tooltip,
        location,
        command,
      );

  @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.textDocument,
    required this.range,
    this.workDoneToken,
  });
  static InlayHintParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson 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(
      textDocument: textDocument,
      range: range,
      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['textDocument'] = textDocument.toJson();
    __result['range'] = range.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    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();
      }
      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('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 textDocument == other.textDocument &&
          range == other.range &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        textDocument,
        range,
        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.resolveProvider,
    this.workDoneProgress,
    this.documentSelector,
    this.id,
  });
  static InlayHintRegistrationOptions fromJson(Map<String, Object?> json) {
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    return InlayHintRegistrationOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
      documentSelector: documentSelector,
      id: id,
    );
  }

  /// 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<DocumentFilter>? 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?>{};
    if (resolveProvider != null) {
      __result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    __result['documentSelector'] = documentSelector;
    if (id != null) {
      __result['id'] = id;
    }
    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();
      }
      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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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();
      }
      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 resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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({
    required this.range,
    this.expression,
  });
  static InlineValueEvaluatableExpression fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final expressionJson = json['expression'];
    final expression = expressionJson as String?;
    return InlineValueEvaluatableExpression(
      range: range,
      expression: expression,
    );
  }

  /// 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?>{};
    __result['range'] = range.toJson();
    if (expression != null) {
      __result['expression'] = expression;
    }
    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('expression');
      try {
        final expression = obj['expression'];
        if (expression != null && !(expression is String)) {
          reporter.reportError('must be of type String');
          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 range == other.range && expression == other.expression && true;
    }
    return false;
  }

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

  @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.textDocument,
    required this.range,
    required this.context,
    this.workDoneToken,
  });
  static InlineValueParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final contextJson = json['context'];
    final context =
        InlineValueContext.fromJson(contextJson 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(
      textDocument: textDocument,
      range: range,
      context: context,
      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['textDocument'] = textDocument.toJson();
    __result['range'] = range.toJson();
    __result['context'] = context.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    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();
      }
      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('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('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 textDocument == other.textDocument &&
          range == other.range &&
          context == other.context &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        textDocument,
        range,
        context,
        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.workDoneProgress,
    this.documentSelector,
    this.id,
  });
  static InlineValueRegistrationOptions fromJson(Map<String, Object?> json) {
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    return InlineValueRegistrationOptions(
      workDoneProgress: workDoneProgress,
      documentSelector: documentSelector,
      id: id,
    );
  }

  /// 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<DocumentFilter>? 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?>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    __result['documentSelector'] = documentSelector;
    if (id != null) {
      __result['id'] = id;
    }
    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();
      }
      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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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();
      }
      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 workDoneProgress == other.workDoneProgress &&
          listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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.range,
    this.variableName,
    required this.caseSensitiveLookup,
  });
  static InlineValueVariableLookup fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final variableNameJson = json['variableName'];
    final variableName = variableNameJson as String?;
    final caseSensitiveLookupJson = json['caseSensitiveLookup'];
    final caseSensitiveLookup = caseSensitiveLookupJson as bool;
    return InlineValueVariableLookup(
      range: range,
      variableName: variableName,
      caseSensitiveLookup: caseSensitiveLookup,
    );
  }

  /// 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['range'] = range.toJson();
    if (variableName != null) {
      __result['variableName'] = variableName;
    }
    __result['caseSensitiveLookup'] = caseSensitiveLookup;
    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('variableName');
      try {
        final variableName = obj['variableName'];
        if (variableName != null && !(variableName is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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 range == other.range &&
          variableName == other.variableName &&
          caseSensitiveLookup == other.caseSensitiveLookup &&
          true;
    }
    return false;
  }

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

  @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.newText,
    required this.insert,
    required this.replace,
  });
  static InsertReplaceEdit fromJson(Map<String, Object?> json) {
    final newTextJson = json['newText'];
    final newText = newTextJson as String;
    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 InsertReplaceEdit(
      newText: newText,
      insert: insert,
      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['newText'] = newText;
    __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('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('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 InsertReplaceEdit');
      return false;
    }
  }

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

  @override
  int get hashCode => Object.hash(
        newText,
        insert,
        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.textDocument,
    required this.position,
    this.workDoneToken,
  });
  static LinkedEditingRangeParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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(
      textDocument: textDocument,
      position: position,
      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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    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();
      }
      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('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 textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        textDocument,
        position,
        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.workDoneProgress,
    this.id,
  });
  static LinkedEditingRangeRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final idJson = json['id'];
    final id = idJson as String?;
    return LinkedEditingRangeRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
      id: id,
    );
  }

  /// 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<DocumentFilter>? 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 (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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 LinkedEditingRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is LinkedEditingRangeRegistrationOptions &&
        other.runtimeType == LinkedEditingRangeRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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.uri,
    required this.range,
  });
  static Location fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return Location(
      uri: uri,
      range: range,
    );
  }

  final Range range;
  final String uri;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['uri'] = uri;
    __result['range'] = range.toJson();
    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('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 Location');
      return false;
    }
  }

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

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

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

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

  LocationLink({
    this.originSelectionRange,
    required this.targetUri,
    required this.targetRange,
    required this.targetSelectionRange,
  });
  static LocationLink fromJson(Map<String, Object?> json) {
    final originSelectionRangeJson = json['originSelectionRange'];
    final originSelectionRange = originSelectionRangeJson != null
        ? Range.fromJson(originSelectionRangeJson as Map<String, Object?>)
        : null;
    final targetUriJson = json['targetUri'];
    final targetUri = targetUriJson as String;
    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?>);
    return LocationLink(
      originSelectionRange: originSelectionRange,
      targetUri: targetUri,
      targetRange: targetRange,
      targetSelectionRange: targetSelectionRange,
    );
  }

  /// 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['targetUri'] = targetUri;
    __result['targetRange'] = targetRange.toJson();
    __result['targetSelectionRange'] = targetSelectionRange.toJson();
    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('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();
      }
      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();
      }
      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 &&
          targetUri == other.targetUri &&
          targetRange == other.targetRange &&
          targetSelectionRange == other.targetSelectionRange &&
          true;
    }
    return false;
  }

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

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

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

  LogMessageParams({
    required this.type,
    required this.message,
  });
  static LogMessageParams fromJson(Map<String, Object?> json) {
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    final messageJson = json['message'];
    final message = messageJson as String;
    return LogMessageParams(
      type: type,
      message: message,
    );
  }

  /// The actual message
  final String message;

  /// The message type.
  final MessageType type;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['type'] = type.toJson();
    __result['message'] = message;
    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 (!(MessageType.canParse(type, reporter))) {
          reporter.reportError('must be of type MessageType');
          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 LogMessageParams');
      return false;
    }
  }

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

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

  @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({
    required this.parser,
    this.version,
    this.allowedTags,
  });
  static MarkdownClientCapabilities fromJson(Map<String, Object?> json) {
    final parserJson = json['parser'];
    final parser = parserJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    final allowedTagsJson = json['allowedTags'];
    final allowedTags = (allowedTagsJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    return MarkdownClientCapabilities(
      parser: parser,
      version: version,
      allowedTags: allowedTags,
    );
  }

  /// 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?>{};
    __result['parser'] = parser;
    if (version != null) {
      __result['version'] = version;
    }
    if (allowedTags != null) {
      __result['allowedTags'] = allowedTags;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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();
      }
      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 parser == other.parser &&
          version == other.version &&
          listEqual(
              allowedTags, other.allowedTags, (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        parser,
        version,
        lspHashCode(allowedTags),
      );

  @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({
    required this.jsonrpc,
    this.clientRequestTime,
  });
  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 jsonrpcJson = json['jsonrpc'];
    final jsonrpc = jsonrpcJson as String;
    final clientRequestTimeJson = json['clientRequestTime'];
    final clientRequestTime = clientRequestTimeJson as int?;
    return Message(
      jsonrpc: jsonrpc,
      clientRequestTime: clientRequestTime,
    );
  }

  final int? clientRequestTime;
  final String jsonrpc;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('clientRequestTime');
      try {
        final clientRequestTime = obj['clientRequestTime'];
        if (clientRequestTime != null && !(clientRequestTime is int)) {
          reporter.reportError('must be of type int');
          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 jsonrpc == other.jsonrpc &&
          clientRequestTime == other.clientRequestTime &&
          true;
    }
    return false;
  }

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

  @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.scheme,
    required this.identifier,
    required this.unique,
    this.kind,
  });
  static Moniker fromJson(Map<String, Object?> json) {
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String;
    final uniqueJson = json['unique'];
    final unique = UniquenessLevel.fromJson(uniqueJson as String);
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? MonikerKind.fromJson(kindJson as String) : null;
    return Moniker(
      scheme: scheme,
      identifier: identifier,
      unique: unique,
      kind: kind,
    );
  }

  /// 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['scheme'] = scheme;
    __result['identifier'] = identifier;
    __result['unique'] = unique.toJson();
    if (kind != null) {
      __result['kind'] = kind?.toJson();
    }
    return __result;
  }

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

  @override
  int get hashCode => Object.hash(
        scheme,
        identifier,
        unique,
        kind,
      );

  @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({
    required this.textDocument,
    required this.position,
    this.workDoneToken,
    this.partialResultToken,
  });
  static MonikerParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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)''')));
    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 MonikerParams(
      textDocument: textDocument,
      position: position,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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 MonikerParams');
      return false;
    }
  }

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

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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.kind,
    required this.document,
    this.metadata,
    this.executionSummary,
  });
  static NotebookCell fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = NotebookCellKind.fromJson(kindJson as int);
    final documentJson = json['document'];
    final document = documentJson as String;
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    final executionSummaryJson = json['executionSummary'];
    final executionSummary = executionSummaryJson != null
        ? ExecutionSummary.fromJson(
            executionSummaryJson as Map<String, Object?>)
        : null;
    return NotebookCell(
      kind: kind,
      document: document,
      metadata: metadata,
      executionSummary: executionSummary,
    );
  }

  /// 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['kind'] = kind.toJson();
    __result['document'] = document;
    if (metadata != null) {
      __result['metadata'] = metadata;
    }
    if (executionSummary != null) {
      __result['executionSummary'] = executionSummary?.toJson();
    }
    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 (!(NotebookCellKind.canParse(kind, reporter))) {
          reporter.reportError('must be of type NotebookCellKind');
          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 (!(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();
      }
      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 kind == other.kind &&
          document == other.document &&
          metadata == other.metadata &&
          executionSummary == other.executionSummary &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        document,
        metadata,
        executionSummary,
      );

  @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({
    required this.start,
    required this.deleteCount,
    this.cells,
  });
  static NotebookCellArrayChange fromJson(Map<String, Object?> json) {
    final startJson = json['start'];
    final start = startJson as int;
    final deleteCountJson = json['deleteCount'];
    final deleteCount = deleteCountJson as int;
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>?)
        ?.map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    return NotebookCellArrayChange(
      start: start,
      deleteCount: deleteCount,
      cells: cells,
    );
  }

  /// 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?>{};
    __result['start'] = start;
    __result['deleteCount'] = deleteCount;
    if (cells != null) {
      __result['cells'] = cells?.map((item) => item.toJson()).toList();
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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('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();
      }
      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 start == other.start &&
          deleteCount == other.deleteCount &&
          listEqual(
              cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        start,
        deleteCount,
        lspHashCode(cells),
      );

  @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({
    required this.notebook,
    this.language,
  });
  static NotebookCellTextDocumentFilter fromJson(Map<String, Object?> json) {
    final notebookJson = json['notebook'];
    final notebook = notebookJson is String
        ? Either2<String, Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>>.t1(
            notebookJson)
        : ((NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter) ||
                NotebookDocumentFilter2.canParse(
                    notebookJson, nullLspJsonReporter) ||
                NotebookDocumentFilter3.canParse(
                    notebookJson, nullLspJsonReporter))
            ? Either2<String, Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>>.t2(
                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)'''))))
            : (throw '''$notebookJson was not one of (String, Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>)'''));
    final languageJson = json['language'];
    final language = languageJson as String?;
    return NotebookCellTextDocumentFilter(
      notebook: notebook,
      language: language,
    );
  }

  /// 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<
      String,
      Either3<NotebookDocumentFilter1, NotebookDocumentFilter2,
          NotebookDocumentFilter3>> notebook;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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 (!((notebook is String ||
            (NotebookDocumentFilter1.canParse(notebook, reporter) ||
                NotebookDocumentFilter2.canParse(notebook, reporter) ||
                NotebookDocumentFilter3.canParse(notebook, reporter))))) {
          reporter.reportError(
              'must be of type Either2<String, Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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 notebook == other.notebook && language == other.language && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        notebook,
        language,
      );

  @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.uri,
    required this.notebookType,
    required this.version,
    this.metadata,
    required this.cells,
  });
  static NotebookDocument fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>)
        .map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    return NotebookDocument(
      uri: uri,
      notebookType: notebookType,
      version: version,
      metadata: metadata,
      cells: cells,
    );
  }

  /// 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['uri'] = uri;
    __result['notebookType'] = notebookType;
    __result['version'] = version;
    if (metadata != null) {
      __result['metadata'] = metadata;
    }
    __result['cells'] = cells.map((item) => item.toJson()).toList();
    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('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('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();
      }
      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();
      }
      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 uri == other.uri &&
          notebookType == other.notebookType &&
          version == other.version &&
          metadata == other.metadata &&
          listEqual(
              cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        notebookType,
        version,
        metadata,
        lspHashCode(cells),
      );

  @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.metadata,
    this.cells,
  });
  static NotebookDocumentChangeEvent fromJson(Map<String, Object?> json) {
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    final cellsJson = json['cells'];
    final cells = cellsJson != null
        ? NotebookDocumentChangeEventCells.fromJson(
            cellsJson as Map<String, Object?>)
        : null;
    return NotebookDocumentChangeEvent(
      metadata: metadata,
      cells: cells,
    );
  }

  /// Changes to cells
  final NotebookDocumentChangeEventCells? cells;

  /// The changed meta data if any.
  final Object? metadata;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (metadata != null) {
      __result['metadata'] = metadata;
    }
    if (cells != null) {
      __result['cells'] = cells?.toJson();
    }
    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 metadata == other.metadata && cells == other.cells && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        metadata,
        cells,
      );

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

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

  NotebookDocumentChangeEventCells({
    this.structure,
    this.data,
    this.textContent,
  });
  static NotebookDocumentChangeEventCells fromJson(Map<String, Object?> json) {
    final structureJson = json['structure'];
    final structure = structureJson != null
        ? NotebookDocumentChangeEventStructure.fromJson(
            structureJson as Map<String, Object?>)
        : null;
    final dataJson = json['data'];
    final data = (dataJson as List<Object?>?)
        ?.map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final textContentJson = json['textContent'];
    final textContent = (textContentJson as List<Object?>?)
        ?.map((item) => NotebookDocumentChangeEventTextContent.fromJson(
            item as Map<String, Object?>))
        .toList();
    return NotebookDocumentChangeEventCells(
      structure: structure,
      data: data,
      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 (structure != null) {
      __result['structure'] = structure?.toJson();
    }
    if (data != null) {
      __result['data'] = data?.map((item) => item.toJson()).toList();
    }
    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('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('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('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 structure == other.structure &&
          listEqual(
              data, other.data, (NotebookCell a, NotebookCell b) => a == b) &&
          listEqual(
              textContent,
              other.textContent,
              (NotebookDocumentChangeEventTextContent a,
                      NotebookDocumentChangeEventTextContent b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        structure,
        lspHashCode(data),
        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.didOpen,
    this.didClose,
  });
  static NotebookDocumentChangeEventStructure fromJson(
      Map<String, Object?> json) {
    final arrayJson = json['array'];
    final array =
        NotebookCellArrayChange.fromJson(arrayJson as Map<String, Object?>);
    final didOpenJson = json['didOpen'];
    final didOpen = (didOpenJson as List<Object?>?)
        ?.map((item) => TextDocumentItem.fromJson(item as Map<String, Object?>))
        .toList();
    final didCloseJson = json['didClose'];
    final didClose = (didCloseJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentIdentifier.fromJson(item as Map<String, Object?>))
        .toList();
    return NotebookDocumentChangeEventStructure(
      array: array,
      didOpen: didOpen,
      didClose: didClose,
    );
  }

  /// 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 (didOpen != null) {
      __result['didOpen'] = didOpen?.map((item) => item.toJson()).toList();
    }
    if (didClose != null) {
      __result['didClose'] = didClose?.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('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();
      }
      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();
      }
      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(didOpen, other.didOpen,
              (TextDocumentItem a, TextDocumentItem b) => a == b) &&
          listEqual(didClose, other.didClose,
              (TextDocumentIdentifier a, TextDocumentIdentifier b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        array,
        lspHashCode(didOpen),
        lspHashCode(didClose),
      );

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

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

  NotebookDocumentChangeEventTextContent({
    required this.document,
    required this.changes,
  });
  static NotebookDocumentChangeEventTextContent fromJson(
      Map<String, Object?> json) {
    final documentJson = json['document'];
    final document = VersionedTextDocumentIdentifier.fromJson(
        documentJson as Map<String, Object?>);
    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();
    return NotebookDocumentChangeEventTextContent(
      document: document,
      changes: changes,
    );
  }

  final List<
      Either2<TextDocumentContentChangeEvent1,
          TextDocumentContentChangeEvent2>> changes;
  final VersionedTextDocumentIdentifier document;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['document'] = document.toJson();
    __result['changes'] = changes;
    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 (!(VersionedTextDocumentIdentifier.canParse(document, reporter))) {
          reporter
              .reportError('must be of type VersionedTextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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 document == other.document &&
          listEqual(
              changes,
              other.changes,
              (Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          a,
                      Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        document,
        lspHashCode(changes),
      );

  @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.scheme,
    this.pattern,
  });
  static NotebookDocumentFilter1 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    return NotebookDocumentFilter1(
      notebookType: notebookType,
      scheme: scheme,
      pattern: pattern,
    );
  }

  /// 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 (scheme != null) {
      __result['scheme'] = scheme;
    }
    if (pattern != null) {
      __result['pattern'] = pattern;
    }
    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('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && !(scheme 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();
      }
      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 &&
          scheme == other.scheme &&
          pattern == other.pattern &&
          true;
    }
    return false;
  }

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

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

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

  NotebookDocumentFilter2({
    this.notebookType,
    required this.scheme,
    this.pattern,
  });
  static NotebookDocumentFilter2 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    return NotebookDocumentFilter2(
      notebookType: notebookType,
      scheme: scheme,
      pattern: pattern,
    );
  }

  /// 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['scheme'] = scheme;
    if (pattern != null) {
      __result['pattern'] = pattern;
    }
    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('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('pattern');
      try {
        final pattern = obj['pattern'];
        if (pattern != null && !(pattern 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 &&
          scheme == other.scheme &&
          pattern == other.pattern &&
          true;
    }
    return false;
  }

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

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

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

  NotebookDocumentFilter3({
    this.notebookType,
    this.scheme,
    required this.pattern,
  });
  static NotebookDocumentFilter3 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String;
    return NotebookDocumentFilter3(
      notebookType: notebookType,
      scheme: scheme,
      pattern: pattern,
    );
  }

  /// 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 (scheme != null) {
      __result['scheme'] = scheme;
    }
    __result['pattern'] = pattern;
    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('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && !(scheme 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();
      }
      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 &&
          scheme == other.scheme &&
          pattern == other.pattern &&
          true;
    }
    return false;
  }

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

  @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({
    this.notebookDocument,
    required this.cells,
  });
  static NotebookDocumentSyncOptionsNotebookSelector fromJson(
      Map<String, Object?> json) {
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument = notebookDocumentJson == null
        ? null
        : (notebookDocumentJson is String
            ? Either2<String, Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>>.t1(
                notebookDocumentJson)
            : ((NotebookDocumentFilter1.canParse(notebookDocumentJson, nullLspJsonReporter) ||
                    NotebookDocumentFilter2.canParse(
                        notebookDocumentJson, nullLspJsonReporter) ||
                    NotebookDocumentFilter3.canParse(
                        notebookDocumentJson, nullLspJsonReporter))
                ? Either2<String, Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>>.t2(
                    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)'''))))
                : (throw '''$notebookDocumentJson was not one of (String, Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>)''')));
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>)
        .map((item) => NotebookDocumentSyncOptionsCells.fromJson(
            item as Map<String, Object?>))
        .toList();
    return NotebookDocumentSyncOptionsNotebookSelector(
      notebookDocument: notebookDocument,
      cells: cells,
    );
  }

  /// 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<
      String,
      Either3<NotebookDocumentFilter1, NotebookDocumentFilter2,
          NotebookDocumentFilter3>>? notebookDocument;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    if (notebookDocument != null) {
      __result['notebookDocument'] = notebookDocument;
    }
    __result['cells'] = cells.map((item) => item.toJson()).toList();
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookDocument');
      try {
        final notebookDocument = obj['notebookDocument'];
        if (notebookDocument != null &&
            !((notebookDocument is String ||
                (NotebookDocumentFilter1.canParse(notebookDocument, reporter) ||
                    NotebookDocumentFilter2.canParse(
                        notebookDocument, reporter) ||
                    NotebookDocumentFilter3.canParse(
                        notebookDocument, reporter))))) {
          reporter.reportError(
              'must be of type Either2<String, Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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 notebookDocument == other.notebookDocument &&
          listEqual(
              cells,
              other.cells,
              (NotebookDocumentSyncOptionsCells a,
                      NotebookDocumentSyncOptionsCells b) =>
                  a == b) &&
          true;
    }
    return false;
  }

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

  @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({
    required this.notebookSelector,
    this.save,
    this.id,
  });
  static NotebookDocumentSyncRegistrationOptions fromJson(
      Map<String, Object?> 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?;
    final idJson = json['id'];
    final id = idJson as String?;
    return NotebookDocumentSyncRegistrationOptions(
      notebookSelector: notebookSelector,
      save: save,
      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;

  /// 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;
    }
    if (id != null) {
      __result['id'] = id;
    }
    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();
      }
      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 NotebookDocumentSyncRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncRegistrationOptions &&
        other.runtimeType == NotebookDocumentSyncRegistrationOptions) {
      return listEqual(
              notebookSelector,
              other.notebookSelector,
              (NotebookDocumentSyncOptionsNotebookSelector a,
                      NotebookDocumentSyncOptionsNotebookSelector b) =>
                  a == b) &&
          save == other.save &&
          id == other.id &&
          true;
    }
    return false;
  }

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

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

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

  NotificationMessage({
    required this.method,
    this.params,
    required this.jsonrpc,
    this.clientRequestTime,
  });
  static NotificationMessage fromJson(Map<String, Object?> json) {
    final methodJson = json['method'];
    final method = Method.fromJson(methodJson as String);
    final paramsJson = json['params'];
    final params = paramsJson;
    final jsonrpcJson = json['jsonrpc'];
    final jsonrpc = jsonrpcJson as String;
    final clientRequestTimeJson = json['clientRequestTime'];
    final clientRequestTime = clientRequestTimeJson as int?;
    return NotificationMessage(
      method: method,
      params: params,
      jsonrpc: jsonrpc,
      clientRequestTime: clientRequestTime,
    );
  }

  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?>{};
    __result['method'] = method.toJson();
    if (params != null) {
      __result['params'] = params;
    }
    __result['jsonrpc'] = jsonrpc;
    if (clientRequestTime != null) {
      __result['clientRequestTime'] = clientRequestTime;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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('clientRequestTime');
      try {
        final clientRequestTime = obj['clientRequestTime'];
        if (clientRequestTime != null && !(clientRequestTime is int)) {
          reporter.reportError('must be of type int');
          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 method == other.method &&
          params == other.params &&
          jsonrpc == other.jsonrpc &&
          clientRequestTime == other.clientRequestTime &&
          true;
    }
    return false;
  }

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

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

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

  OptionalVersionedTextDocumentIdentifier({
    this.version,
    required this.uri,
  });
  static OptionalVersionedTextDocumentIdentifier fromJson(
      Map<String, Object?> json) {
    final versionJson = json['version'];
    final version = versionJson as int?;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return OptionalVersionedTextDocumentIdentifier(
      version: version,
      uri: uri,
    );
  }

  /// 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['version'] = version;
    __result['uri'] = uri;
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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 OptionalVersionedTextDocumentIdentifier');
      return false;
    }
  }

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

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

  @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({
    required this.label,
    this.documentation,
  });
  static ParameterInformation fromJson(Map<String, Object?> json) {
    final labelJson = json['label'];
    final label = labelJson as String;
    final documentationJson = json['documentation'];
    final documentation = documentationJson == null
        ? null
        : (documentationJson is String
            ? Either2<String, MarkupContent>.t1(documentationJson)
            : (MarkupContent.canParse(documentationJson, nullLspJsonReporter)
                ? Either2<String, MarkupContent>.t2(MarkupContent.fromJson(
                    documentationJson as Map<String, Object?>))
                : (throw '''$documentationJson was not one of (String, MarkupContent)''')));
    return ParameterInformation(
      label: label,
      documentation: documentation,
    );
  }

  /// The human-readable doc-comment of this parameter. Will be shown in the UI
  /// but can be omitted.
  final Either2<String, MarkupContent>? 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?>{};
    __result['label'] = label;
    if (documentation != null) {
      __result['documentation'] = documentation;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('documentation');
      try {
        final documentation = obj['documentation'];
        if (documentation != null &&
            !((documentation is String ||
                MarkupContent.canParse(documentation, reporter)))) {
          reporter
              .reportError('must be of type Either2<String, MarkupContent>');
          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 label == other.label &&
          documentation == other.documentation &&
          true;
    }
    return false;
  }

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

  @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.line,
    required this.character,
  });
  static Position fromJson(Map<String, Object?> json) {
    final lineJson = json['line'];
    final line = lineJson as int;
    final characterJson = json['character'];
    final character = characterJson as int;
    return Position(
      line: line,
      character: character,
    );
  }

  /// 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['line'] = line;
    __result['character'] = character;
    return __result;
  }

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

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

  @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.textDocument,
    required this.position,
  });
  static PrepareRenameParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    return PrepareRenameParams(
      textDocument: textDocument,
      position: position,
    );
  }

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['textDocument'] = textDocument.toJson();
    __result['position'] = position.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();
      }
      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();
      }
      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 textDocument == other.textDocument &&
          position == other.position &&
          true;
    }
    return false;
  }

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

  @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.relatedInformation,
    this.tagSupport,
    this.versionSupport,
    this.codeDescriptionSupport,
    this.dataSupport,
  });
  static PublishDiagnosticsClientCapabilities fromJson(
      Map<String, Object?> json) {
    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?;
    final codeDescriptionSupportJson = json['codeDescriptionSupport'];
    final codeDescriptionSupport = codeDescriptionSupportJson as bool?;
    final dataSupportJson = json['dataSupport'];
    final dataSupport = dataSupportJson as bool?;
    return PublishDiagnosticsClientCapabilities(
      relatedInformation: relatedInformation,
      tagSupport: tagSupport,
      versionSupport: versionSupport,
      codeDescriptionSupport: codeDescriptionSupport,
      dataSupport: dataSupport,
    );
  }

  /// 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 (relatedInformation != null) {
      __result['relatedInformation'] = relatedInformation;
    }
    if (tagSupport != null) {
      __result['tagSupport'] = tagSupport?.toJson();
    }
    if (versionSupport != null) {
      __result['versionSupport'] = versionSupport;
    }
    if (codeDescriptionSupport != null) {
      __result['codeDescriptionSupport'] = codeDescriptionSupport;
    }
    if (dataSupport != null) {
      __result['dataSupport'] = dataSupport;
    }
    return __result;
  }

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

  @override
  int get hashCode => Object.hash(
        relatedInformation,
        tagSupport,
        versionSupport,
        codeDescriptionSupport,
        dataSupport,
      );

  @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.uri,
    this.version,
    required this.diagnostics,
  });
  static PublishDiagnosticsParams fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = (diagnosticsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    return PublishDiagnosticsParams(
      uri: uri,
      version: version,
      diagnostics: diagnostics,
    );
  }

  /// 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['uri'] = uri;
    if (version != null) {
      __result['version'] = version;
    }
    __result['diagnostics'] = diagnostics.map((item) => item.toJson()).toList();
    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 {
        final version = obj['version'];
        if (version != null && !(version is int)) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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 uri == other.uri &&
          version == other.version &&
          listEqual(diagnostics, other.diagnostics,
              (Diagnostic a, Diagnostic b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

  Range({
    required this.start,
    required this.end,
  });
  static Range fromJson(Map<String, Object?> json) {
    final startJson = json['start'];
    final start = Position.fromJson(startJson as Map<String, Object?>);
    final endJson = json['end'];
    final end = Position.fromJson(endJson as Map<String, Object?>);
    return Range(
      start: start,
      end: end,
    );
  }

  /// 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['start'] = start.toJson();
    __result['end'] = end.toJson();
    return __result;
  }

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

  @override
  int get hashCode => Object.hash(
        start,
        end,
      );

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

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

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

  final String placeholder;
  final Range range;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['range'] = range.toJson();
    __result['placeholder'] = placeholder;
    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('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();
      }
      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 range == other.range && placeholder == other.placeholder && true;
    }
    return false;
  }

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

  @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,
    required this.textDocument,
    required this.position,
    this.workDoneToken,
    this.partialResultToken,
  });
  static ReferenceParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context =
        ReferenceContext.fromJson(contextJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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)''')));
    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 ReferenceParams(
      context: context,
      textDocument: textDocument,
      position: position,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  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();
    __result['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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('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('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('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('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 ReferenceParams');
      return false;
    }
  }

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

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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({
    this.relatedDocuments,
    this.kind = 'full',
    this.resultId,
    required this.items,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static RelatedFullDocumentDiagnosticReport 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)'''))));
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    return RelatedFullDocumentDiagnosticReport(
      relatedDocuments: relatedDocuments,
      kind: kind,
      resultId: resultId,
      items: items,
    );
  }

  /// 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?>{};
    if (relatedDocuments != null) {
      __result['relatedDocuments'] = relatedDocuments;
    }
    __result['kind'] = kind;
    if (resultId != null) {
      __result['resultId'] = resultId;
    }
    __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('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('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('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();
      }
      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 mapEqual(
              relatedDocuments,
              other.relatedDocuments,
              (Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          a,
                      Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          kind == other.kind &&
          resultId == other.resultId &&
          listEqual(
              items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
          true;
    }
    return false;
  }

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

  @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.relatedDocuments,
    this.kind = 'unchanged',
    required this.resultId,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static RelatedUnchangedDocumentDiagnosticReport 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)'''))));
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    return RelatedUnchangedDocumentDiagnosticReport(
      relatedDocuments: relatedDocuments,
      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;

  /// 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?>{};
    if (relatedDocuments != null) {
      __result['relatedDocuments'] = relatedDocuments;
    }
    __result['kind'] = kind;
    __result['resultId'] = resultId;
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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 RelatedUnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RelatedUnchangedDocumentDiagnosticReport &&
        other.runtimeType == RelatedUnchangedDocumentDiagnosticReport) {
      return mapEqual(
              relatedDocuments,
              other.relatedDocuments,
              (Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          a,
                      Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          kind == other.kind &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(relatedDocuments),
        kind,
        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 = WorkspaceFolder.canParse(baseUriJson, nullLspJsonReporter)
        ? Either2<WorkspaceFolder, String>.t1(
            WorkspaceFolder.fromJson(baseUriJson as Map<String, Object?>))
        : (baseUriJson is String
            ? Either2<WorkspaceFolder, String>.t2(baseUriJson)
            : (throw '''$baseUriJson was not one of (WorkspaceFolder, String)'''));
    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<WorkspaceFolder, String> 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 (!((WorkspaceFolder.canParse(baseUri, reporter) ||
            baseUri is String))) {
          reporter
              .reportError('must be of type Either2<WorkspaceFolder, 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();
      }
      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.prepareSupport,
    this.prepareSupportDefaultBehavior,
    this.honorsChangeAnnotations,
  });
  static RenameClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson 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;
    final honorsChangeAnnotationsJson = json['honorsChangeAnnotations'];
    final honorsChangeAnnotations = honorsChangeAnnotationsJson as bool?;
    return RenameClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      prepareSupport: prepareSupport,
      prepareSupportDefaultBehavior: prepareSupportDefaultBehavior,
      honorsChangeAnnotations: honorsChangeAnnotations,
    );
  }

  /// 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 (prepareSupport != null) {
      __result['prepareSupport'] = prepareSupport;
    }
    if (prepareSupportDefaultBehavior != null) {
      __result['prepareSupportDefaultBehavior'] =
          prepareSupportDefaultBehavior?.toJson();
    }
    if (honorsChangeAnnotations != null) {
      __result['honorsChangeAnnotations'] = honorsChangeAnnotations;
    }
    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('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();
      }
      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();
      }
      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 &&
          prepareSupport == other.prepareSupport &&
          prepareSupportDefaultBehavior ==
              other.prepareSupportDefaultBehavior &&
          honorsChangeAnnotations == other.honorsChangeAnnotations &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        prepareSupport,
        prepareSupportDefaultBehavior,
        honorsChangeAnnotations,
      );

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

/// Rename file operation
class RenameFile implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFile.canParse,
    RenameFile.fromJson,
  );

  RenameFile({
    this.kind = 'rename',
    required this.oldUri,
    required this.newUri,
    this.options,
    this.annotationId,
  }) {
    if (kind != 'rename') {
      throw 'kind may only be the literal \'rename\'';
    }
  }
  static RenameFile fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final oldUriJson = json['oldUri'];
    final oldUri = oldUriJson as String;
    final newUriJson = json['newUri'];
    final newUri = newUriJson as String;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? RenameFileOptions.fromJson(optionsJson as Map<String, Object?>)
        : null;
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    return RenameFile(
      kind: kind,
      oldUri: oldUri,
      newUri: newUri,
      options: options,
      annotationId: annotationId,
    );
  }

  /// 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?>{};
    __result['kind'] = kind;
    __result['oldUri'] = oldUri;
    __result['newUri'] = newUri;
    if (options != null) {
      __result['options'] = options?.toJson();
    }
    if (annotationId != null) {
      __result['annotationId'] = annotationId;
    }
    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 == 'rename')) {
          reporter.reportError('must be the literal \'rename\'');
          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('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('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();
      }
      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();
      }
      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 kind == other.kind &&
          oldUri == other.oldUri &&
          newUri == other.newUri &&
          options == other.options &&
          annotationId == other.annotationId &&
          true;
    }
    return false;
  }

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

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

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

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

  /// 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 (overwrite != null) {
      __result['overwrite'] = overwrite;
    }
    if (ignoreIfExists != null) {
      __result['ignoreIfExists'] = ignoreIfExists;
    }
    return __result;
  }

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

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

  @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.textDocument,
    required this.position,
    this.workDoneToken,
  });
  static RenameParams fromJson(Map<String, Object?> json) {
    final newNameJson = json['newName'];
    final newName = newNameJson as String;
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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,
      textDocument: textDocument,
      position: position,
      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['textDocument'] = textDocument.toJson();
    __result['position'] = position.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('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('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('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 &&
          textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        newName,
        textDocument,
        position,
        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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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({
    required this.id,
    required this.method,
    this.params,
    required this.jsonrpc,
    this.clientRequestTime,
  });
  static RequestMessage 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)'''));
    final methodJson = json['method'];
    final method = Method.fromJson(methodJson as String);
    final paramsJson = json['params'];
    final params = paramsJson;
    final jsonrpcJson = json['jsonrpc'];
    final jsonrpc = jsonrpcJson as String;
    final clientRequestTimeJson = json['clientRequestTime'];
    final clientRequestTime = clientRequestTimeJson as int?;
    return RequestMessage(
      id: id,
      method: method,
      params: params,
      jsonrpc: jsonrpc,
      clientRequestTime: clientRequestTime,
    );
  }

  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?>{};
    __result['id'] = id;
    __result['method'] = method.toJson();
    if (params != null) {
      __result['params'] = params;
    }
    __result['jsonrpc'] = jsonrpc;
    if (clientRequestTime != null) {
      __result['clientRequestTime'] = clientRequestTime;
    }
    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();
      }
      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();
      }
      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('clientRequestTime');
      try {
        final clientRequestTime = obj['clientRequestTime'];
        if (clientRequestTime != null && !(clientRequestTime is int)) {
          reporter.reportError('must be of type int');
          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 id == other.id &&
          method == other.method &&
          params == other.params &&
          jsonrpc == other.jsonrpc &&
          clientRequestTime == other.clientRequestTime &&
          true;
    }
    return false;
  }

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

  @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,
    required this.message,
    this.data,
  });
  static ResponseError fromJson(Map<String, Object?> json) {
    final codeJson = json['code'];
    final code = ErrorCodes.fromJson(codeJson as int);
    final messageJson = json['message'];
    final message = messageJson as String;
    final dataJson = json['data'];
    final data = dataJson as String?;
    return ResponseError(
      code: code,
      message: message,
      data: data,
    );
  }

  /// 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();
    __result['message'] = message;
    if (data != null) {
      __result['data'] = data;
    }
    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('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('data');
      try {
        final data = obj['data'];
        if (data != null && !(data 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 &&
          message == other.message &&
          data == other.data &&
          true;
    }
    return false;
  }

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

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

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

  ResponseMessage({
    this.id,
    this.result,
    this.error,
    required this.jsonrpc,
    this.clientRequestTime,
  });
  static ResponseMessage fromJson(Map<String, Object?> json) {
    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 resultJson = json['result'];
    final result = resultJson;
    final errorJson = json['error'];
    final error = errorJson != null
        ? ResponseError.fromJson(errorJson as Map<String, Object?>)
        : null;
    final jsonrpcJson = json['jsonrpc'];
    final jsonrpc = jsonrpcJson as String;
    final clientRequestTimeJson = json['clientRequestTime'];
    final clientRequestTime = clientRequestTimeJson as int?;
    return ResponseMessage(
      id: id,
      result: result,
      error: error,
      jsonrpc: jsonrpc,
      clientRequestTime: clientRequestTime,
    );
  }

  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?>{};
    __result['id'] = id;
    __result['jsonrpc'] = jsonrpc;
    if (clientRequestTime != null) {
      __result['clientRequestTime'] = clientRequestTime;
    }
    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('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('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('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('clientRequestTime');
      try {
        final clientRequestTime = obj['clientRequestTime'];
        if (clientRequestTime != null && !(clientRequestTime is int)) {
          reporter.reportError('must be of type int');
          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 id == other.id &&
          result == other.result &&
          error == other.error &&
          jsonrpc == other.jsonrpc &&
          clientRequestTime == other.clientRequestTime &&
          true;
    }
    return false;
  }

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

  @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({
    required this.range,
    this.parent,
  });
  static SelectionRange fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final parentJson = json['parent'];
    final parent = parentJson != null
        ? SelectionRange.fromJson(parentJson as Map<String, Object?>)
        : null;
    return SelectionRange(
      range: range,
      parent: parent,
    );
  }

  /// 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?>{};
    __result['range'] = range.toJson();
    if (parent != null) {
      __result['parent'] = parent?.toJson();
    }
    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('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();
      }
      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 range == other.range && parent == other.parent && true;
    }
    return false;
  }

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

  @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({
    required this.textDocument,
    required this.positions,
    this.workDoneToken,
    this.partialResultToken,
  });
  static SelectionRangeParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionsJson = json['positions'];
    final positions = (positionsJson as List<Object?>)
        .map((item) => Position.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)''')));
    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 SelectionRangeParams(
      textDocument: textDocument,
      positions: positions,
      workDoneToken: workDoneToken,
      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;

  /// 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?>{};
    __result['textDocument'] = textDocument.toJson();
    __result['positions'] = positions.map((item) => item.toJson()).toList();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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 SelectionRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SelectionRangeParams &&
        other.runtimeType == SelectionRangeParams) {
      return textDocument == other.textDocument &&
          listEqual(
              positions, other.positions, (Position a, Position b) => a == b) &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

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

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

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

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

  /// 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<DocumentFilter>? 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?>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    __result['documentSelector'] = documentSelector;
    if (id != null) {
      __result['id'] = id;
    }
    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();
      }
      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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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();
      }
      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 workDoneProgress == other.workDoneProgress &&
          listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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({
    this.resultId,
    required this.data,
  });
  static SemanticTokens fromJson(Map<String, Object?> json) {
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>).map((item) => item as int).toList();
    return SemanticTokens(
      resultId: resultId,
      data: data,
    );
  }

  /// 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?>{};
    if (resultId != null) {
      __result['resultId'] = resultId;
    }
    __result['data'] = data;
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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 SemanticTokens');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokens && other.runtimeType == SemanticTokens) {
      return resultId == other.resultId &&
          listEqual(data, other.data, (int a, int b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

  SemanticTokensClientCapabilities({
    this.dynamicRegistration,
    required this.requests,
    required this.tokenTypes,
    required this.tokenModifiers,
    required this.formats,
    this.overlappingTokenSupport,
    this.multilineTokenSupport,
    this.serverCancelSupport,
    this.augmentsSyntaxTokens,
  });
  static SemanticTokensClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final requestsJson = json['requests'];
    final requests = SemanticTokensClientCapabilitiesRequests.fromJson(
        requestsJson as Map<String, Object?>);
    final tokenTypesJson = json['tokenTypes'];
    final tokenTypes = (tokenTypesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    final tokenModifiersJson = json['tokenModifiers'];
    final tokenModifiers = (tokenModifiersJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    final formatsJson = json['formats'];
    final formats = (formatsJson as List<Object?>)
        .map((item) => TokenFormat.fromJson(item as String))
        .toList();
    final overlappingTokenSupportJson = json['overlappingTokenSupport'];
    final overlappingTokenSupport = overlappingTokenSupportJson as bool?;
    final multilineTokenSupportJson = json['multilineTokenSupport'];
    final multilineTokenSupport = multilineTokenSupportJson as bool?;
    final serverCancelSupportJson = json['serverCancelSupport'];
    final serverCancelSupport = serverCancelSupportJson as bool?;
    final augmentsSyntaxTokensJson = json['augmentsSyntaxTokens'];
    final augmentsSyntaxTokens = augmentsSyntaxTokensJson as bool?;
    return SemanticTokensClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      requests: requests,
      tokenTypes: tokenTypes,
      tokenModifiers: tokenModifiers,
      formats: formats,
      overlappingTokenSupport: overlappingTokenSupport,
      multilineTokenSupport: multilineTokenSupport,
      serverCancelSupport: serverCancelSupport,
      augmentsSyntaxTokens: augmentsSyntaxTokens,
    );
  }

  /// 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 (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    __result['requests'] = requests.toJson();
    __result['tokenTypes'] = tokenTypes;
    __result['tokenModifiers'] = tokenModifiers;
    __result['formats'] = formats.map((item) => item.toJson()).toList();
    if (overlappingTokenSupport != null) {
      __result['overlappingTokenSupport'] = overlappingTokenSupport;
    }
    if (multilineTokenSupport != null) {
      __result['multilineTokenSupport'] = multilineTokenSupport;
    }
    if (serverCancelSupport != null) {
      __result['serverCancelSupport'] = serverCancelSupport;
    }
    if (augmentsSyntaxTokens != null) {
      __result['augmentsSyntaxTokens'] = augmentsSyntaxTokens;
    }
    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('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('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();
      }
      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('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('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('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('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('augmentsSyntaxTokens');
      try {
        final augmentsSyntaxTokens = obj['augmentsSyntaxTokens'];
        if (augmentsSyntaxTokens != null && !(augmentsSyntaxTokens is bool)) {
          reporter.reportError('must be of type bool');
          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 dynamicRegistration == other.dynamicRegistration &&
          requests == other.requests &&
          listEqual(
              tokenTypes, other.tokenTypes, (String a, String b) => a == b) &&
          listEqual(tokenModifiers, other.tokenModifiers,
              (String a, String b) => a == b) &&
          listEqual(formats, other.formats,
              (TokenFormat a, TokenFormat b) => a == b) &&
          overlappingTokenSupport == other.overlappingTokenSupport &&
          multilineTokenSupport == other.multilineTokenSupport &&
          serverCancelSupport == other.serverCancelSupport &&
          augmentsSyntaxTokens == other.augmentsSyntaxTokens &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        requests,
        lspHashCode(tokenTypes),
        lspHashCode(tokenModifiers),
        lspHashCode(formats),
        overlappingTokenSupport,
        multilineTokenSupport,
        serverCancelSupport,
        augmentsSyntaxTokens,
      );

  @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.range,
    this.full,
  });
  static SemanticTokensClientCapabilitiesRequests fromJson(
      Map<String, Object?> json) {
    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)''')));
    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)''')));
    return SemanticTokensClientCapabilitiesRequests(
      range: range,
      full: full,
    );
  }

  /// 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 (range != null) {
      __result['range'] = range;
    }
    if (full != null) {
      __result['full'] = full;
    }
    return __result;
  }

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

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

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

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

  SemanticTokensDelta({
    this.resultId,
    required this.edits,
  });
  static SemanticTokensDelta fromJson(Map<String, Object?> json) {
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map(
            (item) => SemanticTokensEdit.fromJson(item as Map<String, Object?>))
        .toList();
    return SemanticTokensDelta(
      resultId: resultId,
      edits: edits,
    );
  }

  /// 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?>{};
    if (resultId != null) {
      __result['resultId'] = resultId;
    }
    __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('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('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 SemanticTokensDelta');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensDelta &&
        other.runtimeType == SemanticTokensDelta) {
      return resultId == other.resultId &&
          listEqual(edits, other.edits,
              (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

  SemanticTokensDeltaParams({
    required this.textDocument,
    required this.previousResultId,
    this.workDoneToken,
    this.partialResultToken,
  });
  static SemanticTokensDeltaParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final previousResultIdJson = json['previousResultId'];
    final previousResultId = previousResultIdJson 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)''')));
    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 SemanticTokensDeltaParams(
      textDocument: textDocument,
      previousResultId: previousResultId,
      workDoneToken: workDoneToken,
      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;

  /// 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?>{};
    __result['textDocument'] = textDocument.toJson();
    __result['previousResultId'] = previousResultId;
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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 SemanticTokensDeltaParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensDeltaParams &&
        other.runtimeType == SemanticTokensDeltaParams) {
      return textDocument == other.textDocument &&
          previousResultId == other.previousResultId &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

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

  @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({
    required this.start,
    required this.deleteCount,
    this.data,
  });
  static SemanticTokensEdit fromJson(Map<String, Object?> json) {
    final startJson = json['start'];
    final start = startJson as int;
    final deleteCountJson = json['deleteCount'];
    final deleteCount = deleteCountJson as int;
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>?)?.map((item) => item as int).toList();
    return SemanticTokensEdit(
      start: start,
      deleteCount: deleteCount,
      data: data,
    );
  }

  /// 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?>{};
    __result['start'] = start;
    __result['deleteCount'] = deleteCount;
    if (data != null) {
      __result['data'] = data;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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('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();
      }
      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 start == other.start &&
          deleteCount == other.deleteCount &&
          listEqual(data, other.data, (int a, int b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        start,
        deleteCount,
        lspHashCode(data),
      );

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

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

  SemanticTokensLegend({
    required this.tokenTypes,
    required this.tokenModifiers,
  });
  static SemanticTokensLegend fromJson(Map<String, Object?> json) {
    final tokenTypesJson = json['tokenTypes'];
    final tokenTypes = (tokenTypesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    final tokenModifiersJson = json['tokenModifiers'];
    final tokenModifiers = (tokenModifiersJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return SemanticTokensLegend(
      tokenTypes: tokenTypes,
      tokenModifiers: tokenModifiers,
    );
  }

  /// 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['tokenTypes'] = tokenTypes;
    __result['tokenModifiers'] = tokenModifiers;
    return __result;
  }

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

  @override
  int get hashCode => Object.hash(
        lspHashCode(tokenTypes),
        lspHashCode(tokenModifiers),
      );

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

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

  SemanticTokensOptions({
    required this.legend,
    this.range,
    this.full,
    this.workDoneProgress,
  });
  static SemanticTokensOptions fromJson(Map<String, Object?> json) {
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    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 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 workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SemanticTokensOptions(
      legend: legend,
      range: range,
      full: full,
      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?>{};
    __result['legend'] = legend.toJson();
    if (range != null) {
      __result['range'] = range;
    }
    if (full != null) {
      __result['full'] = full;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

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

  @override
  int get hashCode => Object.hash(
        legend,
        range,
        full,
        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({
    required this.textDocument,
    this.workDoneToken,
    this.partialResultToken,
  });
  static SemanticTokensParams fromJson(Map<String, Object?> json) {
    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)''')));
    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 SemanticTokensParams(
      textDocument: textDocument,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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 SemanticTokensParams');
      return false;
    }
  }

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

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

  @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({
    required this.textDocument,
    required this.range,
    this.workDoneToken,
    this.partialResultToken,
  });
  static SemanticTokensRangeParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson 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)''')));
    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 SemanticTokensRangeParams(
      textDocument: textDocument,
      range: range,
      workDoneToken: workDoneToken,
      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;

  /// 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?>{};
    __result['textDocument'] = textDocument.toJson();
    __result['range'] = range.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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 SemanticTokensRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensRangeParams &&
        other.runtimeType == SemanticTokensRangeParams) {
      return textDocument == other.textDocument &&
          range == other.range &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

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

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

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

  SemanticTokensRegistrationOptions({
    this.documentSelector,
    required this.legend,
    this.range,
    this.full,
    this.workDoneProgress,
    this.id,
  });
  static SemanticTokensRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    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 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 workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final idJson = json['id'];
    final id = idJson as String?;
    return SemanticTokensRegistrationOptions(
      documentSelector: documentSelector,
      legend: legend,
      range: range,
      full: full,
      workDoneProgress: workDoneProgress,
      id: id,
    );
  }

  /// 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<DocumentFilter>? 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;
    __result['legend'] = legend.toJson();
    if (range != null) {
      __result['range'] = range;
    }
    if (full != null) {
      __result['full'] = full;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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('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('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 SemanticTokensRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensRegistrationOptions &&
        other.runtimeType == SemanticTokensRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          legend == other.legend &&
          range == other.range &&
          full == other.full &&
          workDoneProgress == other.workDoneProgress &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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.positionEncoding,
    this.textDocumentSync,
    this.notebookDocumentSync,
    this.completionProvider,
    this.hoverProvider,
    this.signatureHelpProvider,
    this.declarationProvider,
    this.definitionProvider,
    this.typeDefinitionProvider,
    this.implementationProvider,
    this.referencesProvider,
    this.documentHighlightProvider,
    this.documentSymbolProvider,
    this.codeActionProvider,
    this.codeLensProvider,
    this.documentLinkProvider,
    this.colorProvider,
    this.documentFormattingProvider,
    this.documentRangeFormattingProvider,
    this.documentOnTypeFormattingProvider,
    this.renameProvider,
    this.foldingRangeProvider,
    this.executeCommandProvider,
    this.selectionRangeProvider,
    this.linkedEditingRangeProvider,
    this.callHierarchyProvider,
    this.semanticTokensProvider,
    this.monikerProvider,
    this.typeHierarchyProvider,
    this.inlineValueProvider,
    this.inlayHintProvider,
    this.diagnosticProvider,
    this.workspaceSymbolProvider,
    this.workspace,
    this.experimental,
  });
  static ServerCapabilities fromJson(Map<String, Object?> json) {
    final positionEncodingJson = json['positionEncoding'];
    final positionEncoding = positionEncodingJson != null
        ? PositionEncodingKind.fromJson(positionEncodingJson as String)
        : null;
    final textDocumentSyncJson = json['textDocumentSync'];
    final textDocumentSync = textDocumentSyncJson == null
        ? null
        : (TextDocumentSyncOptions.canParse(
                textDocumentSyncJson, nullLspJsonReporter)
            ? Either2<TextDocumentSyncOptions, TextDocumentSyncKind>.t1(
                TextDocumentSyncOptions.fromJson(
                    textDocumentSyncJson as Map<String, Object?>))
            : (TextDocumentSyncKind.canParse(
                    textDocumentSyncJson, nullLspJsonReporter)
                ? Either2<TextDocumentSyncOptions, TextDocumentSyncKind>.t2(
                    TextDocumentSyncKind.fromJson(textDocumentSyncJson as int))
                : (throw '''$textDocumentSyncJson was not one of (TextDocumentSyncOptions, TextDocumentSyncKind)''')));
    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 completionProviderJson = json['completionProvider'];
    final completionProvider = completionProviderJson != null
        ? CompletionOptions.fromJson(
            completionProviderJson as Map<String, Object?>)
        : null;
    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 signatureHelpProviderJson = json['signatureHelpProvider'];
    final signatureHelpProvider = signatureHelpProviderJson != null
        ? SignatureHelpOptions.fromJson(
            signatureHelpProviderJson 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 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 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 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 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 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 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 documentLinkProviderJson = json['documentLinkProvider'];
    final documentLinkProvider = documentLinkProviderJson != null
        ? DocumentLinkOptions.fromJson(
            documentLinkProviderJson 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 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 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 documentOnTypeFormattingProviderJson =
        json['documentOnTypeFormattingProvider'];
    final documentOnTypeFormattingProvider =
        documentOnTypeFormattingProviderJson != null
            ? DocumentOnTypeFormattingOptions.fromJson(
                documentOnTypeFormattingProviderJson as Map<String, Object?>)
            : null;
    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 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 executeCommandProviderJson = json['executeCommandProvider'];
    final executeCommandProvider = executeCommandProviderJson != null
        ? ExecuteCommandOptions.fromJson(
            executeCommandProviderJson as Map<String, Object?>)
        : null;
    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 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 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 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 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 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 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 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 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 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)''')));
    final workspaceJson = json['workspace'];
    final workspace = workspaceJson != null
        ? ServerCapabilitiesWorkspace.fromJson(
            workspaceJson as Map<String, Object?>)
        : null;
    final experimentalJson = json['experimental'];
    final experimental = experimentalJson;
    return ServerCapabilities(
      positionEncoding: positionEncoding,
      textDocumentSync: textDocumentSync,
      notebookDocumentSync: notebookDocumentSync,
      completionProvider: completionProvider,
      hoverProvider: hoverProvider,
      signatureHelpProvider: signatureHelpProvider,
      declarationProvider: declarationProvider,
      definitionProvider: definitionProvider,
      typeDefinitionProvider: typeDefinitionProvider,
      implementationProvider: implementationProvider,
      referencesProvider: referencesProvider,
      documentHighlightProvider: documentHighlightProvider,
      documentSymbolProvider: documentSymbolProvider,
      codeActionProvider: codeActionProvider,
      codeLensProvider: codeLensProvider,
      documentLinkProvider: documentLinkProvider,
      colorProvider: colorProvider,
      documentFormattingProvider: documentFormattingProvider,
      documentRangeFormattingProvider: documentRangeFormattingProvider,
      documentOnTypeFormattingProvider: documentOnTypeFormattingProvider,
      renameProvider: renameProvider,
      foldingRangeProvider: foldingRangeProvider,
      executeCommandProvider: executeCommandProvider,
      selectionRangeProvider: selectionRangeProvider,
      linkedEditingRangeProvider: linkedEditingRangeProvider,
      callHierarchyProvider: callHierarchyProvider,
      semanticTokensProvider: semanticTokensProvider,
      monikerProvider: monikerProvider,
      typeHierarchyProvider: typeHierarchyProvider,
      inlineValueProvider: inlineValueProvider,
      inlayHintProvider: inlayHintProvider,
      diagnosticProvider: diagnosticProvider,
      workspaceSymbolProvider: workspaceSymbolProvider,
      workspace: workspace,
      experimental: experimental,
    );
  }

  /// 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<TextDocumentSyncOptions, TextDocumentSyncKind>?
      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 (positionEncoding != null) {
      __result['positionEncoding'] = positionEncoding?.toJson();
    }
    if (textDocumentSync != null) {
      __result['textDocumentSync'] = textDocumentSync;
    }
    if (notebookDocumentSync != null) {
      __result['notebookDocumentSync'] = notebookDocumentSync;
    }
    if (completionProvider != null) {
      __result['completionProvider'] = completionProvider?.toJson();
    }
    if (hoverProvider != null) {
      __result['hoverProvider'] = hoverProvider;
    }
    if (signatureHelpProvider != null) {
      __result['signatureHelpProvider'] = signatureHelpProvider?.toJson();
    }
    if (declarationProvider != null) {
      __result['declarationProvider'] = declarationProvider;
    }
    if (definitionProvider != null) {
      __result['definitionProvider'] = definitionProvider;
    }
    if (typeDefinitionProvider != null) {
      __result['typeDefinitionProvider'] = typeDefinitionProvider;
    }
    if (implementationProvider != null) {
      __result['implementationProvider'] = implementationProvider;
    }
    if (referencesProvider != null) {
      __result['referencesProvider'] = referencesProvider;
    }
    if (documentHighlightProvider != null) {
      __result['documentHighlightProvider'] = documentHighlightProvider;
    }
    if (documentSymbolProvider != null) {
      __result['documentSymbolProvider'] = documentSymbolProvider;
    }
    if (codeActionProvider != null) {
      __result['codeActionProvider'] = codeActionProvider;
    }
    if (codeLensProvider != null) {
      __result['codeLensProvider'] = codeLensProvider?.toJson();
    }
    if (documentLinkProvider != null) {
      __result['documentLinkProvider'] = documentLinkProvider?.toJson();
    }
    if (colorProvider != null) {
      __result['colorProvider'] = colorProvider;
    }
    if (documentFormattingProvider != null) {
      __result['documentFormattingProvider'] = documentFormattingProvider;
    }
    if (documentRangeFormattingProvider != null) {
      __result['documentRangeFormattingProvider'] =
          documentRangeFormattingProvider;
    }
    if (documentOnTypeFormattingProvider != null) {
      __result['documentOnTypeFormattingProvider'] =
          documentOnTypeFormattingProvider?.toJson();
    }
    if (renameProvider != null) {
      __result['renameProvider'] = renameProvider;
    }
    if (foldingRangeProvider != null) {
      __result['foldingRangeProvider'] = foldingRangeProvider;
    }
    if (executeCommandProvider != null) {
      __result['executeCommandProvider'] = executeCommandProvider?.toJson();
    }
    if (selectionRangeProvider != null) {
      __result['selectionRangeProvider'] = selectionRangeProvider;
    }
    if (linkedEditingRangeProvider != null) {
      __result['linkedEditingRangeProvider'] = linkedEditingRangeProvider;
    }
    if (callHierarchyProvider != null) {
      __result['callHierarchyProvider'] = callHierarchyProvider;
    }
    if (semanticTokensProvider != null) {
      __result['semanticTokensProvider'] = semanticTokensProvider;
    }
    if (monikerProvider != null) {
      __result['monikerProvider'] = monikerProvider;
    }
    if (typeHierarchyProvider != null) {
      __result['typeHierarchyProvider'] = typeHierarchyProvider;
    }
    if (inlineValueProvider != null) {
      __result['inlineValueProvider'] = inlineValueProvider;
    }
    if (inlayHintProvider != null) {
      __result['inlayHintProvider'] = inlayHintProvider;
    }
    if (diagnosticProvider != null) {
      __result['diagnosticProvider'] = diagnosticProvider;
    }
    if (workspaceSymbolProvider != null) {
      __result['workspaceSymbolProvider'] = workspaceSymbolProvider;
    }
    if (workspace != null) {
      __result['workspace'] = workspace?.toJson();
    }
    if (experimental != null) {
      __result['experimental'] = experimental;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('textDocumentSync');
      try {
        final textDocumentSync = obj['textDocumentSync'];
        if (textDocumentSync != null &&
            !((TextDocumentSyncOptions.canParse(textDocumentSync, reporter) ||
                TextDocumentSyncKind.canParse(textDocumentSync, reporter)))) {
          reporter.reportError(
              'must be of type Either2<TextDocumentSyncOptions, TextDocumentSyncKind>');
          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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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();
      }
      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();
      }
      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 positionEncoding == other.positionEncoding &&
          textDocumentSync == other.textDocumentSync &&
          notebookDocumentSync == other.notebookDocumentSync &&
          completionProvider == other.completionProvider &&
          hoverProvider == other.hoverProvider &&
          signatureHelpProvider == other.signatureHelpProvider &&
          declarationProvider == other.declarationProvider &&
          definitionProvider == other.definitionProvider &&
          typeDefinitionProvider == other.typeDefinitionProvider &&
          implementationProvider == other.implementationProvider &&
          referencesProvider == other.referencesProvider &&
          documentHighlightProvider == other.documentHighlightProvider &&
          documentSymbolProvider == other.documentSymbolProvider &&
          codeActionProvider == other.codeActionProvider &&
          codeLensProvider == other.codeLensProvider &&
          documentLinkProvider == other.documentLinkProvider &&
          colorProvider == other.colorProvider &&
          documentFormattingProvider == other.documentFormattingProvider &&
          documentRangeFormattingProvider ==
              other.documentRangeFormattingProvider &&
          documentOnTypeFormattingProvider ==
              other.documentOnTypeFormattingProvider &&
          renameProvider == other.renameProvider &&
          foldingRangeProvider == other.foldingRangeProvider &&
          executeCommandProvider == other.executeCommandProvider &&
          selectionRangeProvider == other.selectionRangeProvider &&
          linkedEditingRangeProvider == other.linkedEditingRangeProvider &&
          callHierarchyProvider == other.callHierarchyProvider &&
          semanticTokensProvider == other.semanticTokensProvider &&
          monikerProvider == other.monikerProvider &&
          typeHierarchyProvider == other.typeHierarchyProvider &&
          inlineValueProvider == other.inlineValueProvider &&
          inlayHintProvider == other.inlayHintProvider &&
          diagnosticProvider == other.diagnosticProvider &&
          workspaceSymbolProvider == other.workspaceSymbolProvider &&
          workspace == other.workspace &&
          experimental == other.experimental &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll([
        positionEncoding,
        textDocumentSync,
        notebookDocumentSync,
        completionProvider,
        hoverProvider,
        signatureHelpProvider,
        declarationProvider,
        definitionProvider,
        typeDefinitionProvider,
        implementationProvider,
        referencesProvider,
        documentHighlightProvider,
        documentSymbolProvider,
        codeActionProvider,
        codeLensProvider,
        documentLinkProvider,
        colorProvider,
        documentFormattingProvider,
        documentRangeFormattingProvider,
        documentOnTypeFormattingProvider,
        renameProvider,
        foldingRangeProvider,
        executeCommandProvider,
        selectionRangeProvider,
        linkedEditingRangeProvider,
        callHierarchyProvider,
        semanticTokensProvider,
        monikerProvider,
        typeHierarchyProvider,
        inlineValueProvider,
        inlayHintProvider,
        diagnosticProvider,
        workspaceSymbolProvider,
        workspace,
        experimental,
      ]);

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

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

  ServerCapabilitiesFileOperations({
    this.didCreate,
    this.willCreate,
    this.didRename,
    this.willRename,
    this.didDelete,
    this.willDelete,
  });
  static ServerCapabilitiesFileOperations fromJson(Map<String, Object?> json) {
    final didCreateJson = json['didCreate'];
    final didCreate = didCreateJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didCreateJson as Map<String, Object?>)
        : null;
    final willCreateJson = json['willCreate'];
    final willCreate = willCreateJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willCreateJson as Map<String, Object?>)
        : null;
    final didRenameJson = json['didRename'];
    final didRename = didRenameJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didRenameJson as Map<String, Object?>)
        : null;
    final willRenameJson = json['willRename'];
    final willRename = willRenameJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willRenameJson as Map<String, Object?>)
        : null;
    final didDeleteJson = json['didDelete'];
    final didDelete = didDeleteJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didDeleteJson as Map<String, Object?>)
        : null;
    final willDeleteJson = json['willDelete'];
    final willDelete = willDeleteJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willDeleteJson as Map<String, Object?>)
        : null;
    return ServerCapabilitiesFileOperations(
      didCreate: didCreate,
      willCreate: willCreate,
      didRename: didRename,
      willRename: willRename,
      didDelete: didDelete,
      willDelete: willDelete,
    );
  }

  /// 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 (willCreate != null) {
      __result['willCreate'] = willCreate?.toJson();
    }
    if (didRename != null) {
      __result['didRename'] = didRename?.toJson();
    }
    if (willRename != null) {
      __result['willRename'] = willRename?.toJson();
    }
    if (didDelete != null) {
      __result['didDelete'] = didDelete?.toJson();
    }
    if (willDelete != null) {
      __result['willDelete'] = willDelete?.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('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('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('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();
      }
      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('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();
      }
      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 &&
          willCreate == other.willCreate &&
          didRename == other.didRename &&
          willRename == other.willRename &&
          didDelete == other.didDelete &&
          willDelete == other.willDelete &&
          true;
    }
    return false;
  }

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

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

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

  ServerCapabilitiesWorkspace({
    this.workspaceFolders,
    this.fileOperations,
  });
  static ServerCapabilitiesWorkspace fromJson(Map<String, Object?> json) {
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = workspaceFoldersJson != null
        ? WorkspaceFoldersServerCapabilities.fromJson(
            workspaceFoldersJson as Map<String, Object?>)
        : null;
    final fileOperationsJson = json['fileOperations'];
    final fileOperations = fileOperationsJson != null
        ? ServerCapabilitiesFileOperations.fromJson(
            fileOperationsJson as Map<String, Object?>)
        : null;
    return ServerCapabilitiesWorkspace(
      workspaceFolders: workspaceFolders,
      fileOperations: fileOperations,
    );
  }

  /// 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 (workspaceFolders != null) {
      __result['workspaceFolders'] = workspaceFolders?.toJson();
    }
    if (fileOperations != null) {
      __result['fileOperations'] = fileOperations?.toJson();
    }
    return __result;
  }

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

  @override
  int get hashCode => Object.hash(
        workspaceFolders,
        fileOperations,
      );

  @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({
    required this.uri,
    this.external,
    this.takeFocus,
    this.selection,
  });
  static ShowDocumentParams fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final externalJson = json['external'];
    final external = externalJson as bool?;
    final takeFocusJson = json['takeFocus'];
    final takeFocus = takeFocusJson as bool?;
    final selectionJson = json['selection'];
    final selection = selectionJson != null
        ? Range.fromJson(selectionJson as Map<String, Object?>)
        : null;
    return ShowDocumentParams(
      uri: uri,
      external: external,
      takeFocus: takeFocus,
      selection: selection,
    );
  }

  /// 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?>{};
    __result['uri'] = uri;
    if (external != null) {
      __result['external'] = external;
    }
    if (takeFocus != null) {
      __result['takeFocus'] = takeFocus;
    }
    if (selection != null) {
      __result['selection'] = selection?.toJson();
    }
    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('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('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('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();
      }
      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 uri == other.uri &&
          external == other.external &&
          takeFocus == other.takeFocus &&
          selection == other.selection &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        external,
        takeFocus,
        selection,
      );

  @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.type,
    required this.message,
  });
  static ShowMessageParams fromJson(Map<String, Object?> json) {
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    final messageJson = json['message'];
    final message = messageJson as String;
    return ShowMessageParams(
      type: type,
      message: message,
    );
  }

  /// The actual message.
  final String message;

  /// The message type.
  final MessageType type;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['type'] = type.toJson();
    __result['message'] = message;
    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 (!(MessageType.canParse(type, reporter))) {
          reporter.reportError('must be of type MessageType');
          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 ShowMessageParams');
      return false;
    }
  }

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

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

  @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({
    required this.type,
    required this.message,
    this.actions,
  });
  static ShowMessageRequestParams fromJson(Map<String, Object?> json) {
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    final messageJson = json['message'];
    final message = messageJson as String;
    final actionsJson = json['actions'];
    final actions = (actionsJson as List<Object?>?)
        ?.map(
            (item) => MessageActionItem.fromJson(item as Map<String, Object?>))
        .toList();
    return ShowMessageRequestParams(
      type: type,
      message: message,
      actions: actions,
    );
  }

  /// 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?>{};
    __result['type'] = type.toJson();
    __result['message'] = message;
    if (actions != null) {
      __result['actions'] = actions?.map((item) => item.toJson()).toList();
    }
    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 (!(MessageType.canParse(type, reporter))) {
          reporter.reportError('must be of type MessageType');
          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('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();
      }
      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 type == other.type &&
          message == other.message &&
          listEqual(actions, other.actions,
              (MessageActionItem a, MessageActionItem b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        type,
        message,
        lspHashCode(actions),
      );

  @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({
    required this.signatures,
    this.activeSignature,
    this.activeParameter,
  });
  static SignatureHelp fromJson(Map<String, Object?> json) {
    final signaturesJson = json['signatures'];
    final signatures = (signaturesJson as List<Object?>)
        .map((item) =>
            SignatureInformation.fromJson(item as Map<String, Object?>))
        .toList();
    final activeSignatureJson = json['activeSignature'];
    final activeSignature = activeSignatureJson as int?;
    final activeParameterJson = json['activeParameter'];
    final activeParameter = activeParameterJson as int?;
    return SignatureHelp(
      signatures: signatures,
      activeSignature: activeSignature,
      activeParameter: activeParameter,
    );
  }

  /// 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?>{};
    __result['signatures'] = signatures.map((item) => item.toJson()).toList();
    if (activeSignature != null) {
      __result['activeSignature'] = activeSignature;
    }
    if (activeParameter != null) {
      __result['activeParameter'] = activeParameter;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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('activeParameter');
      try {
        final activeParameter = obj['activeParameter'];
        if (activeParameter != null && !(activeParameter is int)) {
          reporter.reportError('must be of type int');
          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 listEqual(signatures, other.signatures,
              (SignatureInformation a, SignatureInformation b) => a == b) &&
          activeSignature == other.activeSignature &&
          activeParameter == other.activeParameter &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(signatures),
        activeSignature,
        activeParameter,
      );

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

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

  SignatureHelpClientCapabilities({
    this.dynamicRegistration,
    this.signatureInformation,
    this.contextSupport,
  });
  static SignatureHelpClientCapabilities fromJson(Map<String, Object?> json) {
    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;
    final contextSupportJson = json['contextSupport'];
    final contextSupport = contextSupportJson as bool?;
    return SignatureHelpClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      signatureInformation: signatureInformation,
      contextSupport: contextSupport,
    );
  }

  /// 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 (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (signatureInformation != null) {
      __result['signatureInformation'] = signatureInformation?.toJson();
    }
    if (contextSupport != null) {
      __result['contextSupport'] = contextSupport;
    }
    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('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();
      }
      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();
      }
      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 dynamicRegistration == other.dynamicRegistration &&
          signatureInformation == other.signatureInformation &&
          contextSupport == other.contextSupport &&
          true;
    }
    return false;
  }

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

  @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.documentationFormat,
    this.parameterInformation,
    this.activeParameterSupport,
  });
  static SignatureHelpClientCapabilitiesSignatureInformation fromJson(
      Map<String, Object?> json) {
    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;
    final activeParameterSupportJson = json['activeParameterSupport'];
    final activeParameterSupport = activeParameterSupportJson as bool?;
    return SignatureHelpClientCapabilitiesSignatureInformation(
      documentationFormat: documentationFormat,
      parameterInformation: parameterInformation,
      activeParameterSupport: activeParameterSupport,
    );
  }

  /// 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 (documentationFormat != null) {
      __result['documentationFormat'] =
          documentationFormat?.map((item) => item.toJson()).toList();
    }
    if (parameterInformation != null) {
      __result['parameterInformation'] = parameterInformation?.toJson();
    }
    if (activeParameterSupport != null) {
      __result['activeParameterSupport'] = activeParameterSupport;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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();
      }
      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 listEqual(documentationFormat, other.documentationFormat,
              (MarkupKind a, MarkupKind b) => a == b) &&
          parameterInformation == other.parameterInformation &&
          activeParameterSupport == other.activeParameterSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentationFormat),
        parameterInformation,
        activeParameterSupport,
      );

  @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({
    required this.triggerKind,
    this.triggerCharacter,
    required this.isRetrigger,
    this.activeSignatureHelp,
  });
  static SignatureHelpContext fromJson(Map<String, Object?> json) {
    final triggerKindJson = json['triggerKind'];
    final triggerKind =
        SignatureHelpTriggerKind.fromJson(triggerKindJson as int);
    final triggerCharacterJson = json['triggerCharacter'];
    final triggerCharacter = triggerCharacterJson as String?;
    final isRetriggerJson = json['isRetrigger'];
    final isRetrigger = isRetriggerJson as bool;
    final activeSignatureHelpJson = json['activeSignatureHelp'];
    final activeSignatureHelp = activeSignatureHelpJson != null
        ? SignatureHelp.fromJson(
            activeSignatureHelpJson as Map<String, Object?>)
        : null;
    return SignatureHelpContext(
      triggerKind: triggerKind,
      triggerCharacter: triggerCharacter,
      isRetrigger: isRetrigger,
      activeSignatureHelp: activeSignatureHelp,
    );
  }

  /// 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?>{};
    __result['triggerKind'] = triggerKind.toJson();
    if (triggerCharacter != null) {
      __result['triggerCharacter'] = triggerCharacter;
    }
    __result['isRetrigger'] = isRetrigger;
    if (activeSignatureHelp != null) {
      __result['activeSignatureHelp'] = activeSignatureHelp?.toJson();
    }
    return __result;
  }

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

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

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

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

  SignatureHelpOptions({
    this.triggerCharacters,
    this.retriggerCharacters,
    this.workDoneProgress,
  });
  static SignatureHelpOptions fromJson(Map<String, Object?> json) {
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final retriggerCharactersJson = json['retriggerCharacters'];
    final retriggerCharacters = (retriggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SignatureHelpOptions(
      triggerCharacters: triggerCharacters,
      retriggerCharacters: retriggerCharacters,
      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 (triggerCharacters != null) {
      __result['triggerCharacters'] = triggerCharacters;
    }
    if (retriggerCharacters != null) {
      __result['retriggerCharacters'] = retriggerCharacters;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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('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(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          listEqual(retriggerCharacters, other.retriggerCharacters,
              (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(triggerCharacters),
        lspHashCode(retriggerCharacters),
        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.textDocument,
    required this.position,
    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 textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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,
      textDocument: textDocument,
      position: position,
      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['textDocument'] = textDocument.toJson();
    __result['position'] = position.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('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('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('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 &&
          textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        context,
        textDocument,
        position,
        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.triggerCharacters,
    this.retriggerCharacters,
    this.workDoneProgress,
  });
  static SignatureHelpRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final retriggerCharactersJson = json['retriggerCharacters'];
    final retriggerCharacters = (retriggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SignatureHelpRegistrationOptions(
      documentSelector: documentSelector,
      triggerCharacters: triggerCharacters,
      retriggerCharacters: retriggerCharacters,
      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<DocumentFilter>? 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 (triggerCharacters != null) {
      __result['triggerCharacters'] = triggerCharacters;
    }
    if (retriggerCharacters != null) {
      __result['retriggerCharacters'] = retriggerCharacters;
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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('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,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          listEqual(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          listEqual(retriggerCharacters, other.retriggerCharacters,
              (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        lspHashCode(triggerCharacters),
        lspHashCode(retriggerCharacters),
        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({
    required this.label,
    this.documentation,
    this.parameters,
    this.activeParameter,
  });
  static SignatureInformation fromJson(Map<String, Object?> json) {
    final labelJson = json['label'];
    final label = labelJson as String;
    final documentationJson = json['documentation'];
    final documentation = documentationJson == null
        ? null
        : (documentationJson is String
            ? Either2<String, MarkupContent>.t1(documentationJson)
            : (MarkupContent.canParse(documentationJson, nullLspJsonReporter)
                ? Either2<String, MarkupContent>.t2(MarkupContent.fromJson(
                    documentationJson as Map<String, Object?>))
                : (throw '''$documentationJson was not one of (String, MarkupContent)''')));
    final parametersJson = json['parameters'];
    final parameters = (parametersJson as List<Object?>?)
        ?.map((item) =>
            ParameterInformation.fromJson(item as Map<String, Object?>))
        .toList();
    final activeParameterJson = json['activeParameter'];
    final activeParameter = activeParameterJson as int?;
    return SignatureInformation(
      label: label,
      documentation: documentation,
      parameters: parameters,
      activeParameter: activeParameter,
    );
  }

  /// 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<String, MarkupContent>? 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?>{};
    __result['label'] = label;
    if (documentation != null) {
      __result['documentation'] = documentation;
    }
    if (parameters != null) {
      __result['parameters'] =
          parameters?.map((item) => item.toJson()).toList();
    }
    if (activeParameter != null) {
      __result['activeParameter'] = activeParameter;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('documentation');
      try {
        final documentation = obj['documentation'];
        if (documentation != null &&
            !((documentation is String ||
                MarkupContent.canParse(documentation, reporter)))) {
          reporter
              .reportError('must be of type Either2<String, MarkupContent>');
          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();
      }
      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();
      }
      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 label == other.label &&
          documentation == other.documentation &&
          listEqual(parameters, other.parameters,
              (ParameterInformation a, ParameterInformation b) => a == b) &&
          activeParameter == other.activeParameter &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        label,
        documentation,
        lspHashCode(parameters),
        activeParameter,
      );

  @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({
    required this.name,
    required this.kind,
    this.tags,
    this.deprecated,
    required this.location,
    this.containerName,
  });
  static SymbolInformation fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    final deprecatedJson = json['deprecated'];
    final deprecated = deprecatedJson as bool?;
    final locationJson = json['location'];
    final location = Location.fromJson(locationJson as Map<String, Object?>);
    final containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    return SymbolInformation(
      name: name,
      kind: kind,
      tags: tags,
      deprecated: deprecated,
      location: location,
      containerName: containerName,
    );
  }

  /// 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?>{};
    __result['name'] = name;
    __result['kind'] = kind.toJson();
    if (tags != null) {
      __result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    if (deprecated != null) {
      __result['deprecated'] = deprecated;
    }
    __result['location'] = location.toJson();
    if (containerName != null) {
      __result['containerName'] = containerName;
    }
    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('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('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('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('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('containerName');
      try {
        final containerName = obj['containerName'];
        if (containerName != null && !(containerName is String)) {
          reporter.reportError('must be of type String');
          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 name == other.name &&
          kind == other.kind &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          deprecated == other.deprecated &&
          location == other.location &&
          containerName == other.containerName &&
          true;
    }
    return false;
  }

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

  @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({
    required this.syncKind,
    this.documentSelector,
  });
  static TextDocumentChangeRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final syncKindJson = json['syncKind'];
    final syncKind = TextDocumentSyncKind.fromJson(syncKindJson as int);
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    return TextDocumentChangeRegistrationOptions(
      syncKind: syncKind,
      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<DocumentFilter>? 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['syncKind'] = syncKind.toJson();
    __result['documentSelector'] = documentSelector;
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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 syncKind == other.syncKind &&
          listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          true;
    }
    return false;
  }

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

  @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.synchronization,
    this.completion,
    this.hover,
    this.signatureHelp,
    this.declaration,
    this.definition,
    this.typeDefinition,
    this.implementation,
    this.references,
    this.documentHighlight,
    this.documentSymbol,
    this.codeAction,
    this.codeLens,
    this.documentLink,
    this.colorProvider,
    this.formatting,
    this.rangeFormatting,
    this.onTypeFormatting,
    this.rename,
    this.publishDiagnostics,
    this.foldingRange,
    this.selectionRange,
    this.linkedEditingRange,
    this.callHierarchy,
    this.semanticTokens,
    this.moniker,
    this.typeHierarchy,
    this.inlineValue,
    this.inlayHint,
    this.diagnostic,
  });
  static TextDocumentClientCapabilities fromJson(Map<String, Object?> json) {
    final synchronizationJson = json['synchronization'];
    final synchronization = synchronizationJson != null
        ? TextDocumentSyncClientCapabilities.fromJson(
            synchronizationJson as Map<String, Object?>)
        : null;
    final completionJson = json['completion'];
    final completion = completionJson != null
        ? CompletionClientCapabilities.fromJson(
            completionJson as Map<String, Object?>)
        : null;
    final hoverJson = json['hover'];
    final hover = hoverJson != null
        ? HoverClientCapabilities.fromJson(hoverJson as Map<String, Object?>)
        : null;
    final signatureHelpJson = json['signatureHelp'];
    final signatureHelp = signatureHelpJson != null
        ? SignatureHelpClientCapabilities.fromJson(
            signatureHelpJson 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 typeDefinitionJson = json['typeDefinition'];
    final typeDefinition = typeDefinitionJson != null
        ? TypeDefinitionClientCapabilities.fromJson(
            typeDefinitionJson as Map<String, Object?>)
        : null;
    final implementationJson = json['implementation'];
    final implementation = implementationJson != null
        ? ImplementationClientCapabilities.fromJson(
            implementationJson as Map<String, Object?>)
        : null;
    final referencesJson = json['references'];
    final references = referencesJson != null
        ? ReferenceClientCapabilities.fromJson(
            referencesJson as Map<String, Object?>)
        : null;
    final documentHighlightJson = json['documentHighlight'];
    final documentHighlight = documentHighlightJson != null
        ? DocumentHighlightClientCapabilities.fromJson(
            documentHighlightJson as Map<String, Object?>)
        : null;
    final documentSymbolJson = json['documentSymbol'];
    final documentSymbol = documentSymbolJson != null
        ? DocumentSymbolClientCapabilities.fromJson(
            documentSymbolJson 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 documentLinkJson = json['documentLink'];
    final documentLink = documentLinkJson != null
        ? DocumentLinkClientCapabilities.fromJson(
            documentLinkJson as Map<String, Object?>)
        : null;
    final colorProviderJson = json['colorProvider'];
    final colorProvider = colorProviderJson != null
        ? DocumentColorClientCapabilities.fromJson(
            colorProviderJson as Map<String, Object?>)
        : null;
    final formattingJson = json['formatting'];
    final formatting = formattingJson != null
        ? DocumentFormattingClientCapabilities.fromJson(
            formattingJson as Map<String, Object?>)
        : null;
    final rangeFormattingJson = json['rangeFormatting'];
    final rangeFormatting = rangeFormattingJson != null
        ? DocumentRangeFormattingClientCapabilities.fromJson(
            rangeFormattingJson as Map<String, Object?>)
        : null;
    final onTypeFormattingJson = json['onTypeFormatting'];
    final onTypeFormatting = onTypeFormattingJson != null
        ? DocumentOnTypeFormattingClientCapabilities.fromJson(
            onTypeFormattingJson as Map<String, Object?>)
        : null;
    final renameJson = json['rename'];
    final rename = renameJson != null
        ? RenameClientCapabilities.fromJson(renameJson as Map<String, Object?>)
        : null;
    final publishDiagnosticsJson = json['publishDiagnostics'];
    final publishDiagnostics = publishDiagnosticsJson != null
        ? PublishDiagnosticsClientCapabilities.fromJson(
            publishDiagnosticsJson as Map<String, Object?>)
        : null;
    final foldingRangeJson = json['foldingRange'];
    final foldingRange = foldingRangeJson != null
        ? FoldingRangeClientCapabilities.fromJson(
            foldingRangeJson as Map<String, Object?>)
        : null;
    final selectionRangeJson = json['selectionRange'];
    final selectionRange = selectionRangeJson != null
        ? SelectionRangeClientCapabilities.fromJson(
            selectionRangeJson as Map<String, Object?>)
        : null;
    final linkedEditingRangeJson = json['linkedEditingRange'];
    final linkedEditingRange = linkedEditingRangeJson != null
        ? LinkedEditingRangeClientCapabilities.fromJson(
            linkedEditingRangeJson as Map<String, Object?>)
        : null;
    final callHierarchyJson = json['callHierarchy'];
    final callHierarchy = callHierarchyJson != null
        ? CallHierarchyClientCapabilities.fromJson(
            callHierarchyJson as Map<String, Object?>)
        : null;
    final semanticTokensJson = json['semanticTokens'];
    final semanticTokens = semanticTokensJson != null
        ? SemanticTokensClientCapabilities.fromJson(
            semanticTokensJson as Map<String, Object?>)
        : null;
    final monikerJson = json['moniker'];
    final moniker = monikerJson != null
        ? MonikerClientCapabilities.fromJson(
            monikerJson as Map<String, Object?>)
        : null;
    final typeHierarchyJson = json['typeHierarchy'];
    final typeHierarchy = typeHierarchyJson != null
        ? TypeHierarchyClientCapabilities1.fromJson(
            typeHierarchyJson as Map<String, Object?>)
        : null;
    final inlineValueJson = json['inlineValue'];
    final inlineValue = inlineValueJson != null
        ? InlineValueClientCapabilities.fromJson(
            inlineValueJson as Map<String, Object?>)
        : null;
    final inlayHintJson = json['inlayHint'];
    final inlayHint = inlayHintJson != null
        ? InlayHintClientCapabilities.fromJson(
            inlayHintJson as Map<String, Object?>)
        : null;
    final diagnosticJson = json['diagnostic'];
    final diagnostic = diagnosticJson != null
        ? DiagnosticClientCapabilities.fromJson(
            diagnosticJson as Map<String, Object?>)
        : null;
    return TextDocumentClientCapabilities(
      synchronization: synchronization,
      completion: completion,
      hover: hover,
      signatureHelp: signatureHelp,
      declaration: declaration,
      definition: definition,
      typeDefinition: typeDefinition,
      implementation: implementation,
      references: references,
      documentHighlight: documentHighlight,
      documentSymbol: documentSymbol,
      codeAction: codeAction,
      codeLens: codeLens,
      documentLink: documentLink,
      colorProvider: colorProvider,
      formatting: formatting,
      rangeFormatting: rangeFormatting,
      onTypeFormatting: onTypeFormatting,
      rename: rename,
      publishDiagnostics: publishDiagnostics,
      foldingRange: foldingRange,
      selectionRange: selectionRange,
      linkedEditingRange: linkedEditingRange,
      callHierarchy: callHierarchy,
      semanticTokens: semanticTokens,
      moniker: moniker,
      typeHierarchy: typeHierarchy,
      inlineValue: inlineValue,
      inlayHint: inlayHint,
      diagnostic: diagnostic,
    );
  }

  /// 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 (synchronization != null) {
      __result['synchronization'] = synchronization?.toJson();
    }
    if (completion != null) {
      __result['completion'] = completion?.toJson();
    }
    if (hover != null) {
      __result['hover'] = hover?.toJson();
    }
    if (signatureHelp != null) {
      __result['signatureHelp'] = signatureHelp?.toJson();
    }
    if (declaration != null) {
      __result['declaration'] = declaration?.toJson();
    }
    if (definition != null) {
      __result['definition'] = definition?.toJson();
    }
    if (typeDefinition != null) {
      __result['typeDefinition'] = typeDefinition?.toJson();
    }
    if (implementation != null) {
      __result['implementation'] = implementation?.toJson();
    }
    if (references != null) {
      __result['references'] = references?.toJson();
    }
    if (documentHighlight != null) {
      __result['documentHighlight'] = documentHighlight?.toJson();
    }
    if (documentSymbol != null) {
      __result['documentSymbol'] = documentSymbol?.toJson();
    }
    if (codeAction != null) {
      __result['codeAction'] = codeAction?.toJson();
    }
    if (codeLens != null) {
      __result['codeLens'] = codeLens?.toJson();
    }
    if (documentLink != null) {
      __result['documentLink'] = documentLink?.toJson();
    }
    if (colorProvider != null) {
      __result['colorProvider'] = colorProvider?.toJson();
    }
    if (formatting != null) {
      __result['formatting'] = formatting?.toJson();
    }
    if (rangeFormatting != null) {
      __result['rangeFormatting'] = rangeFormatting?.toJson();
    }
    if (onTypeFormatting != null) {
      __result['onTypeFormatting'] = onTypeFormatting?.toJson();
    }
    if (rename != null) {
      __result['rename'] = rename?.toJson();
    }
    if (publishDiagnostics != null) {
      __result['publishDiagnostics'] = publishDiagnostics?.toJson();
    }
    if (foldingRange != null) {
      __result['foldingRange'] = foldingRange?.toJson();
    }
    if (selectionRange != null) {
      __result['selectionRange'] = selectionRange?.toJson();
    }
    if (linkedEditingRange != null) {
      __result['linkedEditingRange'] = linkedEditingRange?.toJson();
    }
    if (callHierarchy != null) {
      __result['callHierarchy'] = callHierarchy?.toJson();
    }
    if (semanticTokens != null) {
      __result['semanticTokens'] = semanticTokens?.toJson();
    }
    if (moniker != null) {
      __result['moniker'] = moniker?.toJson();
    }
    if (typeHierarchy != null) {
      __result['typeHierarchy'] = typeHierarchy;
    }
    if (inlineValue != null) {
      __result['inlineValue'] = inlineValue?.toJson();
    }
    if (inlayHint != null) {
      __result['inlayHint'] = inlayHint?.toJson();
    }
    if (diagnostic != null) {
      __result['diagnostic'] = diagnostic?.toJson();
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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('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();
      }
      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('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('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();
      }
      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 synchronization == other.synchronization &&
          completion == other.completion &&
          hover == other.hover &&
          signatureHelp == other.signatureHelp &&
          declaration == other.declaration &&
          definition == other.definition &&
          typeDefinition == other.typeDefinition &&
          implementation == other.implementation &&
          references == other.references &&
          documentHighlight == other.documentHighlight &&
          documentSymbol == other.documentSymbol &&
          codeAction == other.codeAction &&
          codeLens == other.codeLens &&
          documentLink == other.documentLink &&
          colorProvider == other.colorProvider &&
          formatting == other.formatting &&
          rangeFormatting == other.rangeFormatting &&
          onTypeFormatting == other.onTypeFormatting &&
          rename == other.rename &&
          publishDiagnostics == other.publishDiagnostics &&
          foldingRange == other.foldingRange &&
          selectionRange == other.selectionRange &&
          linkedEditingRange == other.linkedEditingRange &&
          callHierarchy == other.callHierarchy &&
          semanticTokens == other.semanticTokens &&
          moniker == other.moniker &&
          typeHierarchy == other.typeHierarchy &&
          inlineValue == other.inlineValue &&
          inlayHint == other.inlayHint &&
          diagnostic == other.diagnostic &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll([
        synchronization,
        completion,
        hover,
        signatureHelp,
        declaration,
        definition,
        typeDefinition,
        implementation,
        references,
        documentHighlight,
        documentSymbol,
        codeAction,
        codeLens,
        documentLink,
        colorProvider,
        formatting,
        rangeFormatting,
        onTypeFormatting,
        rename,
        publishDiagnostics,
        foldingRange,
        selectionRange,
        linkedEditingRange,
        callHierarchy,
        semanticTokens,
        moniker,
        typeHierarchy,
        inlineValue,
        inlayHint,
        diagnostic,
      ]);

  @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.textDocument,
    required this.edits,
  });
  static TextDocumentEdit fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = OptionalVersionedTextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map((item) => SnippetTextEdit.canParse(item, nullLspJsonReporter)
            ? Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t1(
                SnippetTextEdit.fromJson(item as Map<String, Object?>))
            : (AnnotatedTextEdit.canParse(item, nullLspJsonReporter)
                ? Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t2(
                    AnnotatedTextEdit.fromJson(item as Map<String, Object?>))
                : (TextEdit.canParse(item, nullLspJsonReporter)
                    ? Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t3(
                        TextEdit.fromJson(item as Map<String, Object?>))
                    : (throw '''$item was not one of (SnippetTextEdit, AnnotatedTextEdit, TextEdit)'''))))
        .toList();
    return TextDocumentEdit(
      textDocument: textDocument,
      edits: edits,
    );
  }

  /// 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<SnippetTextEdit, AnnotatedTextEdit, TextEdit>> edits;

  /// The text document to change.
  final OptionalVersionedTextDocumentIdentifier textDocument;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['textDocument'] = textDocument.toJson();
    __result['edits'] = edits;
    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 (!(OptionalVersionedTextDocumentIdentifier.canParse(
            textDocument, reporter))) {
          reporter.reportError(
              'must be of type OptionalVersionedTextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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) => (SnippetTextEdit.canParse(item, reporter) ||
                AnnotatedTextEdit.canParse(item, reporter) ||
                TextEdit.canParse(item, reporter))))))) {
          reporter.reportError(
              'must be of type List<Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>>');
          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 textDocument == other.textDocument &&
          listEqual(
              edits,
              other.edits,
              (Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit> a,
                      Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        textDocument,
        lspHashCode(edits),
      );

  @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.uri,
    required this.languageId,
    required this.version,
    required this.text,
  });
  static TextDocumentItem fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final languageIdJson = json['languageId'];
    final languageId = languageIdJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    final textJson = json['text'];
    final text = textJson as String;
    return TextDocumentItem(
      uri: uri,
      languageId: languageId,
      version: version,
      text: text,
    );
  }

  /// 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['uri'] = uri;
    __result['languageId'] = languageId;
    __result['version'] = version;
    __result['text'] = text;
    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('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('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();
      }
      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 TextDocumentItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentItem && other.runtimeType == TextDocumentItem) {
      return uri == other.uri &&
          languageId == other.languageId &&
          version == other.version &&
          text == other.text &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        languageId,
        version,
        text,
      );

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

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

  TextDocumentPositionParams({
    required this.textDocument,
    required this.position,
  });
  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 textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    return TextDocumentPositionParams(
      textDocument: textDocument,
      position: position,
    );
  }

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['textDocument'] = textDocument.toJson();
    __result['position'] = position.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();
      }
      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();
      }
      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 textDocument == other.textDocument &&
          position == other.position &&
          true;
    }
    return false;
  }

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

  @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) => DocumentFilter.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<DocumentFilter>? 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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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,
              (DocumentFilter a, DocumentFilter 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.includeText,
    this.documentSelector,
  });
  static TextDocumentSaveRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final includeTextJson = json['includeText'];
    final includeText = includeTextJson as bool?;
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    return TextDocumentSaveRegistrationOptions(
      includeText: includeText,
      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<DocumentFilter>? documentSelector;

  /// 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;
    }
    __result['documentSelector'] = documentSelector;
    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();
      }
      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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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 includeText == other.includeText &&
          listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          true;
    }
    return false;
  }

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

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

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

  TextDocumentSyncClientCapabilities({
    this.dynamicRegistration,
    this.willSave,
    this.willSaveWaitUntil,
    this.didSave,
  });
  static TextDocumentSyncClientCapabilities fromJson(
      Map<String, Object?> json) {
    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?;
    final didSaveJson = json['didSave'];
    final didSave = didSaveJson as bool?;
    return TextDocumentSyncClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      willSave: willSave,
      willSaveWaitUntil: willSaveWaitUntil,
      didSave: didSave,
    );
  }

  /// 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 (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (willSave != null) {
      __result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      __result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    if (didSave != null) {
      __result['didSave'] = didSave;
    }
    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('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();
      }
      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();
      }
      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 dynamicRegistration == other.dynamicRegistration &&
          willSave == other.willSave &&
          willSaveWaitUntil == other.willSaveWaitUntil &&
          didSave == other.didSave &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        willSave,
        willSaveWaitUntil,
        didSave,
      );

  @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.openClose,
    this.change,
    this.willSave,
    this.willSaveWaitUntil,
    this.save,
  });
  static TextDocumentSyncOptions fromJson(Map<String, Object?> json) {
    final openCloseJson = json['openClose'];
    final openClose = openCloseJson as bool?;
    final changeJson = json['change'];
    final change = changeJson != null
        ? TextDocumentSyncKind.fromJson(changeJson as int)
        : null;
    final willSaveJson = json['willSave'];
    final willSave = willSaveJson as bool?;
    final willSaveWaitUntilJson = json['willSaveWaitUntil'];
    final willSaveWaitUntil = willSaveWaitUntilJson 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)''')));
    return TextDocumentSyncOptions(
      openClose: openClose,
      change: change,
      willSave: willSave,
      willSaveWaitUntil: willSaveWaitUntil,
      save: save,
    );
  }

  /// 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 (openClose != null) {
      __result['openClose'] = openClose;
    }
    if (change != null) {
      __result['change'] = change?.toJson();
    }
    if (willSave != null) {
      __result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      __result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    if (save != null) {
      __result['save'] = save;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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('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();
      }
      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();
      }
      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 openClose == other.openClose &&
          change == other.change &&
          willSave == other.willSave &&
          willSaveWaitUntil == other.willSaveWaitUntil &&
          save == other.save &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        openClose,
        change,
        willSave,
        willSaveWaitUntil,
        save,
      );

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

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

  TextEdit({
    required this.range,
    required this.newText,
  });
  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 rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final newTextJson = json['newText'];
    final newText = newTextJson as String;
    return TextEdit(
      range: range,
      newText: newText,
    );
  }

  /// 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['range'] = range.toJson();
    __result['newText'] = newText;
    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('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();
      }
      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 range == other.range && newText == other.newText && true;
    }
    return false;
  }

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

  @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({
    required this.textDocument,
    required this.position,
    this.workDoneToken,
    this.partialResultToken,
  });
  static TypeDefinitionParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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)''')));
    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 TypeDefinitionParams(
      textDocument: textDocument,
      position: position,
      workDoneToken: workDoneToken,
      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;

  /// 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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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();
      }
      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('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('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 TypeDefinitionParams');
      return false;
    }
  }

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

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

  @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.workDoneProgress,
    this.id,
  });
  static TypeDefinitionRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final idJson = json['id'];
    final id = idJson as String?;
    return TypeDefinitionRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
      id: id,
    );
  }

  /// 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<DocumentFilter>? 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 (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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 TypeDefinitionRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeDefinitionRegistrationOptions &&
        other.runtimeType == TypeDefinitionRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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({
    required this.name,
    required this.kind,
    this.tags,
    this.detail,
    required this.uri,
    required this.range,
    required this.selectionRange,
    this.data,
  });
  static TypeHierarchyItem fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final uriJson = json['uri'];
    final uri = uriJson 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 dataJson = json['data'];
    final data = dataJson;
    return TypeHierarchyItem(
      name: name,
      kind: kind,
      tags: tags,
      detail: detail,
      uri: uri,
      range: range,
      selectionRange: selectionRange,
      data: data,
    );
  }

  /// 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?>{};
    __result['name'] = name;
    __result['kind'] = kind.toJson();
    if (tags != null) {
      __result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    if (detail != null) {
      __result['detail'] = detail;
    }
    __result['uri'] = uri;
    __result['range'] = range.toJson();
    __result['selectionRange'] = selectionRange.toJson();
    if (data != null) {
      __result['data'] = data;
    }
    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('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('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('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('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('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();
      }
      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 name == other.name &&
          kind == other.kind &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          detail == other.detail &&
          uri == other.uri &&
          range == other.range &&
          selectionRange == other.selectionRange &&
          data == other.data &&
          true;
    }
    return false;
  }

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

  @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.textDocument,
    required this.position,
    this.workDoneToken,
  });
  static TypeHierarchyPrepareParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson 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(
      textDocument: textDocument,
      position: position,
      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['textDocument'] = textDocument.toJson();
    __result['position'] = position.toJson();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    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();
      }
      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('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 textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        textDocument,
        position,
        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.workDoneProgress,
    this.id,
  });
  static TypeHierarchyRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) => DocumentFilter.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    final idJson = json['id'];
    final id = idJson as String?;
    return TypeHierarchyRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
      id: id,
    );
  }

  /// 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<DocumentFilter>? 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 (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    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) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          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('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 TypeHierarchyRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchyRegistrationOptions &&
        other.runtimeType == TypeHierarchyRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          id == other.id &&
          true;
    }
    return false;
  }

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

  @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.workDoneToken,
    this.partialResultToken,
  });
  static TypeHierarchySubtypesParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = TypeHierarchyItem.fromJson(itemJson 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)''')));
    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 TypeHierarchySubtypesParams(
      item: item,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  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 (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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('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('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 TypeHierarchySubtypesParams');
      return false;
    }
  }

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

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

  @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.workDoneToken,
    this.partialResultToken,
  });
  static TypeHierarchySupertypesParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = TypeHierarchyItem.fromJson(itemJson 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)''')));
    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 TypeHierarchySupertypesParams(
      item: item,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  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 (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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('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('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 TypeHierarchySupertypesParams');
      return false;
    }
  }

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

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

  @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.version,
    required this.uri,
  });
  static VersionedNotebookDocumentIdentifier fromJson(
      Map<String, Object?> json) {
    final versionJson = json['version'];
    final version = versionJson as int;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return VersionedNotebookDocumentIdentifier(
      version: version,
      uri: uri,
    );
  }

  /// 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['version'] = version;
    __result['uri'] = uri;
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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 VersionedNotebookDocumentIdentifier');
      return false;
    }
  }

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

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

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

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

  VersionedTextDocumentIdentifier({
    required this.version,
    required this.uri,
  });
  static VersionedTextDocumentIdentifier fromJson(Map<String, Object?> json) {
    final versionJson = json['version'];
    final version = versionJson as int;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return VersionedTextDocumentIdentifier(
      version: version,
      uri: uri,
    );
  }

  /// 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['version'] = version;
    __result['uri'] = uri;
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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 VersionedTextDocumentIdentifier');
      return false;
    }
  }

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

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

  @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.textDocument,
    required this.reason,
  });
  static WillSaveTextDocumentParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final reasonJson = json['reason'];
    final reason = TextDocumentSaveReason.fromJson(reasonJson as int);
    return WillSaveTextDocumentParams(
      textDocument: textDocument,
      reason: reason,
    );
  }

  /// The 'TextDocumentSaveReason'.
  final TextDocumentSaveReason reason;

  /// The document that will be saved.
  final TextDocumentIdentifier textDocument;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['textDocument'] = textDocument.toJson();
    __result['reason'] = reason.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();
      }
      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();
      }
      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 textDocument == other.textDocument &&
          reason == other.reason &&
          true;
    }
    return false;
  }

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

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

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

  WorkDoneProgressBegin({
    this.kind = 'begin',
    required this.title,
    this.cancellable,
    this.message,
    this.percentage,
  }) {
    if (kind != 'begin') {
      throw 'kind may only be the literal \'begin\'';
    }
  }
  static WorkDoneProgressBegin fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final titleJson = json['title'];
    final title = titleJson as String;
    final cancellableJson = json['cancellable'];
    final cancellable = cancellableJson as bool?;
    final messageJson = json['message'];
    final message = messageJson as String?;
    final percentageJson = json['percentage'];
    final percentage = percentageJson as int?;
    return WorkDoneProgressBegin(
      kind: kind,
      title: title,
      cancellable: cancellable,
      message: message,
      percentage: percentage,
    );
  }

  /// 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?>{};
    __result['kind'] = kind;
    __result['title'] = title;
    if (cancellable != null) {
      __result['cancellable'] = cancellable;
    }
    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('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('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();
      }
      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('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 WorkDoneProgressBegin');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkDoneProgressBegin &&
        other.runtimeType == WorkDoneProgressBegin) {
      return kind == other.kind &&
          title == other.title &&
          cancellable == other.cancellable &&
          message == other.message &&
          percentage == other.percentage &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        title,
        cancellable,
        message,
        percentage,
      );

  @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.kind = 'report',
    this.cancellable,
    this.message,
    this.percentage,
  }) {
    if (kind != 'report') {
      throw 'kind may only be the literal \'report\'';
    }
  }
  static WorkDoneProgressReport fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final cancellableJson = json['cancellable'];
    final cancellable = cancellableJson as bool?;
    final messageJson = json['message'];
    final message = messageJson as String?;
    final percentageJson = json['percentage'];
    final percentage = percentageJson as int?;
    return WorkDoneProgressReport(
      kind: kind,
      cancellable: cancellable,
      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?>{};
    __result['kind'] = kind;
    if (cancellable != null) {
      __result['cancellable'] = cancellable;
    }
    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('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('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('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 kind == other.kind &&
          cancellable == other.cancellable &&
          message == other.message &&
          percentage == other.percentage &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        cancellable,
        message,
        percentage,
      );

  @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,
    required this.previousResultIds,
    this.workDoneToken,
    this.partialResultToken,
  });
  static WorkspaceDiagnosticParams fromJson(Map<String, Object?> json) {
    final identifierJson = json['identifier'];
    final identifier = identifierJson as 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)''')));
    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 WorkspaceDiagnosticParams(
      identifier: identifier,
      previousResultIds: previousResultIds,
      workDoneToken: workDoneToken,
      partialResultToken: partialResultToken,
    );
  }

  /// 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;
    }
    __result['previousResultIds'] =
        previousResultIds.map((item) => item.toJson()).toList();
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    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('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();
      }
      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 WorkspaceDiagnosticParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceDiagnosticParams &&
        other.runtimeType == WorkspaceDiagnosticParams) {
      return identifier == other.identifier &&
          listEqual(previousResultIds, other.previousResultIds,
              (PreviousResultId a, PreviousResultId b) => a == b) &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

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

  @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.changes,
    this.documentChanges,
    this.changeAnnotations,
  });
  static WorkspaceEdit fromJson(Map<String, Object?> json) {
    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) =>
                    TextDocumentEdit.canParse(item, nullLspJsonReporter))))
            ? Either2<List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>.t1((documentChangesJson)
                .map((item) =>
                    TextDocumentEdit.fromJson(item as Map<String, Object?>))
                .toList())
            : ((documentChangesJson is List<Object?> &&
                    (documentChangesJson.every((item) =>
                        (TextDocumentEdit.canParse(item, nullLspJsonReporter) ||
                            CreateFile.canParse(item, nullLspJsonReporter) ||
                            RenameFile.canParse(item, nullLspJsonReporter) ||
                            DeleteFile.canParse(item, nullLspJsonReporter)))))
                ? Either2<List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>.t2(
                    (documentChangesJson).map((item) => TextDocumentEdit.canParse(item, nullLspJsonReporter) ? Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t1(TextDocumentEdit.fromJson(item as Map<String, Object?>)) : (CreateFile.canParse(item, nullLspJsonReporter) ? Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t2(CreateFile.fromJson(item as Map<String, Object?>)) : (RenameFile.canParse(item, nullLspJsonReporter) ? Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t3(RenameFile.fromJson(item as Map<String, Object?>)) : (DeleteFile.canParse(item, nullLspJsonReporter) ? Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t4(DeleteFile.fromJson(item as Map<String, Object?>)) : (throw '''$item was not one of (TextDocumentEdit, CreateFile, RenameFile, DeleteFile)'''))))).toList())
                : (throw '''$documentChangesJson was not one of (List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>)''')));
    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?>)));
    return WorkspaceEdit(
      changes: changes,
      documentChanges: documentChanges,
      changeAnnotations: changeAnnotations,
    );
  }

  /// 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<TextDocumentEdit>,
          List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>?
      documentChanges;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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) =>
                        TextDocumentEdit.canParse(item, reporter)))) ||
                (documentChanges is List<Object?> &&
                    (documentChanges.every((item) =>
                        (TextDocumentEdit.canParse(item, reporter) ||
                            CreateFile.canParse(item, reporter) ||
                            RenameFile.canParse(item, reporter) ||
                            DeleteFile.canParse(item, reporter)))))))) {
          reporter.reportError(
              'must be of type Either2<List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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();
      }
      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(
              changes,
              other.changes,
              (List<TextEdit> a, List<TextEdit> b) =>
                  listEqual(a, b, (TextEdit a, TextEdit b) => a == b)) &&
          documentChanges == other.documentChanges &&
          mapEqual(changeAnnotations, other.changeAnnotations,
              (ChangeAnnotation a, ChangeAnnotation b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(changes),
        documentChanges,
        lspHashCode(changeAnnotations),
      );

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

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

  WorkspaceEditClientCapabilities({
    this.documentChanges,
    this.resourceOperations,
    this.failureHandling,
    this.normalizesLineEndings,
    this.changeAnnotationSupport,
  });
  static WorkspaceEditClientCapabilities fromJson(Map<String, Object?> json) {
    final documentChangesJson = json['documentChanges'];
    final documentChanges = documentChangesJson as bool?;
    final resourceOperationsJson = json['resourceOperations'];
    final resourceOperations = (resourceOperationsJson as List<Object?>?)
        ?.map((item) => ResourceOperationKind.fromJson(item as String))
        .toList();
    final failureHandlingJson = json['failureHandling'];
    final failureHandling = failureHandlingJson != null
        ? FailureHandlingKind.fromJson(failureHandlingJson as String)
        : null;
    final normalizesLineEndingsJson = json['normalizesLineEndings'];
    final normalizesLineEndings = normalizesLineEndingsJson as bool?;
    final changeAnnotationSupportJson = json['changeAnnotationSupport'];
    final changeAnnotationSupport = changeAnnotationSupportJson != null
        ? WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson(
            changeAnnotationSupportJson as Map<String, Object?>)
        : null;
    return WorkspaceEditClientCapabilities(
      documentChanges: documentChanges,
      resourceOperations: resourceOperations,
      failureHandling: failureHandling,
      normalizesLineEndings: normalizesLineEndings,
      changeAnnotationSupport: changeAnnotationSupport,
    );
  }

  /// 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 (documentChanges != null) {
      __result['documentChanges'] = documentChanges;
    }
    if (resourceOperations != null) {
      __result['resourceOperations'] =
          resourceOperations?.map((item) => item.toJson()).toList();
    }
    if (failureHandling != null) {
      __result['failureHandling'] = failureHandling?.toJson();
    }
    if (normalizesLineEndings != null) {
      __result['normalizesLineEndings'] = normalizesLineEndings;
    }
    if (changeAnnotationSupport != null) {
      __result['changeAnnotationSupport'] = changeAnnotationSupport?.toJson();
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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('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();
      }
      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('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();
      }
      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 documentChanges == other.documentChanges &&
          listEqual(resourceOperations, other.resourceOperations,
              (ResourceOperationKind a, ResourceOperationKind b) => a == b) &&
          failureHandling == other.failureHandling &&
          normalizesLineEndings == other.normalizesLineEndings &&
          changeAnnotationSupport == other.changeAnnotationSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        documentChanges,
        lspHashCode(resourceOperations),
        failureHandling,
        normalizesLineEndings,
        changeAnnotationSupport,
      );

  @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.uri,
    required this.name,
  });
  static WorkspaceFolder fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final nameJson = json['name'];
    final name = nameJson as String;
    return WorkspaceFolder(
      uri: uri,
      name: name,
    );
  }

  /// 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['uri'] = uri;
    __result['name'] = name;
    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('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();
      }
      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 uri == other.uri && name == other.name && true;
    }
    return false;
  }

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

  @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.supported,
    this.changeNotifications,
  });
  static WorkspaceFoldersServerCapabilities fromJson(
      Map<String, Object?> json) {
    final supportedJson = json['supported'];
    final supported = supportedJson as bool?;
    final changeNotificationsJson = json['changeNotifications'];
    final changeNotifications = changeNotificationsJson == null
        ? null
        : (changeNotificationsJson is String
            ? Either2<String, bool>.t1(changeNotificationsJson)
            : (changeNotificationsJson is bool
                ? Either2<String, bool>.t2(changeNotificationsJson)
                : (throw '''$changeNotificationsJson was not one of (String, bool)''')));
    return WorkspaceFoldersServerCapabilities(
      supported: supported,
      changeNotifications: changeNotifications,
    );
  }

  /// 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<String, bool>? changeNotifications;

  /// The server has support for workspace folders
  final bool? supported;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      reporter.push('changeNotifications');
      try {
        final changeNotifications = obj['changeNotifications'];
        if (changeNotifications != null &&
            !((changeNotifications is String || changeNotifications is bool))) {
          reporter.reportError('must be of type Either2<String, 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 supported == other.supported &&
          changeNotifications == other.changeNotifications &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        supported,
        changeNotifications,
      );

  @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.uri,
    this.version,
    this.kind = 'full',
    this.resultId,
    required this.items,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static WorkspaceFullDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    return WorkspaceFullDocumentDiagnosticReport(
      uri: uri,
      version: version,
      kind: kind,
      resultId: resultId,
      items: items,
    );
  }

  /// 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['uri'] = uri;
    __result['version'] = version;
    __result['kind'] = kind;
    if (resultId != null) {
      __result['resultId'] = resultId;
    }
    __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('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();
      }
      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('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();
      }
      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 uri == other.uri &&
          version == other.version &&
          kind == other.kind &&
          resultId == other.resultId &&
          listEqual(
              items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
          true;
    }
    return false;
  }

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

  @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({
    required this.name,
    required this.kind,
    this.tags,
    required this.location,
    this.containerName,
  });
  static WorkspaceSymbol fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    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 containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    return WorkspaceSymbol(
      name: name,
      kind: kind,
      tags: tags,
      location: location,
      containerName: containerName,
    );
  }

  /// 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?>{};
    __result['name'] = name;
    __result['kind'] = kind.toJson();
    if (tags != null) {
      __result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    __result['location'] = location;
    if (containerName != null) {
      __result['containerName'] = containerName;
    }
    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('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('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('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('containerName');
      try {
        final containerName = obj['containerName'];
        if (containerName != null && !(containerName is String)) {
          reporter.reportError('must be of type String');
          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 name == other.name &&
          kind == other.kind &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          location == other.location &&
          containerName == other.containerName &&
          true;
    }
    return false;
  }

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

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

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

  WorkspaceSymbolClientCapabilities({
    this.dynamicRegistration,
    this.symbolKind,
    this.tagSupport,
    this.resolveSupport,
  });
  static WorkspaceSymbolClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    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;
    final resolveSupportJson = json['resolveSupport'];
    final resolveSupport = resolveSupportJson != null
        ? WorkspaceSymbolClientCapabilitiesResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    return WorkspaceSymbolClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      symbolKind: symbolKind,
      tagSupport: tagSupport,
      resolveSupport: resolveSupport,
    );
  }

  /// 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 (symbolKind != null) {
      __result['symbolKind'] = symbolKind?.toJson();
    }
    if (tagSupport != null) {
      __result['tagSupport'] = tagSupport?.toJson();
    }
    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('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();
      }
      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();
      }
      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 &&
          symbolKind == other.symbolKind &&
          tagSupport == other.tagSupport &&
          resolveSupport == other.resolveSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        symbolKind,
        tagSupport,
        resolveSupport,
      );

  @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({
    required this.query,
    this.workDoneToken,
    this.partialResultToken,
  });
  static WorkspaceSymbolParams fromJson(Map<String, Object?> json) {
    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)''')));
    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 WorkspaceSymbolParams(
      query: query,
      workDoneToken: workDoneToken,
      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;

  /// 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?>{};
    __result['query'] = query;
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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();
      }
      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 WorkspaceSymbolParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolParams &&
        other.runtimeType == WorkspaceSymbolParams) {
      return query == other.query &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

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

  @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({
    required this.uri,
    this.version,
    this.kind = 'unchanged',
    required this.resultId,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static WorkspaceUnchangedDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    return WorkspaceUnchangedDocumentDiagnosticReport(
      uri: uri,
      version: version,
      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;

  /// 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['uri'] = uri;
    __result['version'] = version;
    __result['kind'] = kind;
    __result['resultId'] = resultId;
    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();
      }
      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 WorkspaceUnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceUnchangedDocumentDiagnosticReport &&
        other.runtimeType == WorkspaceUnchangedDocumentDiagnosticReport) {
      return uri == other.uri &&
          version == other.version &&
          kind == other.kind &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

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

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