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

  ApplyWorkspaceEditResponse(
      {required this.applied, this.failureReason, this.failedChange});
  static ApplyWorkspaceEditResponse 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 ApplyWorkspaceEditResponse(
        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 `failureHandlingStrategy` in its client
  /// capabilities.
  final int? failedChange;

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

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

  @override
  bool operator ==(Object other) {
    if (other is ApplyWorkspaceEditResponse &&
        other.runtimeType == ApplyWorkspaceEditResponse) {
      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 &&
            (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 num))
        .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 &&
                (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 &&
            (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 &&
                (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.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 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,
        window: window,
        general: general,
        experimental: experimental);
  }

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

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

  /// 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 (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('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 &&
          window == other.window &&
          general == other.general &&
          experimental == other.experimental &&
          true;
    }
    return false;
  }

  @override
  int get hashCode =>
      Object.hash(workspace, textDocument, 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.regularExpressions, this.markdown});
  static ClientCapabilitiesGeneral fromJson(Map<String, Object?> json) {
    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;
    return ClientCapabilitiesGeneral(
        regularExpressions: regularExpressions, markdown: markdown);
  }

  /// Client capabilities specific to the client's markdown parser.
  ///  @since 3.16.0
  final MarkdownClientCapabilities? markdown;

  /// Client capabilities specific to regular expressions.
  ///  @since 3.16.0
  final RegularExpressionsClientCapabilities? regularExpressions;

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

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

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

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

  /// Whether client supports handling progress notifications. If set servers
  /// are allowed to report in `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});
  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;
    return ClientCapabilitiesWorkspace(
        applyEdit: applyEdit,
        workspaceEdit: workspaceEdit,
        didChangeConfiguration: didChangeConfiguration,
        didChangeWatchedFiles: didChangeWatchedFiles,
        symbol: symbol,
        executeCommand: executeCommand,
        workspaceFolders: workspaceFolders,
        configuration: configuration,
        semanticTokens: semanticTokens,
        codeLens: codeLens,
        fileOperations: fileOperations);
  }

  /// The client supports applying batch edits to the workspace by supporting
  /// the request 'workspace/applyEdit'
  final bool? applyEdit;

  /// Capabilities specific to the code lens requests scoped to the workspace.
  ///  @since 3.16.0
  final CodeLensWorkspaceClientCapabilities? codeLens;

  /// The client supports `workspace/configuration` requests.
  ///  @since 3.6.0
  final bool? configuration;

  /// Capabilities specific to the `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;

  /// 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();
    }
    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();
      }
      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 &&
          true;
    }
    return false;
  }

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

  @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 &&
                (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 th 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 &&
            (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 &&
            (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});
  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();
    return CodeActionContext(diagnostics: diagnostics, only: only);
  }

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

  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();
    }
    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 &&
            (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 &&
                (only.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 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) &&
          true;
    }
    return false;
  }

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

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

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

/// 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 &&
                (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 &&
                (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 && (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});
  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?;
    return CompletionClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        completionItem: completionItem,
        completionItemKind: completionItemKind,
        contextSupport: contextSupport);
  }

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

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

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

  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;
    }
    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();
      }
      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 &&
          true;
    }
    return false;
  }

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

  @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});
  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;
    return CompletionClientCapabilitiesCompletionItem(
        snippetSupport: snippetSupport,
        commitCharactersSupport: commitCharactersSupport,
        documentationFormat: documentationFormat,
        deprecatedSupport: deprecatedSupport,
        preselectSupport: preselectSupport,
        tagSupport: tagSupport,
        insertReplaceSupport: insertReplaceSupport,
        resolveSupport: resolveSupport,
        insertTextModeSupport: insertTextModeSupport);
  }

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

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

  /// Indicates which properties a client can resolve lazily on a completion
  /// item. Before version 3.16.0 only the predefined properties `documentation`
  /// and `details` could be resolved lazily.
  ///  @since 3.16.0
  final 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();
    }
    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 &&
                (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();
      }
      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 &&
          true;
    }
    return false;
  }

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

  @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 &&
                (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 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 num))
        .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 &&
            (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 &&
            (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 &&
            (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 num);
    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.kind,
      this.tags,
      this.detail,
      this.documentation,
      this.deprecated,
      this.preselect,
      this.sortText,
      this.filterText,
      this.insertText,
      this.insertTextFormat,
      this.insertTextMode,
      this.textEdit,
      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 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 num)
        : 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 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,
        kind: kind,
        tags: tags,
        detail: detail,
        documentation: documentation,
        deprecated: deprecated,
        preselect: preselect,
        sortText: sortText,
        filterText: filterText,
        insertText: insertText,
        insertTextFormat: insertTextFormat,
        insertTextMode: insertTextMode,
        textEdit: textEdit,
        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.
  final String? filterText;

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

  /// The format of the insert text. The format applies to both the `insertText`
  /// property and the `newText` property of a provided `textEdit`. If omitted
  /// defaults to `InsertTextFormat.PlainText`.
  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
  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. By default also the text that is
  /// inserted when selecting this completion.
  final String label;

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

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

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

  /// An edit which is applied to a document when selecting this completion.
  /// When an edit is provided the value of `insertText` is ignored.
  ///
  /// *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 `InsertReplaceEdits` via the
  /// `textDocument.completion.insertReplaceSupport` client capability property.
  ///
  /// *Note 1:* The text edit's range as well as both ranges from an insert
  /// replace edit must be a [single line] and they must contain the position at
  /// which completion has been requested.
  /// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range
  /// must be a prefix of the edit's replace range, that means it must be
  /// contained and starting at the same position.
  ///  @since 3.16.0 additional type `InsertReplaceEdit`
  final Either2<TextEdit, InsertReplaceEdit>? textEdit;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['label'] = label;
    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 (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('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 &&
                (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('additionalTextEdits');
      try {
        final additionalTextEdits = obj['additionalTextEdits'];
        if (additionalTextEdits != null &&
            !((additionalTextEdits is List &&
                (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 &&
                (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 &&
          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 &&
          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,
      kind,
      lspHashCode(tags),
      detail,
      documentation,
      deprecated,
      preselect,
      sortText,
      filterText,
      insertText,
      insertTextFormat,
      insertTextMode,
      textEdit,
      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;
}

/// 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, required this.items});
  static CompletionList fromJson(Map<String, Object?> json) {
    final isIncompleteJson = json['isIncomplete'];
    final isIncomplete = isIncompleteJson as bool;
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => CompletionItem.fromJson(item as Map<String, Object?>))
        .toList();
    return CompletionList(isIncomplete: isIncomplete, items: items);
  }

  /// This list it not complete. Further typing should result in recomputing
  /// this list.
  final bool isIncomplete;

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

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['isIncomplete'] = isIncomplete;
    __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('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 &&
            (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 &&
          listEqual(items, other.items,
              (CompletionItem a, CompletionItem b) => a == b) &&
          true;
    }
    return false;
  }

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

  @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.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 workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CompletionOptions(
        triggerCharacters: triggerCharacters,
        allCommitCharacters: allCommitCharacters,
        resolveProvider: resolveProvider,
        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 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 (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 &&
                (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 &&
                (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('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 &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

  @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.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 workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return CompletionRegistrationOptions(
        documentSelector: documentSelector,
        triggerCharacters: triggerCharacters,
        allCommitCharacters: allCommitCharacters,
        resolveProvider: resolveProvider,
        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;

  /// 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 (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 &&
                (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 &&
                (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 &&
                (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('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 &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

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

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

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

  final num _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 &&
            (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 identifer 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 &&
            (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 &&
                (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 &&
                (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 identifer 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 &&
            (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 num)
        : 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 num))
        .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 &&
                (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 &&
                (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());
}

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

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

  final num _value;

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

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

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

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

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

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 &&
            (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});
  static DidChangeWatchedFilesClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DidChangeWatchedFilesClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

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

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

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

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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

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

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

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 conditions (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 &&
                (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 &&
                (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 &&
                (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 &&
                (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 TextDocumentPositionParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      DocumentOnTypeFormattingParams.canParse,
      DocumentOnTypeFormattingParams.fromJson);

  DocumentOnTypeFormattingParams(
      {required this.ch,
      required this.options,
      required this.textDocument,
      required this.position});
  static DocumentOnTypeFormattingParams fromJson(Map<String, Object?> json) {
    final chJson = json['ch'];
    final ch = chJson as String;
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final 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 DocumentOnTypeFormattingParams(
        ch: ch,
        options: options,
        textDocument: textDocument,
        position: position);
  }

  /// The character that has been typed.
  final String ch;

  /// The format options.
  final FormattingOptions options;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

  Map<String, Object?> toJson() {
    var __result = <String, Object?>{};
    __result['ch'] = ch;
    __result['options'] = options.toJson();
    __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('ch');
      try {
        if (!obj.containsKey('ch')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final ch = obj['ch'];
        if (ch == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(ch is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        if (!obj.containsKey('options')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final options = obj['options'];
        if (options == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(FormattingOptions.canParse(options, reporter))) {
          reporter.reportError('must be of type FormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('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 DocumentOnTypeFormattingParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentOnTypeFormattingParams &&
        other.runtimeType == DocumentOnTypeFormattingParams) {
      return ch == other.ch &&
          options == other.options &&
          textDocument == other.textDocument &&
          position == other.position &&
          true;
    }
    return false;
  }

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

  @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 &&
                (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 &&
                (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 &&
                (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 num))
        .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 &&
                (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 &&
                (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 &&
                (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 num))
        .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 &&
            (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 &&
                (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);
  static const ServerNotInitialized = ErrorCodes(-32002);
  static const UnknownErrorCode = ErrorCodes(-32001);

  /// This is the start range of JSON RPC reserved error codes. It doesn't
  /// denote a real error code.
  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);
  static const ContentModified = ErrorCodes(-32801);
  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 &&
            (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 && (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 &&
            (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 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 conditions (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 &&
            (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 as String;
    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.
  ///
  /// 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 conditions (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 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)) {
          reporter.reportError('must be of type String');
          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});
  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;
    return FoldingRange(
        startLine: startLine,
        startCharacter: startCharacter,
        endLine: endLine,
        endCharacter: endCharacter,
        kind: kind);
  }

  /// 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();
    }
    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();
      }
      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 &&
          true;
    }
    return false;
  }

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

  @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});
  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?;
    return FoldingRangeClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        rangeLimit: rangeLimit,
        lineFoldingOnly: lineFoldingOnly);
  }

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

  /// 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;
    }
    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();
      }
      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 &&
          true;
    }
    return false;
  }

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

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

/// Enum of known 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 &&
                (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());
}

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

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', 'message', 'verbose'}.contains(traceJson)
        ? traceJson as String?
        : throw '''$traceJson was not one of (null, 'off', 'message', '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 == 'message' || trace == 'verbose'))) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceFolders');
      try {
        final workspaceFolders = obj['workspaceFolders'];
        if (workspaceFolders != null &&
            !((workspaceFolders is List &&
                (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());
}

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

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

  /// 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 &&
                (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 &&
            (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
  /// `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});
  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?;
    return MarkdownClientCapabilities(parser: parser, version: version);
  }

  /// 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;
    }
    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();
      }
      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 && true;
    }
    return false;
  }

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

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

/// A `MarkupContent` literal represents a string value which content is
/// interpreted base on its kind flag. Currently the protocol supports
/// `plaintext` and `markdown` as markup kinds.
///
/// If the kind is `markdown` then the value can contain fenced code blocks like
/// in GitHub issues.
///
/// Here is an example how such a string can be constructed using JavaScript /
/// TypeScript: ```typescript let markdown: MarkdownContent = {
///
/// kind: MarkupKind.Markdown,
/// 	value: [
/// 		'# Header',
/// 		'Some text',
/// 		'```typescript',
/// 		'someCode();',
/// 		'```'
/// 	].join('\n') }; ```
///
/// *Please Note* that clients might sanitize the return markdown. A client
/// could decide to remove HTML from the markdown to avoid script execution.
class MarkupContent implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(MarkupContent.canParse, MarkupContent.fromJson);

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

  /// The type of the Markup
  final MarkupKind kind;

  /// The content itself
  final String value;

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

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

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

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

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

/// Describes the content type that a client supports in various result literals
/// like `Hover`, `ParameterInfo` or `CompletionItem`.
///
/// Please note that `MarkupKinds` must not start with a `$`. This kinds are
/// reserved for internal usage.
class MarkupKind {
  const MarkupKind._(this._value);
  const MarkupKind.fromJson(this._value);

  final String _value;

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

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

  final String jsonrpc;

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

  @override
  int get hashCode => jsonrpc.hashCode;

  @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 'shutdown' method.
  static const shutdown = Method('shutdown');

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

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

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

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

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

  /// Constant for the 'workspace/configuration' method.
  static const workspace_configuration = Method('workspace/configuration');

  /// Constant for the 'workspace/didChangeWatchedFiles' method.
  static const workspace_didChangeWatchedFiles =
      Method('workspace/didChangeWatchedFiles');

  /// Constant for the 'workspace/symbol' method.
  static const workspace_symbol = Method('workspace/symbol');

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

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

  /// Constant for the 'textDocument/signatureHelp' method.
  static const textDocument_signatureHelp =
      Method('textDocument/signatureHelp');

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

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

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

  /// Constant for the 'textDocument/moniker' method.
  static const textDocument_moniker = Method('textDocument/moniker');

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

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

  NotificationMessage(
      {required this.method, this.params, required this.jsonrpc});
  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;
    return NotificationMessage(
        method: method, params: params, jsonrpc: jsonrpc);
  }

  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;
    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();
      }
      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 &&
          true;
    }
    return false;
  }

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

  @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 (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (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 (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.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);
    }
    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). Assuming that the
  /// line is represented as a string, the `character` value represents the gap
  /// between the `character` and `character + 1`.
  ///
  /// 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());
}

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 num _value;

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

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

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 num))
        .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 &&
            (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 &&
            (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 &&
                (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 &&
            (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());
}

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 num)
            : 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 identifer 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 &&
            (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 &&
                (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});
  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;
    return RequestMessage(
        id: id, method: method, params: params, jsonrpc: jsonrpc);
  }

  /// 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;
    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();
      }
      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 &&
          true;
    }
    return false;
  }

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

  @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});
  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;
    return ResponseMessage(
        id: id, result: result, error: error, jsonrpc: jsonrpc);
  }

  /// 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 (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();
      }
      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 &&
          true;
    }
    return false;
  }

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

  @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 &&
            (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 &&
                (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 && (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});
  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?;
    return SemanticTokensClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        requests: requests,
        tokenTypes: tokenTypes,
        tokenModifiers: tokenModifiers,
        formats: formats,
        overlappingTokenSupport: overlappingTokenSupport,
        multilineTokenSupport: multilineTokenSupport);
  }

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

  /// 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;
    }
    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 &&
            (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 &&
            (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 &&
            (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();
      }
      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 &&
          true;
    }
    return false;
  }

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

  @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 &&
            (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 &&
            (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 && (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 &&
            (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 &&
            (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 && (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 &&
                (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.textDocumentSync,
      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.workspaceSymbolProvider,
      this.workspace,
      this.experimental});
  static ServerCapabilities fromJson(Map<String, Object?> json) {
    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 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 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(
        textDocumentSync: textDocumentSync,
        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,
        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 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 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;

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

  /// 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 (textDocumentSync != null) {
      __result['textDocumentSync'] = textDocumentSync;
    }
    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 (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('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('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('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 textDocumentSync == other.textDocumentSync &&
          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 &&
          workspaceSymbolProvider == other.workspaceSymbolProvider &&
          workspace == other.workspace &&
          experimental == other.experimental &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll([
        textDocumentSync,
        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,
        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', 'message', 'verbose'}.contains(valueJson)
        ? valueJson as String
        : throw '''$valueJson was not one of ('off', 'message', '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 == 'message' || value == 'verbose'))) {
          reporter.reportError('must be of type String');
          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 &&
                (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 &&
            (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 &&
                (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 num);
    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 &&
                (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 &&
                (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 &&
                (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 &&
                (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 &&
                (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 num _value;

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

  /// 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 &&
                (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 (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 (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.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.
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 num))
        .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 completion item.
  ///  @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 &&
                (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 num _value;

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

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

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

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

  @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 &&
            (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 (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.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 (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (DocumentOnTypeFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingParams.fromJson(json);
    }
    if (RenameParams.canParse(json, nullLspJsonReporter)) {
      return RenameParams.fromJson(json);
    }
    if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
      return PrepareRenameParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.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 (CompletionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionRegistrationOptions.fromJson(json);
    }
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.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 (DocumentHighlightRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentHighlightRegistrationOptions.fromJson(json);
    }
    if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolRegistrationOptions.fromJson(json);
    }
    if (CodeActionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionRegistrationOptions.fromJson(json);
    }
    if (CodeLensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensRegistrationOptions.fromJson(json);
    }
    if (DocumentLinkRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkRegistrationOptions.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 (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.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 &&
                (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 &&
                (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 &&
                (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());
}

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

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 (WorkspaceSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolOptions.fromJson(json);
    }
    if (ExecuteCommandOptions.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandOptions.fromJson(json);
    }
    if (CompletionOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionOptions.fromJson(json);
    }
    if (HoverOptions.canParse(json, nullLspJsonReporter)) {
      return HoverOptions.fromJson(json);
    }
    if (SignatureHelpOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpOptions.fromJson(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 (DocumentHighlightOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightOptions.fromJson(json);
    }
    if (DocumentSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolOptions.fromJson(json);
    }
    if (CodeActionOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionOptions.fromJson(json);
    }
    if (CodeLensOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensOptions.fromJson(json);
    }
    if (DocumentLinkOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkOptions.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 (FoldingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeOptions.fromJson(json);
    }
    if (SelectionRangeOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeOptions.fromJson(json);
    }
    if (CallHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOptions.fromJson(json);
    }
    if (SemanticTokensOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensOptions.fromJson(json);
    }
    if (LinkedEditingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeOptions.fromJson(json);
    }
    if (MonikerOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerOptions.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 (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (ExecuteCommandParams.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.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 (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.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 (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.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 (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 (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.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 `WorkDoneProgressStart` 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());
}

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 &&
                (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 &&
                    (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 &&
                        (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 &&
                    (documentChanges.every((item) =>
                        TextDocumentEdit.canParse(item, reporter)))) ||
                (documentChanges is List &&
                    (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 &&
                (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 &&
            (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 &&
            (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());
}

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

  WorkspaceSymbolClientCapabilities(
      {this.dynamicRegistration, this.symbolKind, this.tagSupport});
  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;
    return WorkspaceSymbolClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        symbolKind: symbolKind,
        tagSupport: tagSupport);
  }

  /// Symbol request supports dynamic registration.
  final bool? dynamicRegistration;

  /// Specific capabilities for the `SymbolKind` in the `workspace/symbol`
  /// request.
  final WorkspaceSymbolClientCapabilitiesSymbolKind? symbolKind;

  /// The client supports tags on `SymbolInformation`. Clients supporting tags
  /// have to handle unknown tags gracefully.
  ///  @since 3.16.0
  final WorkspaceSymbolClientCapabilitiesTagSupport? tagSupport;

  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();
    }
    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();
      }
      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 &&
          true;
    }
    return false;
  }

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

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

  WorkspaceSymbolOptions({this.workDoneProgress});
  static WorkspaceSymbolOptions fromJson(Map<String, Object?> json) {
    if (WorkspaceSymbolRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceSymbolRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkspaceSymbolOptions(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 WorkspaceSymbolOptions');
      return false;
    }
  }

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

  @override
  int get hashCode => workDoneProgress.hashCode;

  @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.workDoneProgress});
  static WorkspaceSymbolRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkspaceSymbolRegistrationOptions(
        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 WorkspaceSymbolRegistrationOptions');
      return false;
    }
  }

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

  @override
  int get hashCode => workDoneProgress.hashCode;

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