// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// This file has been automatically generated. Please do not edit it manually.
// To regenerate the file, use the script
// "pkg/analysis_server/tool/lsp_spec/generate_all.dart".

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

const jsonEncoder = JsonEncoder.withIndent('    ');

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

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

  /// The actual annotation identifier.
  final String annotationId;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    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;

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

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

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyIncomingCallsParams.canParse,
    CallHierarchyIncomingCallsParams.fromJson,
  );

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

  final CallHierarchyItem item;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  final bool? workDoneProgress;

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

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

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

  @override
  int get hashCode => workDoneProgress.hashCode;

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

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

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

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

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

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

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

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

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

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

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

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

  final CallHierarchyItem item;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  int get hashCode => id.hashCode;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// The client supports code action literals as a valid response of the
  /// `textDocument/codeAction` request.
  ///  @since 3.8.0
  final CodeActionClientCapabilitiesCodeActionLiteralSupport?
      codeActionLiteralSupport;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    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;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    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 implements ToJsonable {
  const CodeActionKind(this._value);
  const CodeActionKind.fromJson(this._value);

  final String _value;

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

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

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

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

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

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

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

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

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    if (other is CodeActionLiteralSupportCodeActionKind &&
        other.runtimeType == CodeActionLiteralSupportCodeActionKind) {
      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 CodeActionOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionOptions.canParse,
    CodeActionOptions.fromJson,
  );

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionParams.canParse,
    CodeActionParams.fromJson,
  );

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  final int _value;

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

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

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

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

  @override
  int get hashCode => href.hashCode;

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

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

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

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

  /// A data entry field that is preserved on a code lens item between a code
  /// lens and a code lens resolve request.
  final Object? data;

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

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

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

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

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    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;
  @override
  final bool? workDoneProgress;

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

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

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensParams.canParse,
    CodeLensParams.fromJson,
  );

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    if (other is CodeLensRegistrationOptions &&
        other.runtimeType == CodeLensRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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;

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

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

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

  @override
  int get hashCode => refreshSupport.hashCode;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// The color 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.
  @override
  final Either2<int, String>? partialResultToken;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// Client supports the 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 CompletionItemInsertTextModeSupport? insertTextModeSupport;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// The kind of this completion item. Based of the kind an icon is chosen by
  /// the editor. The standardized set of available values is defined in
  /// `CompletionItemKind`.
  final CompletionItemKind? kind;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  final Range insert;
  final Range replace;

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

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

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

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

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

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

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

  final List<InsertTextMode> valueSet;

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

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

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

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

  final int _value;

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  final int _value;

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  int get hashCode => labelDetailsSupport.hashCode;

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

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

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

  /// The completion context. This is only available 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.
  @override
  final Either2<int, String>? partialResultToken;

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

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

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

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

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

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

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

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

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

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

  /// The list of all possible characters that commit a completion. This field
  /// can be used if clients don't support individual commit characters per
  /// completion item. See 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
  @override
  final List<String>? allCommitCharacters;

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

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

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

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

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

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

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

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

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

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

  final int _value;

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

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

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    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;

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

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

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

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

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

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

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

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

  /// A create
  final String kind;

  /// Additional options
  final CreateFileOptions? options;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    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;

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

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

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

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

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

  @override
  bool operator ==(Object other) {
    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
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DeclarationParams.canParse,
    DeclarationParams.fromJson,
  );

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

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

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

  @override
  bool operator ==(Object other) {
    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
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DefinitionParams.canParse,
    DefinitionParams.fromJson,
  );

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// A delete
  final String kind;

  /// Delete options.
  final DeleteFileOptions? options;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// An optional property to describe the error code.
  ///  @since 3.16.0
  final CodeDescription? codeDescription;

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

  /// The diagnostic's message.
  final String message;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  final bool retriggerRequest;

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

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

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

  @override
  int get hashCode => retriggerRequest.hashCode;

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

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

  final int _value;

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

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

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

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  final int _value;

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

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

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

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

  @override
  int get hashCode => refreshSupport.hashCode;

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

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

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

  /// Did change configuration notification supports dynamic registration.
  final bool? dynamicRegistration;

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

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

  @override
  bool operator ==(Object other) {
    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;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError('must be of type DidChangeConfigurationParams');
      return false;
    }
  }

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

  @override
  int get hashCode => settings.hashCode;

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

/// The params sent in a change notebook document notification.
///  @since 3.17.0
class DidChangeNotebookDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeNotebookDocumentParams.canParse,
    DidChangeNotebookDocumentParams.fromJson,
  );

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

  /// The actual changes to the notebook document.
  ///
  /// The change describes single state change to the notebook document. So it
  /// moves a notebook document, its cells and its cell text document contents
  /// from state S to S'.
  ///
  /// To mirror the content of a notebook using change events use the following
  /// approach:
  /// - start with the same initial content
  /// - apply the 'notebookDocument/didChange' notifications in the order
  ///   you receive them.
  final NotebookDocumentChangeEvent change;

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

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

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

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

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

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

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

  DidChangeTextDocumentParams({
    required this.contentChanges,
    required this.textDocument,
  });
  static DidChangeTextDocumentParams fromJson(Map<String, Object?> json) {
    final contentChangesJson = json['contentChanges'];
    final contentChanges = (contentChangesJson as List<Object?>)
        .map((item) => TextDocumentContentChangeEvent1.canParse(
                item, nullLspJsonReporter)
            ? Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>.t1(
                TextDocumentContentChangeEvent1.fromJson(
                    item as Map<String, Object?>))
            : (TextDocumentContentChangeEvent2.canParse(item, nullLspJsonReporter)
                ? Either2<TextDocumentContentChangeEvent1,
                        TextDocumentContentChangeEvent2>.t2(
                    TextDocumentContentChangeEvent2.fromJson(item as Map<String, Object?>))
                : (throw '''$item was not one of (TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2)''')))
        .toList();
    final textDocumentJson = json['textDocument'];
    final textDocument = VersionedTextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return DidChangeTextDocumentParams(
      contentChanges: contentChanges,
      textDocument: textDocument,
    );
  }

  /// The actual content changes. The content changes describe single state
  /// changes to the document. So if there are two content changes c1 (at array
  /// index 0) and c2 (at array index 1) for a document in state S then c1 moves
  /// the document from S to S' and c2 from S' to S''. So c1 is computed on the
  /// state S and c2 is computed on the state S'.
  ///
  /// To mirror the content of a document using change events use the following
  /// approach:
  /// - start with the same initial content
  /// - apply the 'textDocument/didChange' notifications in the order you
  ///   receive them.
  /// - apply the `TextDocumentContentChangeEvent`s in a single notification
  ///   in the order you receive them.
  final List<
      Either2<TextDocumentContentChangeEvent1,
          TextDocumentContentChangeEvent2>> contentChanges;

  /// The document that did change. The version number points to the version
  /// after all provided content changes have been applied.
  final VersionedTextDocumentIdentifier textDocument;

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

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

  @override
  bool operator ==(Object other) {
    if (other is DidChangeTextDocumentParams &&
        other.runtimeType == DidChangeTextDocumentParams) {
      return listEqual(
              contentChanges,
              other.contentChanges,
              (Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          a,
                      Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          b) =>
                  a == b) &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

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

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

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

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

  /// Did change watched files notification supports dynamic registration.
  /// Please note that the current protocol doesn't support static configuration
  /// for file changes from the server side.
  final bool? dynamicRegistration;

  /// Whether the client has support for relative patterns or not.
  ///  @since 3.17.0
  final bool? relativePatternSupport;

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

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

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

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

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

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

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

  /// The actual file events.
  final List<FileEvent> changes;

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

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

  @override
  bool operator ==(Object other) {
    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;

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

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

  @override
  bool operator ==(Object other) {
    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;

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

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

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

  @override
  int get hashCode => event.hashCode;

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

/// The params sent in a close notebook document notification.
///  @since 3.17.0
class DidCloseNotebookDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidCloseNotebookDocumentParams.canParse,
    DidCloseNotebookDocumentParams.fromJson,
  );

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

  /// The text documents that represent the content of a notebook cell that got
  /// closed.
  final List<TextDocumentIdentifier> cellTextDocuments;

  /// The notebook document that got closed.
  final NotebookDocumentIdentifier notebookDocument;

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

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

  @override
  bool operator ==(Object other) {
    if (other is DidCloseNotebookDocumentParams &&
        other.runtimeType == DidCloseNotebookDocumentParams) {
      return listEqual(cellTextDocuments, other.cellTextDocuments,
              (TextDocumentIdentifier a, TextDocumentIdentifier b) => a == b) &&
          notebookDocument == other.notebookDocument &&
          true;
    }
    return false;
  }

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

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

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

  DidCloseTextDocumentParams({
    required this.textDocument,
  });
  static DidCloseTextDocumentParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return DidCloseTextDocumentParams(
      textDocument: textDocument,
    );
  }

  /// The document that was closed.
  final TextDocumentIdentifier textDocument;

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

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

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

  @override
  int get hashCode => textDocument.hashCode;

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

/// The params sent in a open notebook document notification.
///  @since 3.17.0
class DidOpenNotebookDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidOpenNotebookDocumentParams.canParse,
    DidOpenNotebookDocumentParams.fromJson,
  );

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

  /// The text documents that represent the content of a notebook cell.
  final List<TextDocumentItem> cellTextDocuments;

  /// The notebook document that got opened.
  final NotebookDocument notebookDocument;

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

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

  @override
  bool operator ==(Object other) {
    if (other is DidOpenNotebookDocumentParams &&
        other.runtimeType == DidOpenNotebookDocumentParams) {
      return listEqual(cellTextDocuments, other.cellTextDocuments,
              (TextDocumentItem a, TextDocumentItem b) => a == b) &&
          notebookDocument == other.notebookDocument &&
          true;
    }
    return false;
  }

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

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

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

  DidOpenTextDocumentParams({
    required this.textDocument,
  });
  static DidOpenTextDocumentParams fromJson(Map<String, Object?> json) {
    final textDocumentJson = json['textDocument'];
    final textDocument =
        TextDocumentItem.fromJson(textDocumentJson as Map<String, Object?>);
    return DidOpenTextDocumentParams(
      textDocument: textDocument,
    );
  }

  /// The document that was opened.
  final TextDocumentItem textDocument;

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

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

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

  @override
  int get hashCode => textDocument.hashCode;

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

/// The params sent in a save notebook document notification.
///  @since 3.17.0
class DidSaveNotebookDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidSaveNotebookDocumentParams.canParse,
    DidSaveNotebookDocumentParams.fromJson,
  );

  DidSaveNotebookDocumentParams({
    required this.notebookDocument,
  });
  static DidSaveNotebookDocumentParams fromJson(Map<String, Object?> json) {
    final notebookDocumentJson = json['notebookDocument'];
    final notebookDocument = NotebookDocumentIdentifier.fromJson(
        notebookDocumentJson as Map<String, Object?>);
    return DidSaveNotebookDocumentParams(
      notebookDocument: notebookDocument,
    );
  }

  /// The notebook document that got saved.
  final NotebookDocumentIdentifier notebookDocument;

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

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

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

  @override
  int get hashCode => notebookDocument.hashCode;

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

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

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

  /// Optional the content when saved. Depends on the includeText value when the
  /// save notification was requested.
  final String? text;

  /// The document that was saved.
  final TextDocumentIdentifier textDocument;

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

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

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

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

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

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

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

  /// Whether document color supports dynamic registration.
  final bool? dynamicRegistration;

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

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

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

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

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

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentColorParams.canParse,
    DocumentColorParams.fromJson,
  );

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

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/// Parameters of the document diagnostic request.
///  @since 3.17.0
class DocumentDiagnosticParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentDiagnosticParams.canParse,
    DocumentDiagnosticParams.fromJson,
  );

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

  /// The additional identifier  provided during registration.
  final String? identifier;

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

  /// The result id of a previous response if provided.
  final String? previousResultId;

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

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

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

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

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

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

/// The document diagnostic report kinds.
///  @since 3.17.0
class DocumentDiagnosticReportKind implements ToJsonable {
  const DocumentDiagnosticReportKind(this._value);
  const DocumentDiagnosticReportKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// A diagnostic report with a full set of problems.
  static const Full = DocumentDiagnosticReportKind('full');

  /// A report indicating that the last returned report is still accurate.
  static const Unchanged = DocumentDiagnosticReportKind('unchanged');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is DocumentDiagnosticReportKind && other._value == _value;
}

/// A partial result for a document diagnostic report.
///  @since 3.17.0
class DocumentDiagnosticReportPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentDiagnosticReportPartialResult.canParse,
    DocumentDiagnosticReportPartialResult.fromJson,
  );

  DocumentDiagnosticReportPartialResult({
    required this.relatedDocuments,
  });
  static DocumentDiagnosticReportPartialResult fromJson(
      Map<String, Object?> json) {
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>).map(
        (key, value) => MapEntry(
            key as String,
            FullDocumentDiagnosticReport.canParse(value, nullLspJsonReporter)
                ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t1(
                    FullDocumentDiagnosticReport.fromJson(
                        value as Map<String, Object?>))
                : (UnchangedDocumentDiagnosticReport.canParse(
                        value, nullLspJsonReporter)
                    ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t2(
                        UnchangedDocumentDiagnosticReport.fromJson(
                            value as Map<String, Object?>))
                    : (throw '''$value was not one of (FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport)'''))));
    return DocumentDiagnosticReportPartialResult(
      relatedDocuments: relatedDocuments,
    );
  }

  final Map<
      String,
      Either2<FullDocumentDiagnosticReport,
          UnchangedDocumentDiagnosticReport>> relatedDocuments;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['relatedDocuments'] = relatedDocuments;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('relatedDocuments');
      try {
        if (!obj.containsKey('relatedDocuments')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final relatedDocuments = obj['relatedDocuments'];
        if (relatedDocuments == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (relatedDocuments is! Map ||
            (relatedDocuments.keys.any((item) =>
                item is! String ||
                relatedDocuments.values.any((item) =>
                    !FullDocumentDiagnosticReport.canParse(item, reporter) &&
                    !UnchangedDocumentDiagnosticReport.canParse(
                        item, reporter))))) {
          reporter.reportError(
              'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentDiagnosticReportPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentDiagnosticReportPartialResult &&
        other.runtimeType == DocumentDiagnosticReportPartialResult) {
      return mapEqual(
              relatedDocuments,
              other.relatedDocuments,
              (Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          a,
                      Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(relatedDocuments);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentFormattingClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingClientCapabilities.canParse,
    DocumentFormattingClientCapabilities.fromJson,
  );

  DocumentFormattingClientCapabilities({
    this.dynamicRegistration,
  });
  static DocumentFormattingClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DocumentFormattingClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether formatting supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentFormattingClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentFormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentFormattingOptions &&
        other.runtimeType == DocumentFormattingOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentFormattingParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingParams.canParse,
    DocumentFormattingParams.fromJson,
  );

  DocumentFormattingParams({
    required this.options,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentFormattingParams fromJson(Map<String, Object?> json) {
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentFormattingParams(
      options: options,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The format options.
  final FormattingOptions options;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['options'] = options.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('options');
      try {
        if (!obj.containsKey('options')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final options = obj['options'];
        if (options == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!FormattingOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type FormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentFormattingParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentFormattingParams &&
        other.runtimeType == DocumentFormattingParams) {
      return options == other.options &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        options,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentFormattingRegistrationOptions
    implements
        DocumentFormattingOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingRegistrationOptions.canParse,
    DocumentFormattingRegistrationOptions.fromJson,
  );

  DocumentFormattingRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static DocumentFormattingRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentFormattingRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentFormattingRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentFormattingRegistrationOptions &&
        other.runtimeType == DocumentFormattingRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A document highlight is a range inside a text document which deserves
/// special attention. Usually a document highlight is visualized by changing
/// the background color of its range.
class DocumentHighlight implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlight.canParse,
    DocumentHighlight.fromJson,
  );

  DocumentHighlight({
    this.kind,
    required this.range,
  });
  static DocumentHighlight fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson != null
        ? DocumentHighlightKind.fromJson(kindJson as int)
        : null;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return DocumentHighlight(
      kind: kind,
      range: range,
    );
  }

  /// The highlight kind, default is DocumentHighlightKind.Text.
  final DocumentHighlightKind? kind;

  /// The range this highlight applies to.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !DocumentHighlightKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type DocumentHighlightKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentHighlight');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentHighlight && other.runtimeType == DocumentHighlight) {
      return kind == other.kind && range == other.range && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentHighlightClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightClientCapabilities.canParse,
    DocumentHighlightClientCapabilities.fromJson,
  );

  DocumentHighlightClientCapabilities({
    this.dynamicRegistration,
  });
  static DocumentHighlightClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DocumentHighlightClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether document highlight supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentHighlightClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 implements ToJsonable {
  const DocumentHighlightKind(this._value);
  const DocumentHighlightKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Read-access of a symbol, like reading a variable.
  static const Read = DocumentHighlightKind(2);

  /// A textual occurrence.
  static const Text = DocumentHighlightKind(1);

  /// Write-access of a symbol, like writing to a variable.
  static const Write = DocumentHighlightKind(3);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is DocumentHighlightKind && other._value == _value;
}

class DocumentHighlightOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightOptions.canParse,
    DocumentHighlightOptions.fromJson,
  );

  DocumentHighlightOptions({
    this.workDoneProgress,
  });
  static DocumentHighlightOptions fromJson(Map<String, Object?> json) {
    if (DocumentHighlightRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentHighlightRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentHighlightOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentHighlightOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightParams.canParse,
    DocumentHighlightParams.fromJson,
  );

  DocumentHighlightParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentHighlightParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentHighlightParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentHighlightParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentHighlightParams &&
        other.runtimeType == DocumentHighlightParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentHighlightRegistrationOptions
    implements
        DocumentHighlightOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightRegistrationOptions.canParse,
    DocumentHighlightRegistrationOptions.fromJson,
  );

  DocumentHighlightRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static DocumentHighlightRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentHighlightRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type DocumentHighlightRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentHighlightRegistrationOptions &&
        other.runtimeType == DocumentHighlightRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A document link is a range in a text document that links to an internal or
/// external resource, like another text document or a web site.
class DocumentLink implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLink.canParse,
    DocumentLink.fromJson,
  );

  DocumentLink({
    this.data,
    required this.range,
    this.target,
    this.tooltip,
  });
  static DocumentLink fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final targetJson = json['target'];
    final target = targetJson as String?;
    final tooltipJson = json['tooltip'];
    final tooltip = tooltipJson as String?;
    return DocumentLink(
      data: data,
      range: range,
      target: target,
      tooltip: tooltip,
    );
  }

  /// A data entry field that is preserved on a document link between a
  /// DocumentLinkRequest and a DocumentLinkResolveRequest.
  final Object? data;

  /// The range this link applies to.
  final Range range;

  /// The uri this link points to. If missing a resolve request is sent later.
  final String? target;

  /// The tooltip text when you hover over this link.
  ///
  /// If a tooltip is provided, is will be displayed in a string that includes
  /// instructions on how to trigger the link, such as `{0} (ctrl + click)`. The
  /// specific instructions vary depending on OS, user settings, and
  /// localization.
  ///  @since 3.15.0
  final String? tooltip;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    result['range'] = range.toJson();
    if (target != null) {
      result['target'] = target;
    }
    if (tooltip != null) {
      result['tooltip'] = tooltip;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('target');
      try {
        final target = obj['target'];
        if (target != null && target is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tooltip');
      try {
        final tooltip = obj['tooltip'];
        if (tooltip != null && tooltip is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLink');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentLink && other.runtimeType == DocumentLink) {
      return data == other.data &&
          range == other.range &&
          target == other.target &&
          tooltip == other.tooltip &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        data,
        range,
        target,
        tooltip,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentLinkClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkClientCapabilities.canParse,
    DocumentLinkClientCapabilities.fromJson,
  );

  DocumentLinkClientCapabilities({
    this.dynamicRegistration,
    this.tooltipSupport,
  });
  static DocumentLinkClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final tooltipSupportJson = json['tooltipSupport'];
    final tooltipSupport = tooltipSupportJson as bool?;
    return DocumentLinkClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      tooltipSupport: tooltipSupport,
    );
  }

  /// Whether document link supports dynamic registration.
  final bool? dynamicRegistration;

  /// Whether the client supports the `tooltip` property on `DocumentLink`.
  ///  @since 3.15.0
  final bool? tooltipSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (tooltipSupport != null) {
      result['tooltipSupport'] = tooltipSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tooltipSupport');
      try {
        final tooltipSupport = obj['tooltipSupport'];
        if (tooltipSupport != null && tooltipSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLinkClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLinkOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkParams.canParse,
    DocumentLinkParams.fromJson,
  );

  DocumentLinkParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentLinkParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentLinkParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The document to provide document links for.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLinkParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentLinkParams &&
        other.runtimeType == DocumentLinkParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentLinkRegistrationOptions
    implements
        DocumentLinkOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkRegistrationOptions.canParse,
    DocumentLinkRegistrationOptions.fromJson,
  );

  DocumentLinkRegistrationOptions({
    this.documentSelector,
    this.resolveProvider,
    this.workDoneProgress,
  });
  static DocumentLinkRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentLinkRegistrationOptions(
      documentSelector: documentSelector,
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// Document links have a resolve provider as well.
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLinkRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentLinkRegistrationOptions &&
        other.runtimeType == DocumentLinkRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentOnTypeFormattingClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['firstTriggerCharacter'] = firstTriggerCharacter;
    if (moreTriggerCharacter != null) {
      result['moreTriggerCharacter'] = moreTriggerCharacter;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('firstTriggerCharacter');
      try {
        if (!obj.containsKey('firstTriggerCharacter')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final firstTriggerCharacter = obj['firstTriggerCharacter'];
        if (firstTriggerCharacter == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (firstTriggerCharacter is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('moreTriggerCharacter');
      try {
        final moreTriggerCharacter = obj['moreTriggerCharacter'];
        if (moreTriggerCharacter != null &&
            (moreTriggerCharacter is! List<Object?> ||
                moreTriggerCharacter.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentOnTypeFormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentOnTypeFormattingOptions &&
        other.runtimeType == DocumentOnTypeFormattingOptions) {
      return firstTriggerCharacter == other.firstTriggerCharacter &&
          listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
              (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        firstTriggerCharacter,
        lspHashCode(moreTriggerCharacter),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentOnTypeFormattingParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingParams.canParse,
    DocumentOnTypeFormattingParams.fromJson,
  );

  DocumentOnTypeFormattingParams({
    required this.ch,
    required this.options,
    required this.position,
    required this.textDocument,
  });
  static DocumentOnTypeFormattingParams fromJson(Map<String, Object?> json) {
    final chJson = json['ch'];
    final ch = chJson as String;
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return DocumentOnTypeFormattingParams(
      ch: ch,
      options: options,
      position: position,
      textDocument: textDocument,
    );
  }

  /// The character that has been typed that triggered the formatting on type
  /// request. That is not necessarily the last character that got inserted into
  /// the document since the client could auto insert characters as well (e.g.
  /// like automatic brace completion).
  final String ch;

  /// The formatting options.
  final FormattingOptions options;

  /// The position around which the on type formatting should happen. This is
  /// not necessarily the exact position where the character denoted by the
  /// property `ch` got typed.
  final Position position;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['ch'] = ch;
    result['options'] = options.toJson();
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ch');
      try {
        if (!obj.containsKey('ch')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final ch = obj['ch'];
        if (ch == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (ch is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        if (!obj.containsKey('options')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final options = obj['options'];
        if (options == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!FormattingOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type FormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentOnTypeFormattingParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentOnTypeFormattingParams &&
        other.runtimeType == DocumentOnTypeFormattingParams) {
      return ch == other.ch &&
          options == other.options &&
          position == other.position &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        ch,
        options,
        position,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentOnTypeFormattingRegistrationOptions
    implements
        DocumentOnTypeFormattingOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingRegistrationOptions.canParse,
    DocumentOnTypeFormattingRegistrationOptions.fromJson,
  );

  DocumentOnTypeFormattingRegistrationOptions({
    this.documentSelector,
    required this.firstTriggerCharacter,
    this.moreTriggerCharacter,
  });
  static DocumentOnTypeFormattingRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final firstTriggerCharacterJson = json['firstTriggerCharacter'];
    final firstTriggerCharacter = firstTriggerCharacterJson as String;
    final moreTriggerCharacterJson = json['moreTriggerCharacter'];
    final moreTriggerCharacter = (moreTriggerCharacterJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    return DocumentOnTypeFormattingRegistrationOptions(
      documentSelector: documentSelector,
      firstTriggerCharacter: firstTriggerCharacter,
      moreTriggerCharacter: moreTriggerCharacter,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// A character on which formatting should be triggered, like `{`.
  @override
  final String firstTriggerCharacter;

  /// More trigger characters.
  @override
  final List<String>? moreTriggerCharacter;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    result['firstTriggerCharacter'] = firstTriggerCharacter;
    if (moreTriggerCharacter != null) {
      result['moreTriggerCharacter'] = moreTriggerCharacter;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('firstTriggerCharacter');
      try {
        if (!obj.containsKey('firstTriggerCharacter')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final firstTriggerCharacter = obj['firstTriggerCharacter'];
        if (firstTriggerCharacter == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (firstTriggerCharacter is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('moreTriggerCharacter');
      try {
        final moreTriggerCharacter = obj['moreTriggerCharacter'];
        if (moreTriggerCharacter != null &&
            (moreTriggerCharacter is! List<Object?> ||
                moreTriggerCharacter.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentOnTypeFormattingRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentOnTypeFormattingRegistrationOptions &&
        other.runtimeType == DocumentOnTypeFormattingRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentRangeFormattingClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentRangeFormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentRangeFormattingOptions &&
        other.runtimeType == DocumentRangeFormattingOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentRangeFormattingParams
    implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingParams.canParse,
    DocumentRangeFormattingParams.fromJson,
  );

  DocumentRangeFormattingParams({
    required this.options,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentRangeFormattingParams fromJson(Map<String, Object?> json) {
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentRangeFormattingParams(
      options: options,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The format options
  final FormattingOptions options;

  /// The range to format
  final Range range;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['options'] = options.toJson();
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('options');
      try {
        if (!obj.containsKey('options')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final options = obj['options'];
        if (options == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!FormattingOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type FormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentRangeFormattingParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentRangeFormattingParams &&
        other.runtimeType == DocumentRangeFormattingParams) {
      return options == other.options &&
          range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        options,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentRangeFormattingRegistrationOptions
    implements
        DocumentRangeFormattingOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingRegistrationOptions.canParse,
    DocumentRangeFormattingRegistrationOptions.fromJson,
  );

  DocumentRangeFormattingRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static DocumentRangeFormattingRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentRangeFormattingRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentRangeFormattingRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentRangeFormattingRegistrationOptions &&
        other.runtimeType == DocumentRangeFormattingRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents programming constructs like variables, classes, interfaces etc.
/// that appear in a document. Document symbols can be hierarchical and they
/// have two ranges: one that encloses its definition and one that points to its
/// most interesting range, e.g. the range of an identifier.
class DocumentSymbol implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbol.canParse,
    DocumentSymbol.fromJson,
  );

  DocumentSymbol({
    this.children,
    this.deprecated,
    this.detail,
    required this.kind,
    required this.name,
    required this.range,
    required this.selectionRange,
    this.tags,
  });
  static DocumentSymbol fromJson(Map<String, Object?> json) {
    final childrenJson = json['children'];
    final children = (childrenJson as List<Object?>?)
        ?.map((item) => DocumentSymbol.fromJson(item as Map<String, Object?>))
        .toList();
    final deprecatedJson = json['deprecated'];
    final deprecated = deprecatedJson as bool?;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final nameJson = json['name'];
    final name = nameJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final selectionRangeJson = json['selectionRange'];
    final selectionRange =
        Range.fromJson(selectionRangeJson as Map<String, Object?>);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return DocumentSymbol(
      children: children,
      deprecated: deprecated,
      detail: detail,
      kind: kind,
      name: name,
      range: range,
      selectionRange: selectionRange,
      tags: tags,
    );
  }

  /// Children of this symbol, e.g. properties of a class.
  final List<DocumentSymbol>? children;

  /// Indicates if this symbol is deprecated.
  ///  @deprecated Use tags instead
  final bool? deprecated;

  /// More detail for this symbol, e.g the signature of a function.
  final String? detail;

  /// The kind of this symbol.
  final SymbolKind kind;

  /// The name of this symbol. Will be displayed in the user interface and
  /// therefore must not be an empty string or a string only consisting of white
  /// spaces.
  final String name;

  /// The range enclosing this symbol not including leading/trailing whitespace
  /// but everything else like comments. This information is typically used to
  /// determine if the clients cursor is inside the symbol to reveal in the
  /// symbol in the UI.
  final Range range;

  /// The range that should be selected and revealed when this symbol is being
  /// picked, e.g. the name of a function. Must be contained by the `range`.
  final Range selectionRange;

  /// Tags for this document symbol.
  ///  @since 3.16.0
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (children != null) {
      result['children'] = children?.map((item) => item.toJson()).toList();
    }
    if (deprecated != null) {
      result['deprecated'] = deprecated;
    }
    if (detail != null) {
      result['detail'] = detail;
    }
    result['kind'] = kind.toJson();
    result['name'] = name;
    result['range'] = range.toJson();
    result['selectionRange'] = selectionRange.toJson();
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('children');
      try {
        final children = obj['children'];
        if (children != null &&
            (children is! List<Object?> ||
                children
                    .any((item) => !DocumentSymbol.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<DocumentSymbol>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deprecated');
      try {
        final deprecated = obj['deprecated'];
        if (deprecated != null && deprecated is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('detail');
      try {
        final detail = obj['detail'];
        if (detail != null && detail is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRange');
      try {
        if (!obj.containsKey('selectionRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final selectionRange = obj['selectionRange'];
        if (selectionRange == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(selectionRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbol');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentSymbol && other.runtimeType == DocumentSymbol) {
      return listEqual(children, other.children,
              (DocumentSymbol a, DocumentSymbol b) => a == b) &&
          deprecated == other.deprecated &&
          detail == other.detail &&
          kind == other.kind &&
          name == other.name &&
          range == other.range &&
          selectionRange == other.selectionRange &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(children),
        deprecated,
        detail,
        kind,
        name,
        range,
        selectionRange,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentSymbolClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolClientCapabilities.canParse,
    DocumentSymbolClientCapabilities.fromJson,
  );

  DocumentSymbolClientCapabilities({
    this.dynamicRegistration,
    this.hierarchicalDocumentSymbolSupport,
    this.labelSupport,
    this.symbolKind,
    this.tagSupport,
  });
  static DocumentSymbolClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final hierarchicalDocumentSymbolSupportJson =
        json['hierarchicalDocumentSymbolSupport'];
    final hierarchicalDocumentSymbolSupport =
        hierarchicalDocumentSymbolSupportJson as bool?;
    final labelSupportJson = json['labelSupport'];
    final labelSupport = labelSupportJson as bool?;
    final symbolKindJson = json['symbolKind'];
    final symbolKind = symbolKindJson != null
        ? DocumentSymbolClientCapabilitiesSymbolKind.fromJson(
            symbolKindJson as Map<String, Object?>)
        : null;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? DocumentSymbolClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    return DocumentSymbolClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      hierarchicalDocumentSymbolSupport: hierarchicalDocumentSymbolSupport,
      labelSupport: labelSupport,
      symbolKind: symbolKind,
      tagSupport: tagSupport,
    );
  }

  /// Whether document symbol supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports hierarchical document symbols.
  final bool? hierarchicalDocumentSymbolSupport;

  /// The client supports an additional label presented in the UI when
  /// registering a document symbol provider.
  ///  @since 3.16.0
  final bool? labelSupport;

  /// Specific capabilities for the `SymbolKind` in the
  /// `textDocument/documentSymbol` request.
  final DocumentSymbolClientCapabilitiesSymbolKind? symbolKind;

  /// The client supports tags on `SymbolInformation`. Tags are supported on
  /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///  @since 3.16.0
  final DocumentSymbolClientCapabilitiesTagSupport? tagSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (hierarchicalDocumentSymbolSupport != null) {
      result['hierarchicalDocumentSymbolSupport'] =
          hierarchicalDocumentSymbolSupport;
    }
    if (labelSupport != null) {
      result['labelSupport'] = labelSupport;
    }
    if (symbolKind != null) {
      result['symbolKind'] = symbolKind?.toJson();
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('hierarchicalDocumentSymbolSupport');
      try {
        final hierarchicalDocumentSymbolSupport =
            obj['hierarchicalDocumentSymbolSupport'];
        if (hierarchicalDocumentSymbolSupport != null &&
            hierarchicalDocumentSymbolSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('labelSupport');
      try {
        final labelSupport = obj['labelSupport'];
        if (labelSupport != null && labelSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('symbolKind');
      try {
        final symbolKind = obj['symbolKind'];
        if (symbolKind != null &&
            !DocumentSymbolClientCapabilitiesSymbolKind.canParse(
                symbolKind, reporter)) {
          reporter.reportError(
              'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        final tagSupport = obj['tagSupport'];
        if (tagSupport != null &&
            !DocumentSymbolClientCapabilitiesTagSupport.canParse(
                tagSupport, reporter)) {
          reporter.reportError(
              'must be of type DocumentSymbolClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentSymbolClientCapabilities &&
        other.runtimeType == DocumentSymbolClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          hierarchicalDocumentSymbolSupport ==
              other.hierarchicalDocumentSymbolSupport &&
          labelSupport == other.labelSupport &&
          symbolKind == other.symbolKind &&
          tagSupport == other.tagSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        hierarchicalDocumentSymbolSupport,
        labelSupport,
        symbolKind,
        tagSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentSymbolClientCapabilitiesSymbolKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolClientCapabilitiesSymbolKind.canParse,
    DocumentSymbolClientCapabilitiesSymbolKind.fromJson,
  );

  DocumentSymbolClientCapabilitiesSymbolKind({
    this.valueSet,
  });
  static DocumentSymbolClientCapabilitiesSymbolKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => SymbolKind.fromJson(item as int))
        .toList();
    return DocumentSymbolClientCapabilitiesSymbolKind(
      valueSet: valueSet,
    );
  }

  /// The symbol kind values the client supports. When this property exists the
  /// client also guarantees that it will handle values outside its set
  /// gracefully and falls back to a default value when unknown.
  ///
  /// If this property is not present the client only supports the symbol kinds
  /// from `File` to `Array` as defined in the initial version of the protocol.
  final List<SymbolKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        final valueSet = obj['valueSet'];
        if (valueSet != null &&
            (valueSet is! List<Object?> ||
                valueSet.any((item) => !SymbolKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentSymbolClientCapabilitiesSymbolKind &&
        other.runtimeType == DocumentSymbolClientCapabilitiesSymbolKind) {
      return listEqual(valueSet, other.valueSet,
              (SymbolKind a, SymbolKind b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentSymbolClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolClientCapabilitiesTagSupport.canParse,
    DocumentSymbolClientCapabilitiesTagSupport.fromJson,
  );

  DocumentSymbolClientCapabilitiesTagSupport({
    required this.valueSet,
  });
  static DocumentSymbolClientCapabilitiesTagSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return DocumentSymbolClientCapabilitiesTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<SymbolTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final valueSet = obj['valueSet'];
        if (valueSet == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (valueSet is! List<Object?> ||
            valueSet.any((item) => !SymbolTag.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentSymbolClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (label != null) {
      result['label'] = label;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('label');
      try {
        final label = obj['label'];
        if (label != null && label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolParams.canParse,
    DocumentSymbolParams.fromJson,
  );

  DocumentSymbolParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentSymbolParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return DocumentSymbolParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentSymbolParams &&
        other.runtimeType == DocumentSymbolParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentSymbolRegistrationOptions
    implements
        DocumentSymbolOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolRegistrationOptions.canParse,
    DocumentSymbolRegistrationOptions.fromJson,
  );

  DocumentSymbolRegistrationOptions({
    this.documentSelector,
    this.label,
    this.workDoneProgress,
  });
  static DocumentSymbolRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final labelJson = json['label'];
    final label = labelJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentSymbolRegistrationOptions(
      documentSelector: documentSelector,
      label: label,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// A human-readable string that is shown when multiple outlines trees are
  /// shown for the same document.
  ///  @since 3.16.0
  @override
  final String? label;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (label != null) {
      result['label'] = label;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        final label = obj['label'];
        if (label != null && label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentSymbolRegistrationOptions &&
        other.runtimeType == DocumentSymbolRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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 implements ToJsonable {
  const ErrorCodes(this._value);
  const ErrorCodes.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// The server detected that the content of a document got modified outside
  /// normal conditions. A server should NOT send this error code if it detects
  /// a content change in it unprocessed messages. The result even computed on
  /// an older state might still be useful for the client.
  ///
  /// If a client decides that a result is not of any use anymore the client
  /// should cancel the request.
  static const ContentModified = ErrorCodes(-32801);
  static const InternalError = ErrorCodes(-32603);
  static const InvalidParams = ErrorCodes(-32602);
  static const InvalidRequest = ErrorCodes(-32600);

  /// This is the end range of JSON-RPC reserved error codes. It doesn't denote
  /// a real error code.
  ///  @since 3.16.0
  static const jsonrpcReservedErrorRangeEnd = ErrorCodes(-32000);

  /// This is the start range of JSON-RPC reserved error codes. It doesn't
  /// denote a real error code. No 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);

  /// This is the end range of LSP reserved error codes. It doesn't denote a
  /// real error code.
  ///  @since 3.16.0
  static const lspReservedErrorRangeEnd = ErrorCodes(-32800);

  /// This is the start range of LSP reserved error codes. It doesn't denote a
  /// real error code.
  ///  @since 3.16.0
  static const lspReservedErrorRangeStart = ErrorCodes(-32899);
  static const MethodNotFound = ErrorCodes(-32601);

  /// Defined by JSON-RPC
  static const ParseError = ErrorCodes(-32700);

  /// The client has canceled a request and a server as detected the cancel.
  static const RequestCancelled = ErrorCodes(-32800);

  /// A request failed but it was syntactically correct, e.g the method name was
  /// known and the parameters were valid. The error message should contain
  /// human readable information about why the request failed.
  ///  @since 3.17.0
  static const RequestFailed = ErrorCodes(-32803);

  /// The server cancelled the request. This error code should only be used for
  /// requests that explicitly support being server cancellable.
  ///  @since 3.17.0
  static const ServerCancelled = ErrorCodes(-32802);

  /// Error code indicating that a server received a notification or request
  /// before the server has received the `initialize` request.
  static const ServerNotInitialized = ErrorCodes(-32002);
  static const UnknownErrorCode = ErrorCodes(-32001);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is ErrorCodes && other._value == _value;
}

class ExecuteCommandClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandClientCapabilities.canParse,
    ExecuteCommandClientCapabilities.fromJson,
  );

  ExecuteCommandClientCapabilities({
    this.dynamicRegistration,
  });
  static ExecuteCommandClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return ExecuteCommandClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Execute command supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecuteCommandClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['commands'] = commands;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('commands');
      try {
        if (!obj.containsKey('commands')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final commands = obj['commands'];
        if (commands == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (commands is! List<Object?> ||
            commands.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecuteCommandOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ExecuteCommandOptions &&
        other.runtimeType == ExecuteCommandOptions) {
      return listEqual(
              commands, other.commands, (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(commands),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ExecuteCommandParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandParams.canParse,
    ExecuteCommandParams.fromJson,
  );

  ExecuteCommandParams({
    this.arguments,
    required this.command,
    this.workDoneToken,
  });
  static ExecuteCommandParams fromJson(Map<String, Object?> json) {
    final argumentsJson = json['arguments'];
    final arguments =
        (argumentsJson as List<Object?>?)?.map((item) => item).toList();
    final commandJson = json['command'];
    final command = commandJson as String;
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return ExecuteCommandParams(
      arguments: arguments,
      command: command,
      workDoneToken: workDoneToken,
    );
  }

  /// Arguments that the command should be invoked with.
  final List<Object?>? arguments;

  /// The identifier of the actual command handler.
  final String command;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (arguments != null) {
      result['arguments'] = arguments;
    }
    result['command'] = command;
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('arguments');
      try {
        final arguments = obj['arguments'];
        if (arguments != null &&
            (arguments is! List<Object?> || arguments.any((item) => false))) {
          reporter.reportError('must be of type List<Object?>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('command');
      try {
        if (!obj.containsKey('command')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final command = obj['command'];
        if (command == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (command is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecuteCommandParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ExecuteCommandParams &&
        other.runtimeType == ExecuteCommandParams) {
      return listEqual(
              arguments, other.arguments, (Object? a, Object? b) => a == b) &&
          command == other.command &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(arguments),
        command,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Execute command registration options.
class ExecuteCommandRegistrationOptions
    implements ExecuteCommandOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandRegistrationOptions.canParse,
    ExecuteCommandRegistrationOptions.fromJson,
  );

  ExecuteCommandRegistrationOptions({
    required this.commands,
    this.workDoneProgress,
  });
  static ExecuteCommandRegistrationOptions fromJson(Map<String, Object?> json) {
    final commandsJson = json['commands'];
    final commands =
        (commandsJson as List<Object?>).map((item) => item as String).toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ExecuteCommandRegistrationOptions(
      commands: commands,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The commands to be executed on the server
  @override
  final List<String> commands;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['commands'] = commands;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('commands');
      try {
        if (!obj.containsKey('commands')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final commands = obj['commands'];
        if (commands == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (commands is! List<Object?> ||
            commands.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecuteCommandRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ExecuteCommandRegistrationOptions &&
        other.runtimeType == ExecuteCommandRegistrationOptions) {
      return listEqual(
              commands, other.commands, (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(commands),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ExecutionSummary implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecutionSummary.canParse,
    ExecutionSummary.fromJson,
  );

  ExecutionSummary({
    required this.executionOrder,
    this.success,
  });
  static ExecutionSummary fromJson(Map<String, Object?> json) {
    final executionOrderJson = json['executionOrder'];
    final executionOrder = executionOrderJson as int;
    final successJson = json['success'];
    final success = successJson as bool?;
    return ExecutionSummary(
      executionOrder: executionOrder,
      success: success,
    );
  }

  /// A strict monotonically increasing value indicating the execution order of
  /// a cell inside a notebook.
  final int executionOrder;

  /// Whether the execution was successful or not if known by the client.
  final bool? success;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['executionOrder'] = executionOrder;
    if (success != null) {
      result['success'] = success;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('executionOrder');
      try {
        if (!obj.containsKey('executionOrder')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final executionOrder = obj['executionOrder'];
        if (executionOrder == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (executionOrder is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('success');
      try {
        final success = obj['success'];
        if (success != null && success is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ExecutionSummary');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ExecutionSummary && other.runtimeType == ExecutionSummary) {
      return executionOrder == other.executionOrder &&
          success == other.success &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        executionOrder,
        success,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FailureHandlingKind implements ToJsonable {
  const FailureHandlingKind._(this._value);
  const FailureHandlingKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'abort':
      case 'textOnlyTransactional':
      case 'transactional':
      case 'undo':
        return true;
    }
    return false;
  }

  /// Applying the workspace change is simply aborted if one of the changes
  /// provided fails. All operations executed before the failing operation stay
  /// executed.
  static const Abort = FailureHandlingKind._('abort');

  /// If the workspace edit contains only textual file changes they are executed
  /// transactional. If resource changes (create, rename or delete file) are
  /// part of the change the failure handling strategy is abort.
  static const TextOnlyTransactional =
      FailureHandlingKind._('textOnlyTransactional');

  /// All operations are executed transactional. That means they either all
  /// succeed or no changes at all are applied to the workspace.
  static const Transactional = FailureHandlingKind._('transactional');

  /// The client tries to undo the operations already executed. But there is no
  /// guarantee that this is succeeding.
  static const Undo = FailureHandlingKind._('undo');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FailureHandlingKind && other._value == _value;
}

/// The file event type.
class FileChangeType implements ToJsonable {
  const FileChangeType(this._value);
  const FileChangeType.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// The file got changed.
  static const Changed = FileChangeType(2);

  /// The file got created.
  static const Created = FileChangeType(1);

  /// The file got deleted.
  static const Deleted = FileChangeType(3);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FileChangeType && other._value == _value;
}

/// Represents information on a file/folder create.
///  @since 3.16.0
class FileCreate implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileCreate.canParse,
    FileCreate.fromJson,
  );

  FileCreate({
    required this.uri,
  });
  static FileCreate fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return FileCreate(
      uri: uri,
    );
  }

  /// A file:// URI for the location of the file/folder being created.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileCreate');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileDelete');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FileDelete && other.runtimeType == FileDelete) {
      return uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An event describing a file change.
class FileEvent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileEvent.canParse,
    FileEvent.fromJson,
  );

  FileEvent({
    required this.type,
    required this.uri,
  });
  static FileEvent fromJson(Map<String, Object?> json) {
    final typeJson = json['type'];
    final type = typeJson as int;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return FileEvent(
      type: type,
      uri: uri,
    );
  }

  /// The change type.
  final int type;

  /// The file's URI.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['type'] = type;
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final type = obj['type'];
        if (type == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (type is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FileEvent && other.runtimeType == FileEvent) {
      return type == other.type && uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        type,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FileOperationClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationClientCapabilities.canParse,
    FileOperationClientCapabilities.fromJson,
  );

  FileOperationClientCapabilities({
    this.didCreate,
    this.didDelete,
    this.didRename,
    this.dynamicRegistration,
    this.willCreate,
    this.willDelete,
    this.willRename,
  });
  static FileOperationClientCapabilities fromJson(Map<String, Object?> json) {
    final didCreateJson = json['didCreate'];
    final didCreate = didCreateJson as bool?;
    final didDeleteJson = json['didDelete'];
    final didDelete = didDeleteJson as bool?;
    final didRenameJson = json['didRename'];
    final didRename = didRenameJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final willCreateJson = json['willCreate'];
    final willCreate = willCreateJson as bool?;
    final willDeleteJson = json['willDelete'];
    final willDelete = willDeleteJson as bool?;
    final willRenameJson = json['willRename'];
    final willRename = willRenameJson as bool?;
    return FileOperationClientCapabilities(
      didCreate: didCreate,
      didDelete: didDelete,
      didRename: didRename,
      dynamicRegistration: dynamicRegistration,
      willCreate: willCreate,
      willDelete: willDelete,
      willRename: willRename,
    );
  }

  /// The client has support for sending didCreateFiles notifications.
  final bool? didCreate;

  /// The client has support for sending didDeleteFiles notifications.
  final bool? didDelete;

  /// The client has support for sending didRenameFiles notifications.
  final bool? didRename;

  /// Whether the client supports dynamic registration for file
  /// requests/notifications.
  final bool? dynamicRegistration;

  /// The client has support for sending willCreateFiles requests.
  final bool? willCreate;

  /// The client has support for sending willDeleteFiles requests.
  final bool? willDelete;

  /// The client has support for sending willRenameFiles requests.
  final bool? willRename;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (didCreate != null) {
      result['didCreate'] = didCreate;
    }
    if (didDelete != null) {
      result['didDelete'] = didDelete;
    }
    if (didRename != null) {
      result['didRename'] = didRename;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (willCreate != null) {
      result['willCreate'] = willCreate;
    }
    if (willDelete != null) {
      result['willDelete'] = willDelete;
    }
    if (willRename != null) {
      result['willRename'] = willRename;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('didCreate');
      try {
        final didCreate = obj['didCreate'];
        if (didCreate != null && didCreate is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didDelete');
      try {
        final didDelete = obj['didDelete'];
        if (didDelete != null && didDelete is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didRename');
      try {
        final didRename = obj['didRename'];
        if (didRename != null && didRename is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willCreate');
      try {
        final willCreate = obj['willCreate'];
        if (willCreate != null && willCreate is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willDelete');
      try {
        final willDelete = obj['willDelete'];
        if (willDelete != null && willDelete is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willRename');
      try {
        final willRename = obj['willRename'];
        if (willRename != null && willRename is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FileOperationClientCapabilities &&
        other.runtimeType == FileOperationClientCapabilities) {
      return didCreate == other.didCreate &&
          didDelete == other.didDelete &&
          didRename == other.didRename &&
          dynamicRegistration == other.dynamicRegistration &&
          willCreate == other.willCreate &&
          willDelete == other.willDelete &&
          willRename == other.willRename &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        didCreate,
        didDelete,
        didRename,
        dynamicRegistration,
        willCreate,
        willDelete,
        willRename,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A filter to describe in which file operation requests or notifications the
/// server is interested in.
///  @since 3.16.0
class FileOperationFilter implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationFilter.canParse,
    FileOperationFilter.fromJson,
  );

  FileOperationFilter({
    required this.pattern,
    this.scheme,
  });
  static FileOperationFilter fromJson(Map<String, Object?> json) {
    final patternJson = json['pattern'];
    final pattern =
        FileOperationPattern.fromJson(patternJson as Map<String, Object?>);
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return FileOperationFilter(
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The actual file operation pattern.
  final FileOperationPattern pattern;

  /// A Uri like `file` or `untitled`.
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['pattern'] = pattern.toJson();
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('pattern');
      try {
        if (!obj.containsKey('pattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final pattern = obj['pattern'];
        if (pattern == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!FileOperationPattern.canParse(pattern, reporter)) {
          reporter.reportError('must be of type FileOperationPattern');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationFilter');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FileOperationFilter &&
        other.runtimeType == FileOperationFilter) {
      return pattern == other.pattern && scheme == other.scheme && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FileOperationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationOptions.canParse,
    FileOperationOptions.fromJson,
  );

  FileOperationOptions({
    this.didCreate,
    this.didDelete,
    this.didRename,
    this.willCreate,
    this.willDelete,
    this.willRename,
  });
  static FileOperationOptions fromJson(Map<String, Object?> json) {
    final didCreateJson = json['didCreate'];
    final didCreate = didCreateJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didCreateJson as Map<String, Object?>)
        : null;
    final didDeleteJson = json['didDelete'];
    final didDelete = didDeleteJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didDeleteJson as Map<String, Object?>)
        : null;
    final didRenameJson = json['didRename'];
    final didRename = didRenameJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didRenameJson as Map<String, Object?>)
        : null;
    final willCreateJson = json['willCreate'];
    final willCreate = willCreateJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willCreateJson as Map<String, Object?>)
        : null;
    final willDeleteJson = json['willDelete'];
    final willDelete = willDeleteJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willDeleteJson as Map<String, Object?>)
        : null;
    final willRenameJson = json['willRename'];
    final willRename = willRenameJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willRenameJson as Map<String, Object?>)
        : null;
    return FileOperationOptions(
      didCreate: didCreate,
      didDelete: didDelete,
      didRename: didRename,
      willCreate: willCreate,
      willDelete: willDelete,
      willRename: willRename,
    );
  }

  /// The server is interested in receiving didCreateFiles notifications.
  final FileOperationRegistrationOptions? didCreate;

  /// The server is interested in receiving didDeleteFiles file notifications.
  final FileOperationRegistrationOptions? didDelete;

  /// The server is interested in receiving didRenameFiles notifications.
  final FileOperationRegistrationOptions? didRename;

  /// The server is interested in receiving willCreateFiles requests.
  final FileOperationRegistrationOptions? willCreate;

  /// The server is interested in receiving willDeleteFiles file requests.
  final FileOperationRegistrationOptions? willDelete;

  /// The server is interested in receiving willRenameFiles requests.
  final FileOperationRegistrationOptions? willRename;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (didCreate != null) {
      result['didCreate'] = didCreate?.toJson();
    }
    if (didDelete != null) {
      result['didDelete'] = didDelete?.toJson();
    }
    if (didRename != null) {
      result['didRename'] = didRename?.toJson();
    }
    if (willCreate != null) {
      result['willCreate'] = willCreate?.toJson();
    }
    if (willDelete != null) {
      result['willDelete'] = willDelete?.toJson();
    }
    if (willRename != null) {
      result['willRename'] = willRename?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('didCreate');
      try {
        final didCreate = obj['didCreate'];
        if (didCreate != null &&
            !FileOperationRegistrationOptions.canParse(didCreate, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didDelete');
      try {
        final didDelete = obj['didDelete'];
        if (didDelete != null &&
            !FileOperationRegistrationOptions.canParse(didDelete, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didRename');
      try {
        final didRename = obj['didRename'];
        if (didRename != null &&
            !FileOperationRegistrationOptions.canParse(didRename, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willCreate');
      try {
        final willCreate = obj['willCreate'];
        if (willCreate != null &&
            !FileOperationRegistrationOptions.canParse(willCreate, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willDelete');
      try {
        final willDelete = obj['willDelete'];
        if (willDelete != null &&
            !FileOperationRegistrationOptions.canParse(willDelete, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willRename');
      try {
        final willRename = obj['willRename'];
        if (willRename != null &&
            !FileOperationRegistrationOptions.canParse(willRename, reporter)) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FileOperationOptions &&
        other.runtimeType == FileOperationOptions) {
      return didCreate == other.didCreate &&
          didDelete == other.didDelete &&
          didRename == other.didRename &&
          willCreate == other.willCreate &&
          willDelete == other.willDelete &&
          willRename == other.willRename &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        didCreate,
        didDelete,
        didRename,
        willCreate,
        willDelete,
        willRename,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A pattern to describe in which file operation requests or notifications the
/// server is interested in.
///  @since 3.16.0
class FileOperationPattern implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationPattern.canParse,
    FileOperationPattern.fromJson,
  );

  FileOperationPattern({
    required this.glob,
    this.matches,
    this.options,
  });
  static FileOperationPattern fromJson(Map<String, Object?> json) {
    final globJson = json['glob'];
    final glob = globJson as String;
    final matchesJson = json['matches'];
    final matches = matchesJson != null
        ? FileOperationPatternKind.fromJson(matchesJson as String)
        : null;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? FileOperationPatternOptions.fromJson(
            optionsJson as Map<String, Object?>)
        : null;
    return FileOperationPattern(
      glob: glob,
      matches: matches,
      options: options,
    );
  }

  /// The glob pattern to match. Glob patterns can have the following syntax:
  /// - `*` to match one or more characters in a path segment
  /// - `?` to match on one character in a path segment
  /// - `**` to match any number of path segments, including none
  /// - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}`
  ///   matches all TypeScript and JavaScript files)
  /// - `[]` to declare a range of characters to match in a path segment
  ///   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
  /// - `[!...]` to negate a range of characters to match in a path segment
  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
  ///   not `example.0`)
  final String glob;

  /// Whether to match files or folders with this pattern.
  ///
  /// Matches both if undefined.
  final FileOperationPatternKind? matches;

  /// Additional options used during matching.
  final FileOperationPatternOptions? options;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['glob'] = glob;
    if (matches != null) {
      result['matches'] = matches?.toJson();
    }
    if (options != null) {
      result['options'] = options?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('glob');
      try {
        if (!obj.containsKey('glob')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final glob = obj['glob'];
        if (glob == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (glob is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('matches');
      try {
        final matches = obj['matches'];
        if (matches != null &&
            !FileOperationPatternKind.canParse(matches, reporter)) {
          reporter.reportError('must be of type FileOperationPatternKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        final options = obj['options'];
        if (options != null &&
            !FileOperationPatternOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type FileOperationPatternOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationPattern');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 implements ToJsonable {
  const FileOperationPatternKind(this._value);
  const FileOperationPatternKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// The pattern matches a file only.
  static const file = FileOperationPatternKind('file');

  /// The pattern matches a folder only.
  static const folder = FileOperationPatternKind('folder');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FileOperationPatternKind && other._value == _value;
}

/// Matching options for the file operation pattern.
///  @since 3.16.0
class FileOperationPatternOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationPatternOptions.canParse,
    FileOperationPatternOptions.fromJson,
  );

  FileOperationPatternOptions({
    this.ignoreCase,
  });
  static FileOperationPatternOptions fromJson(Map<String, Object?> json) {
    final ignoreCaseJson = json['ignoreCase'];
    final ignoreCase = ignoreCaseJson as bool?;
    return FileOperationPatternOptions(
      ignoreCase: ignoreCase,
    );
  }

  /// The pattern should be matched ignoring casing.
  final bool? ignoreCase;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (ignoreCase != null) {
      result['ignoreCase'] = ignoreCase;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ignoreCase');
      try {
        final ignoreCase = obj['ignoreCase'];
        if (ignoreCase != null && ignoreCase is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationPatternOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['filters'] = filters.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('filters');
      try {
        if (!obj.containsKey('filters')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final filters = obj['filters'];
        if (filters == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (filters is! List<Object?> ||
            filters
                .any((item) => !FileOperationFilter.canParse(item, reporter))) {
          reporter.reportError('must be of type List<FileOperationFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FileOperationRegistrationOptions &&
        other.runtimeType == FileOperationRegistrationOptions) {
      return listEqual(filters, other.filters,
              (FileOperationFilter a, FileOperationFilter b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(filters);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents information on a file/folder rename.
///  @since 3.16.0
class FileRename implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileRename.canParse,
    FileRename.fromJson,
  );

  FileRename({
    required this.newUri,
    required this.oldUri,
  });
  static FileRename fromJson(Map<String, Object?> json) {
    final newUriJson = json['newUri'];
    final newUri = newUriJson as String;
    final oldUriJson = json['oldUri'];
    final oldUri = oldUriJson as String;
    return FileRename(
      newUri: newUri,
      oldUri: oldUri,
    );
  }

  /// A file:// URI for the new location of the file/folder being renamed.
  final String newUri;

  /// A file:// URI for the original location of the file/folder being renamed.
  final String oldUri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['newUri'] = newUri;
    result['oldUri'] = oldUri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('newUri');
      try {
        if (!obj.containsKey('newUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newUri = obj['newUri'];
        if (newUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('oldUri');
      try {
        if (!obj.containsKey('oldUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final oldUri = obj['oldUri'];
        if (oldUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (oldUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileRename');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FileRename && other.runtimeType == FileRename) {
      return newUri == other.newUri && oldUri == other.oldUri && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        newUri,
        oldUri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FileSystemWatcher implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileSystemWatcher.canParse,
    FileSystemWatcher.fromJson,
  );

  FileSystemWatcher({
    required this.globPattern,
    this.kind,
  });
  static FileSystemWatcher fromJson(Map<String, Object?> json) {
    final globPatternJson = json['globPattern'];
    final globPattern = globPatternJson is String
        ? Either2<String, RelativePattern>.t1(globPatternJson)
        : (RelativePattern.canParse(globPatternJson, nullLspJsonReporter)
            ? Either2<String, RelativePattern>.t2(RelativePattern.fromJson(
                globPatternJson as Map<String, Object?>))
            : (throw '''$globPatternJson was not one of (String, RelativePattern)'''));
    final kindJson = json['kind'];
    final kind = kindJson != null ? WatchKind.fromJson(kindJson as int) : null;
    return FileSystemWatcher(
      globPattern: globPattern,
      kind: kind,
    );
  }

  /// The glob pattern to watch. See {@link GlobPattern glob pattern} for more
  /// detail.
  ///  @since 3.17.0 support for relative patterns.
  final Either2<String, RelativePattern> globPattern;

  /// The kind of events of interest. If omitted it defaults to WatchKind.Create
  /// | WatchKind.Change | WatchKind.Delete which is 7.
  final WatchKind? kind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['globPattern'] = globPattern;
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('globPattern');
      try {
        if (!obj.containsKey('globPattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final globPattern = obj['globPattern'];
        if (globPattern == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (globPattern is! String &&
            !RelativePattern.canParse(globPattern, reporter)) {
          reporter
              .reportError('must be of type Either2<String, RelativePattern>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !WatchKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type WatchKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileSystemWatcher');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FileSystemWatcher && other.runtimeType == FileSystemWatcher) {
      return globPattern == other.globPattern && kind == other.kind && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        globPattern,
        kind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a folding range. To be valid, start and end line must be bigger
/// than zero and smaller than the number of lines in the document. Clients are
/// free to ignore invalid ranges.
class FoldingRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRange.canParse,
    FoldingRange.fromJson,
  );

  FoldingRange({
    this.collapsedText,
    this.endCharacter,
    required this.endLine,
    this.kind,
    this.startCharacter,
    required this.startLine,
  });
  static FoldingRange fromJson(Map<String, Object?> json) {
    final collapsedTextJson = json['collapsedText'];
    final collapsedText = collapsedTextJson as String?;
    final endCharacterJson = json['endCharacter'];
    final endCharacter = endCharacterJson as int?;
    final endLineJson = json['endLine'];
    final endLine = endLineJson as int;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? FoldingRangeKind.fromJson(kindJson as String) : null;
    final startCharacterJson = json['startCharacter'];
    final startCharacter = startCharacterJson as int?;
    final startLineJson = json['startLine'];
    final startLine = startLineJson as int;
    return FoldingRange(
      collapsedText: collapsedText,
      endCharacter: endCharacter,
      endLine: endLine,
      kind: kind,
      startCharacter: startCharacter,
      startLine: startLine,
    );
  }

  /// The text that the client should show when the specified range is
  /// collapsed. If not defined or not supported by the client, a default will
  /// be chosen by the client.
  ///  @since 3.17.0 - proposed
  final String? collapsedText;

  /// The zero-based character offset before the folded range ends. If not
  /// defined, defaults to the length of the end line.
  final int? endCharacter;

  /// The zero-based end line of the range to fold. The folded area ends with
  /// the line's last character. To be valid, the end must be zero or larger and
  /// smaller than the number of lines in the document.
  final int endLine;

  /// Describes the kind of the folding range such as `comment` or `region`. The
  /// kind is used to categorize folding ranges and used by commands like 'Fold
  /// all comments'. See [FoldingRangeKind] for an enumeration of standardized
  /// kinds.
  final FoldingRangeKind? kind;

  /// The zero-based character offset from where the folded range starts. If not
  /// defined, defaults to the length of the start line.
  final int? startCharacter;

  /// The zero-based start line of the range to fold. The folded area starts
  /// after the line's last character. To be valid, the end must be zero or
  /// larger and smaller than the number of lines in the document.
  final int startLine;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (collapsedText != null) {
      result['collapsedText'] = collapsedText;
    }
    if (endCharacter != null) {
      result['endCharacter'] = endCharacter;
    }
    result['endLine'] = endLine;
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    if (startCharacter != null) {
      result['startCharacter'] = startCharacter;
    }
    result['startLine'] = startLine;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('collapsedText');
      try {
        final collapsedText = obj['collapsedText'];
        if (collapsedText != null && collapsedText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('endCharacter');
      try {
        final endCharacter = obj['endCharacter'];
        if (endCharacter != null && endCharacter is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('endLine');
      try {
        if (!obj.containsKey('endLine')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final endLine = obj['endLine'];
        if (endLine == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (endLine is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !FoldingRangeKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type FoldingRangeKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('startCharacter');
      try {
        final startCharacter = obj['startCharacter'];
        if (startCharacter != null && startCharacter is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('startLine');
      try {
        if (!obj.containsKey('startLine')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final startLine = obj['startLine'];
        if (startLine == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (startLine is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FoldingRange && other.runtimeType == FoldingRange) {
      return collapsedText == other.collapsedText &&
          endCharacter == other.endCharacter &&
          endLine == other.endLine &&
          kind == other.kind &&
          startCharacter == other.startCharacter &&
          startLine == other.startLine &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        collapsedText,
        endCharacter,
        endLine,
        kind,
        startCharacter,
        startLine,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeClientCapabilities.canParse,
    FoldingRangeClientCapabilities.fromJson,
  );

  FoldingRangeClientCapabilities({
    this.dynamicRegistration,
    this.foldingRange,
    this.foldingRangeKind,
    this.lineFoldingOnly,
    this.rangeLimit,
  });
  static FoldingRangeClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final foldingRangeJson = json['foldingRange'];
    final foldingRange = foldingRangeJson != null
        ? FoldingRangeClientCapabilitiesFoldingRange.fromJson(
            foldingRangeJson as Map<String, Object?>)
        : null;
    final foldingRangeKindJson = json['foldingRangeKind'];
    final foldingRangeKind = foldingRangeKindJson != null
        ? FoldingRangeClientCapabilitiesFoldingRangeKind.fromJson(
            foldingRangeKindJson as Map<String, Object?>)
        : null;
    final lineFoldingOnlyJson = json['lineFoldingOnly'];
    final lineFoldingOnly = lineFoldingOnlyJson as bool?;
    final rangeLimitJson = json['rangeLimit'];
    final rangeLimit = rangeLimitJson as int?;
    return FoldingRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      foldingRange: foldingRange,
      foldingRangeKind: foldingRangeKind,
      lineFoldingOnly: lineFoldingOnly,
      rangeLimit: rangeLimit,
    );
  }

  /// Whether implementation supports dynamic registration for folding range
  /// providers. If this is set to `true` the client supports the new
  /// `FoldingRangeRegistrationOptions` return value for the corresponding
  /// server capability as well.
  final bool? dynamicRegistration;

  /// Specific options for the folding range. @since 3.17.0
  final FoldingRangeClientCapabilitiesFoldingRange? foldingRange;

  /// Specific options for the folding range kind.
  ///  @since 3.17.0
  final FoldingRangeClientCapabilitiesFoldingRangeKind? foldingRangeKind;

  /// If set, the client signals that it only supports folding complete lines.
  /// If set, client will ignore specified `startCharacter` and `endCharacter`
  /// properties in a FoldingRange.
  final bool? lineFoldingOnly;

  /// The maximum number of folding ranges that the client prefers to receive
  /// per document. The value serves as a hint, servers are free to follow the
  /// limit.
  final int? rangeLimit;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (foldingRange != null) {
      result['foldingRange'] = foldingRange?.toJson();
    }
    if (foldingRangeKind != null) {
      result['foldingRangeKind'] = foldingRangeKind?.toJson();
    }
    if (lineFoldingOnly != null) {
      result['lineFoldingOnly'] = lineFoldingOnly;
    }
    if (rangeLimit != null) {
      result['rangeLimit'] = rangeLimit;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRange');
      try {
        final foldingRange = obj['foldingRange'];
        if (foldingRange != null &&
            !FoldingRangeClientCapabilitiesFoldingRange.canParse(
                foldingRange, reporter)) {
          reporter.reportError(
              'must be of type FoldingRangeClientCapabilitiesFoldingRange');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRangeKind');
      try {
        final foldingRangeKind = obj['foldingRangeKind'];
        if (foldingRangeKind != null &&
            !FoldingRangeClientCapabilitiesFoldingRangeKind.canParse(
                foldingRangeKind, reporter)) {
          reporter.reportError(
              'must be of type FoldingRangeClientCapabilitiesFoldingRangeKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('lineFoldingOnly');
      try {
        final lineFoldingOnly = obj['lineFoldingOnly'];
        if (lineFoldingOnly != null && lineFoldingOnly is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rangeLimit');
      try {
        final rangeLimit = obj['rangeLimit'];
        if (rangeLimit != null && rangeLimit is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRangeClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FoldingRangeClientCapabilities &&
        other.runtimeType == FoldingRangeClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          foldingRange == other.foldingRange &&
          foldingRangeKind == other.foldingRangeKind &&
          lineFoldingOnly == other.lineFoldingOnly &&
          rangeLimit == other.rangeLimit &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        foldingRange,
        foldingRangeKind,
        lineFoldingOnly,
        rangeLimit,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeClientCapabilitiesFoldingRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeClientCapabilitiesFoldingRange.canParse,
    FoldingRangeClientCapabilitiesFoldingRange.fromJson,
  );

  FoldingRangeClientCapabilitiesFoldingRange({
    this.collapsedText,
  });
  static FoldingRangeClientCapabilitiesFoldingRange fromJson(
      Map<String, Object?> json) {
    final collapsedTextJson = json['collapsedText'];
    final collapsedText = collapsedTextJson as bool?;
    return FoldingRangeClientCapabilitiesFoldingRange(
      collapsedText: collapsedText,
    );
  }

  /// If set, the client signals that it supports setting collapsedText on
  /// folding ranges to display custom labels instead of the default text.
  ///  @since 3.17.0
  final bool? collapsedText;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (collapsedText != null) {
      result['collapsedText'] = collapsedText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('collapsedText');
      try {
        final collapsedText = obj['collapsedText'];
        if (collapsedText != null && collapsedText is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type FoldingRangeClientCapabilitiesFoldingRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FoldingRangeClientCapabilitiesFoldingRange &&
        other.runtimeType == FoldingRangeClientCapabilitiesFoldingRange) {
      return collapsedText == other.collapsedText && true;
    }
    return false;
  }

  @override
  int get hashCode => collapsedText.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeClientCapabilitiesFoldingRangeKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeClientCapabilitiesFoldingRangeKind.canParse,
    FoldingRangeClientCapabilitiesFoldingRangeKind.fromJson,
  );

  FoldingRangeClientCapabilitiesFoldingRangeKind({
    this.valueSet,
  });
  static FoldingRangeClientCapabilitiesFoldingRangeKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => FoldingRangeKind.fromJson(item as String))
        .toList();
    return FoldingRangeClientCapabilitiesFoldingRangeKind(
      valueSet: valueSet,
    );
  }

  /// The folding range kind values the client supports. When this property
  /// exists the client also guarantees that it will handle values outside its
  /// set gracefully and falls back to a default value when unknown.
  final List<FoldingRangeKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        final valueSet = obj['valueSet'];
        if (valueSet != null &&
            (valueSet is! List<Object?> ||
                valueSet.any(
                    (item) => !FoldingRangeKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<FoldingRangeKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type FoldingRangeClientCapabilitiesFoldingRangeKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FoldingRangeClientCapabilitiesFoldingRangeKind &&
        other.runtimeType == FoldingRangeClientCapabilitiesFoldingRangeKind) {
      return listEqual(valueSet, other.valueSet,
              (FoldingRangeKind a, FoldingRangeKind b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A set of predefined range kinds.
class FoldingRangeKind implements ToJsonable {
  const FoldingRangeKind(this._value);
  const FoldingRangeKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// Folding range for a comment
  static const Comment = FoldingRangeKind('comment');

  /// Folding range for a imports or includes
  static const Imports = FoldingRangeKind('imports');

  /// Folding range for a region (e.g. `#region`)
  static const Region = FoldingRangeKind('region');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FoldingRangeKind && other._value == _value;
}

class FoldingRangeOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeOptions.canParse,
    FoldingRangeOptions.fromJson,
  );

  FoldingRangeOptions({
    this.workDoneProgress,
  });
  static FoldingRangeOptions fromJson(Map<String, Object?> json) {
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return FoldingRangeOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRangeOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeParams.canParse,
    FoldingRangeParams.fromJson,
  );

  FoldingRangeParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static FoldingRangeParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return FoldingRangeParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FoldingRangeParams &&
        other.runtimeType == FoldingRangeParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeRegistrationOptions
    implements
        FoldingRangeOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeRegistrationOptions.canParse,
    FoldingRangeRegistrationOptions.fromJson,
  );

  FoldingRangeRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static FoldingRangeRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return FoldingRangeRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FoldingRangeRegistrationOptions &&
        other.runtimeType == FoldingRangeRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Value-object describing what options formatting should use.
class FormattingOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FormattingOptions.canParse,
    FormattingOptions.fromJson,
  );

  FormattingOptions({
    this.insertFinalNewline,
    required this.insertSpaces,
    required this.tabSize,
    this.trimFinalNewlines,
    this.trimTrailingWhitespace,
  });
  static FormattingOptions fromJson(Map<String, Object?> json) {
    final insertFinalNewlineJson = json['insertFinalNewline'];
    final insertFinalNewline = insertFinalNewlineJson as bool?;
    final insertSpacesJson = json['insertSpaces'];
    final insertSpaces = insertSpacesJson as bool;
    final tabSizeJson = json['tabSize'];
    final tabSize = tabSizeJson as int;
    final trimFinalNewlinesJson = json['trimFinalNewlines'];
    final trimFinalNewlines = trimFinalNewlinesJson as bool?;
    final trimTrailingWhitespaceJson = json['trimTrailingWhitespace'];
    final trimTrailingWhitespace = trimTrailingWhitespaceJson as bool?;
    return FormattingOptions(
      insertFinalNewline: insertFinalNewline,
      insertSpaces: insertSpaces,
      tabSize: tabSize,
      trimFinalNewlines: trimFinalNewlines,
      trimTrailingWhitespace: trimTrailingWhitespace,
    );
  }

  /// Insert a newline character at the end of the file if one does not exist.
  ///  @since 3.15.0
  final bool? insertFinalNewline;

  /// Prefer spaces over tabs.
  final bool insertSpaces;

  /// Size of a tab in spaces.
  final int tabSize;

  /// Trim all newlines after the final newline at the end of the file.
  ///  @since 3.15.0
  final bool? trimFinalNewlines;

  /// Trim trailing whitespace on a line.
  ///  @since 3.15.0
  final bool? trimTrailingWhitespace;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (insertFinalNewline != null) {
      result['insertFinalNewline'] = insertFinalNewline;
    }
    result['insertSpaces'] = insertSpaces;
    result['tabSize'] = tabSize;
    if (trimFinalNewlines != null) {
      result['trimFinalNewlines'] = trimFinalNewlines;
    }
    if (trimTrailingWhitespace != null) {
      result['trimTrailingWhitespace'] = trimTrailingWhitespace;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('insertFinalNewline');
      try {
        final insertFinalNewline = obj['insertFinalNewline'];
        if (insertFinalNewline != null && insertFinalNewline is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertSpaces');
      try {
        if (!obj.containsKey('insertSpaces')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final insertSpaces = obj['insertSpaces'];
        if (insertSpaces == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (insertSpaces is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tabSize');
      try {
        if (!obj.containsKey('tabSize')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tabSize = obj['tabSize'];
        if (tabSize == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tabSize is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('trimFinalNewlines');
      try {
        final trimFinalNewlines = obj['trimFinalNewlines'];
        if (trimFinalNewlines != null && trimFinalNewlines is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('trimTrailingWhitespace');
      try {
        final trimTrailingWhitespace = obj['trimTrailingWhitespace'];
        if (trimTrailingWhitespace != null && trimTrailingWhitespace is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FormattingOptions && other.runtimeType == FormattingOptions) {
      return insertFinalNewline == other.insertFinalNewline &&
          insertSpaces == other.insertSpaces &&
          tabSize == other.tabSize &&
          trimFinalNewlines == other.trimFinalNewlines &&
          trimTrailingWhitespace == other.trimTrailingWhitespace &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        insertFinalNewline,
        insertSpaces,
        tabSize,
        trimFinalNewlines,
        trimTrailingWhitespace,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A diagnostic report with a full set of problems.
///  @since 3.17.0
class FullDocumentDiagnosticReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FullDocumentDiagnosticReport.canParse,
    FullDocumentDiagnosticReport.fromJson,
  );

  FullDocumentDiagnosticReport({
    required this.items,
    this.kind = 'full',
    this.resultId,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static FullDocumentDiagnosticReport fromJson(Map<String, Object?> json) {
    if (WorkspaceFullDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceFullDocumentDiagnosticReport.fromJson(json);
    }
    if (RelatedFullDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return RelatedFullDocumentDiagnosticReport.fromJson(json);
    }
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return FullDocumentDiagnosticReport(
      items: items,
      kind: kind,
      resultId: resultId,
    );
  }

  /// The actual items.
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  final String kind;

  /// An optional result id. If provided it will be sent on the next diagnostic
  /// request for the same document.
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    result['kind'] = kind;
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) => !Diagnostic.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'full') {
          reporter.reportError('must be the literal \'full\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FullDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FullDocumentDiagnosticReport &&
        other.runtimeType == FullDocumentDiagnosticReport) {
      return listEqual(
              items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
          kind == other.kind &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(items),
        kind,
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class GeneralClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    GeneralClientCapabilities.canParse,
    GeneralClientCapabilities.fromJson,
  );

  GeneralClientCapabilities({
    this.markdown,
    this.positionEncodings,
    this.regularExpressions,
    this.staleRequestSupport,
  });
  static GeneralClientCapabilities fromJson(Map<String, Object?> json) {
    final markdownJson = json['markdown'];
    final markdown = markdownJson != null
        ? MarkdownClientCapabilities.fromJson(
            markdownJson as Map<String, Object?>)
        : null;
    final positionEncodingsJson = json['positionEncodings'];
    final positionEncodings = (positionEncodingsJson as List<Object?>?)
        ?.map((item) => PositionEncodingKind.fromJson(item as String))
        .toList();
    final regularExpressionsJson = json['regularExpressions'];
    final regularExpressions = regularExpressionsJson != null
        ? RegularExpressionsClientCapabilities.fromJson(
            regularExpressionsJson as Map<String, Object?>)
        : null;
    final staleRequestSupportJson = json['staleRequestSupport'];
    final staleRequestSupport = staleRequestSupportJson != null
        ? GeneralClientCapabilitiesStaleRequestSupport.fromJson(
            staleRequestSupportJson as Map<String, Object?>)
        : null;
    return GeneralClientCapabilities(
      markdown: markdown,
      positionEncodings: positionEncodings,
      regularExpressions: regularExpressions,
      staleRequestSupport: staleRequestSupport,
    );
  }

  /// Client capabilities specific to the client's markdown parser.
  ///  @since 3.16.0
  final MarkdownClientCapabilities? markdown;

  /// The position encodings supported by the client. Client and server have to
  /// agree on the same position encoding to ensure that offsets (e.g. character
  /// position in a line) are interpreted the same on both side.
  ///
  /// To keep the protocol backwards compatible the following applies: if the
  /// value 'utf-16' is missing from the array of position encodings servers can
  /// assume that the client supports UTF-16. UTF-16 is therefore a mandatory
  /// encoding.
  ///
  /// If omitted it defaults to ['utf-16'].
  ///
  /// Implementation considerations: since the conversion from one encoding into
  /// another requires the content of the file / line the conversion is best
  /// done where the file is read which is usually on the server side.
  ///  @since 3.17.0
  final List<PositionEncodingKind>? positionEncodings;

  /// Client capabilities specific to regular expressions.
  ///  @since 3.16.0
  final RegularExpressionsClientCapabilities? regularExpressions;

  /// Client capability that signals how the client handles stale requests (e.g.
  /// a request for which the client will not process the response anymore since
  /// the information is outdated).
  ///  @since 3.17.0
  final GeneralClientCapabilitiesStaleRequestSupport? staleRequestSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (markdown != null) {
      result['markdown'] = markdown?.toJson();
    }
    if (positionEncodings != null) {
      result['positionEncodings'] =
          positionEncodings?.map((item) => item.toJson()).toList();
    }
    if (regularExpressions != null) {
      result['regularExpressions'] = regularExpressions?.toJson();
    }
    if (staleRequestSupport != null) {
      result['staleRequestSupport'] = staleRequestSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('markdown');
      try {
        final markdown = obj['markdown'];
        if (markdown != null &&
            !MarkdownClientCapabilities.canParse(markdown, reporter)) {
          reporter.reportError('must be of type MarkdownClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('positionEncodings');
      try {
        final positionEncodings = obj['positionEncodings'];
        if (positionEncodings != null &&
            (positionEncodings is! List<Object?> ||
                positionEncodings.any((item) =>
                    !PositionEncodingKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<PositionEncodingKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('regularExpressions');
      try {
        final regularExpressions = obj['regularExpressions'];
        if (regularExpressions != null &&
            !RegularExpressionsClientCapabilities.canParse(
                regularExpressions, reporter)) {
          reporter.reportError(
              'must be of type RegularExpressionsClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('staleRequestSupport');
      try {
        final staleRequestSupport = obj['staleRequestSupport'];
        if (staleRequestSupport != null &&
            !GeneralClientCapabilitiesStaleRequestSupport.canParse(
                staleRequestSupport, reporter)) {
          reporter.reportError(
              'must be of type GeneralClientCapabilitiesStaleRequestSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type GeneralClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is GeneralClientCapabilities &&
        other.runtimeType == GeneralClientCapabilities) {
      return markdown == other.markdown &&
          listEqual(positionEncodings, other.positionEncodings,
              (PositionEncodingKind a, PositionEncodingKind b) => a == b) &&
          regularExpressions == other.regularExpressions &&
          staleRequestSupport == other.staleRequestSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        markdown,
        lspHashCode(positionEncodings),
        regularExpressions,
        staleRequestSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class GeneralClientCapabilitiesStaleRequestSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    GeneralClientCapabilitiesStaleRequestSupport.canParse,
    GeneralClientCapabilitiesStaleRequestSupport.fromJson,
  );

  GeneralClientCapabilitiesStaleRequestSupport({
    required this.cancel,
    required this.retryOnContentModified,
  });
  static GeneralClientCapabilitiesStaleRequestSupport fromJson(
      Map<String, Object?> json) {
    final cancelJson = json['cancel'];
    final cancel = cancelJson as bool;
    final retryOnContentModifiedJson = json['retryOnContentModified'];
    final retryOnContentModified = (retryOnContentModifiedJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return GeneralClientCapabilitiesStaleRequestSupport(
      cancel: cancel,
      retryOnContentModified: retryOnContentModified,
    );
  }

  /// The client will actively cancel the request.
  final bool cancel;

  /// The list of requests for which the client will retry the request if it
  /// receives a response with error code `ContentModified``
  final List<String> retryOnContentModified;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cancel'] = cancel;
    result['retryOnContentModified'] = retryOnContentModified;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cancel');
      try {
        if (!obj.containsKey('cancel')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final cancel = obj['cancel'];
        if (cancel == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (cancel is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('retryOnContentModified');
      try {
        if (!obj.containsKey('retryOnContentModified')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final retryOnContentModified = obj['retryOnContentModified'];
        if (retryOnContentModified == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (retryOnContentModified is! List<Object?> ||
            retryOnContentModified.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type GeneralClientCapabilitiesStaleRequestSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is GeneralClientCapabilitiesStaleRequestSupport &&
        other.runtimeType == GeneralClientCapabilitiesStaleRequestSupport) {
      return cancel == other.cancel &&
          listEqual(retryOnContentModified, other.retryOnContentModified,
              (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        cancel,
        lspHashCode(retryOnContentModified),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result of a hover request.
class Hover implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Hover.canParse,
    Hover.fromJson,
  );

  Hover({
    required this.contents,
    this.range,
  });
  static Hover fromJson(Map<String, Object?> json) {
    final contentsJson = json['contents'];
    final contents = MarkupContent.canParse(contentsJson, nullLspJsonReporter)
        ? Either2<MarkupContent, String>.t1(
            MarkupContent.fromJson(contentsJson as Map<String, Object?>))
        : (contentsJson is String
            ? Either2<MarkupContent, String>.t2(contentsJson)
            : (throw '''$contentsJson was not one of (MarkupContent, String)'''));
    final rangeJson = json['range'];
    final range = rangeJson != null
        ? Range.fromJson(rangeJson as Map<String, Object?>)
        : null;
    return Hover(
      contents: contents,
      range: range,
    );
  }

  /// The hover's content
  final Either2<MarkupContent, String> contents;

  /// An optional range is a range inside a text document that is used to
  /// visualize a hover, e.g. by changing the background color.
  final Range? range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['contents'] = contents;
    if (range != null) {
      result['range'] = range?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('contents');
      try {
        if (!obj.containsKey('contents')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final contents = obj['contents'];
        if (contents == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MarkupContent.canParse(contents, reporter) &&
            contents is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        final range = obj['range'];
        if (range != null && !Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Hover');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is Hover && other.runtimeType == Hover) {
      return contents == other.contents && range == other.range && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        contents,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class HoverClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverClientCapabilities.canParse,
    HoverClientCapabilities.fromJson,
  );

  HoverClientCapabilities({
    this.contentFormat,
    this.dynamicRegistration,
  });
  static HoverClientCapabilities fromJson(Map<String, Object?> json) {
    final contentFormatJson = json['contentFormat'];
    final contentFormat = (contentFormatJson as List<Object?>?)
        ?.map((item) => MarkupKind.fromJson(item as String))
        .toList();
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return HoverClientCapabilities(
      contentFormat: contentFormat,
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Client supports the follow content formats if the content property refers
  /// to a `literal of type MarkupContent`. The order describes the preferred
  /// format of the client.
  final List<MarkupKind>? contentFormat;

  /// Whether hover supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (contentFormat != null) {
      result['contentFormat'] =
          contentFormat?.map((item) => item.toJson()).toList();
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('contentFormat');
      try {
        final contentFormat = obj['contentFormat'];
        if (contentFormat != null &&
            (contentFormat is! List<Object?> ||
                contentFormat
                    .any((item) => !MarkupKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<MarkupKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type HoverClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is HoverClientCapabilities &&
        other.runtimeType == HoverClientCapabilities) {
      return listEqual(contentFormat, other.contentFormat,
              (MarkupKind a, MarkupKind b) => a == b) &&
          dynamicRegistration == other.dynamicRegistration &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(contentFormat),
        dynamicRegistration,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class HoverOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverOptions.canParse,
    HoverOptions.fromJson,
  );

  HoverOptions({
    this.workDoneProgress,
  });
  static HoverOptions fromJson(Map<String, Object?> json) {
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return HoverOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type HoverOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is HoverOptions && other.runtimeType == HoverOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class HoverParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverParams.canParse,
    HoverParams.fromJson,
  );

  HoverParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static HoverParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return HoverParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type HoverParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is HoverParams && other.runtimeType == HoverParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class HoverRegistrationOptions
    implements HoverOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverRegistrationOptions.canParse,
    HoverRegistrationOptions.fromJson,
  );

  HoverRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static HoverRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return HoverRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type HoverRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is HoverRegistrationOptions &&
        other.runtimeType == HoverRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (linkSupport != null) {
      result['linkSupport'] = linkSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        final linkSupport = obj['linkSupport'];
        if (linkSupport != null && linkSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ImplementationClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ImplementationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationParams.canParse,
    ImplementationParams.fromJson,
  );

  ImplementationParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static ImplementationParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return ImplementationParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ImplementationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ImplementationParams &&
        other.runtimeType == ImplementationParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ImplementationRegistrationOptions
    implements
        ImplementationOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationRegistrationOptions.canParse,
    ImplementationRegistrationOptions.fromJson,
  );

  ImplementationRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static ImplementationRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ImplementationRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ImplementationRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ImplementationRegistrationOptions &&
        other.runtimeType == ImplementationRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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 InitializeParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeParams.canParse,
    InitializeParams.fromJson,
  );

  InitializeParams({
    required this.capabilities,
    this.clientInfo,
    this.initializationOptions,
    this.locale,
    this.processId,
    this.rootPath,
    this.rootUri,
    this.trace,
    this.workDoneToken,
    this.workspaceFolders,
  });
  static InitializeParams fromJson(Map<String, Object?> json) {
    final capabilitiesJson = json['capabilities'];
    final capabilities =
        ClientCapabilities.fromJson(capabilitiesJson as Map<String, Object?>);
    final clientInfoJson = json['clientInfo'];
    final clientInfo = clientInfoJson != null
        ? InitializeParamsClientInfo.fromJson(
            clientInfoJson as Map<String, Object?>)
        : null;
    final initializationOptionsJson = json['initializationOptions'];
    final initializationOptions = initializationOptionsJson;
    final localeJson = json['locale'];
    final locale = localeJson as String?;
    final processIdJson = json['processId'];
    final processId = processIdJson as int?;
    final rootPathJson = json['rootPath'];
    final rootPath = rootPathJson as String?;
    final rootUriJson = json['rootUri'];
    final rootUri = rootUriJson as String?;
    final traceJson = json['trace'];
    final trace = const {null, 'off', 'messages', 'verbose'}.contains(traceJson)
        ? traceJson as String?
        : throw '''$traceJson was not one of (null, 'off', 'messages', 'verbose')''';
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = (workspaceFoldersJson as List<Object?>?)
        ?.map((item) => WorkspaceFolder.fromJson(item as Map<String, Object?>))
        .toList();
    return InitializeParams(
      capabilities: capabilities,
      clientInfo: clientInfo,
      initializationOptions: initializationOptions,
      locale: locale,
      processId: processId,
      rootPath: rootPath,
      rootUri: rootUri,
      trace: trace,
      workDoneToken: workDoneToken,
      workspaceFolders: workspaceFolders,
    );
  }

  /// The capabilities provided by the client (editor or tool)
  final ClientCapabilities capabilities;

  /// Information about the client
  ///  @since 3.15.0
  final InitializeParamsClientInfo? clientInfo;

  /// User provided initialization options.
  final Object? initializationOptions;

  /// The locale the client is currently showing the user interface in. This
  /// must not necessarily be the locale of the operating system.
  ///
  /// Uses IETF language tags as the value's syntax (See
  /// https://en.wikipedia.org/wiki/IETF_language_tag)
  ///  @since 3.16.0
  final String? locale;

  /// The process Id of the parent process that started the server. Is null if
  /// the process has not been started by another process. If the parent process
  /// is not alive then the server should exit (see exit notification) its
  /// process.
  final int? processId;

  /// The rootPath of the workspace. Is null if no folder is open.
  ///  @deprecated in favour of `rootUri`.
  final String? rootPath;

  /// The rootUri of the workspace. Is null if no folder is open. If both
  /// `rootPath` and `rootUri` are set `rootUri` wins.
  ///  @deprecated in favour of `workspaceFolders`
  final String? rootUri;

  /// The initial trace setting. If omitted trace is disabled ('off').
  final String? trace;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  /// The workspace folders configured in the client when the server starts.
  /// This property is only available if the client supports workspace folders.
  /// It can be `null` if the client supports workspace folders but none are
  /// configured.
  ///  @since 3.6.0
  final List<WorkspaceFolder>? workspaceFolders;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['capabilities'] = capabilities.toJson();
    if (clientInfo != null) {
      result['clientInfo'] = clientInfo?.toJson();
    }
    if (initializationOptions != null) {
      result['initializationOptions'] = initializationOptions;
    }
    if (locale != null) {
      result['locale'] = locale;
    }
    result['processId'] = processId;
    if (rootPath != null) {
      result['rootPath'] = rootPath;
    }
    result['rootUri'] = rootUri;
    if (trace != null) {
      result['trace'] = trace;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    if (workspaceFolders != null) {
      result['workspaceFolders'] =
          workspaceFolders?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('capabilities');
      try {
        if (!obj.containsKey('capabilities')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final capabilities = obj['capabilities'];
        if (capabilities == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!ClientCapabilities.canParse(capabilities, reporter)) {
          reporter.reportError('must be of type ClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('clientInfo');
      try {
        final clientInfo = obj['clientInfo'];
        if (clientInfo != null &&
            !InitializeParamsClientInfo.canParse(clientInfo, reporter)) {
          reporter.reportError('must be of type InitializeParamsClientInfo');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('locale');
      try {
        final locale = obj['locale'];
        if (locale != null && locale is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('processId');
      try {
        if (!obj.containsKey('processId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final processId = obj['processId'];
        if (processId != null && processId is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rootPath');
      try {
        final rootPath = obj['rootPath'];
        if (rootPath != null && rootPath is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rootUri');
      try {
        if (!obj.containsKey('rootUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final rootUri = obj['rootUri'];
        if (rootUri != null && rootUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('trace');
      try {
        final trace = obj['trace'];
        if (trace != null &&
            trace != 'off' &&
            trace != 'messages' &&
            trace != 'verbose') {
          reporter.reportError(
              'must be one of the literals \'off\', \'messages\', \'verbose\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceFolders');
      try {
        final workspaceFolders = obj['workspaceFolders'];
        if (workspaceFolders != null &&
            (workspaceFolders is! List<Object?> ||
                workspaceFolders.any(
                    (item) => !WorkspaceFolder.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InitializeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InitializeParams && other.runtimeType == InitializeParams) {
      return capabilities == other.capabilities &&
          clientInfo == other.clientInfo &&
          initializationOptions == other.initializationOptions &&
          locale == other.locale &&
          processId == other.processId &&
          rootPath == other.rootPath &&
          rootUri == other.rootUri &&
          trace == other.trace &&
          workDoneToken == other.workDoneToken &&
          listEqual(workspaceFolders, other.workspaceFolders,
              (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        capabilities,
        clientInfo,
        initializationOptions,
        locale,
        processId,
        rootPath,
        rootUri,
        trace,
        workDoneToken,
        lspHashCode(workspaceFolders),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InitializeParamsClientInfo implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeParamsClientInfo.canParse,
    InitializeParamsClientInfo.fromJson,
  );

  InitializeParamsClientInfo({
    required this.name,
    this.version,
  });
  static InitializeParamsClientInfo fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return InitializeParamsClientInfo(
      name: name,
      version: version,
    );
  }

  /// The name of the client as defined by the client.
  final String name;

  /// The client's version as defined by the client.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['name'] = name;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InitializeParamsClientInfo');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['capabilities'] = capabilities.toJson();
    if (serverInfo != null) {
      result['serverInfo'] = serverInfo?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('capabilities');
      try {
        if (!obj.containsKey('capabilities')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final capabilities = obj['capabilities'];
        if (capabilities == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!ServerCapabilities.canParse(capabilities, reporter)) {
          reporter.reportError('must be of type ServerCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('serverInfo');
      try {
        final serverInfo = obj['serverInfo'];
        if (serverInfo != null &&
            !InitializeResultServerInfo.canParse(serverInfo, reporter)) {
          reporter.reportError('must be of type InitializeResultServerInfo');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InitializeResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['name'] = name;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InitializeResultServerInfo');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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();
  }

  @override
  Map<String, Object?> toJson() => {};

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError('must be of type InitializedParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InitializedParams && other.runtimeType == InitializedParams) {
      return true;
    }
    return false;
  }

  @override
  int get hashCode => 42;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint information.
///  @since 3.17.0
class InlayHint implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHint.canParse,
    InlayHint.fromJson,
  );

  InlayHint({
    this.data,
    this.kind,
    required this.label,
    this.paddingLeft,
    this.paddingRight,
    required this.position,
    this.textEdits,
    this.tooltip,
  });
  static InlayHint fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? InlayHintKind.fromJson(kindJson as int) : null;
    final labelJson = json['label'];
    final label = labelJson is List<Object?> &&
            labelJson.every((item) =>
                InlayHintLabelPart.canParse(item, nullLspJsonReporter))
        ? Either2<List<InlayHintLabelPart>, String>.t1(labelJson
            .map((item) =>
                InlayHintLabelPart.fromJson(item as Map<String, Object?>))
            .toList())
        : (labelJson is String
            ? Either2<List<InlayHintLabelPart>, String>.t2(labelJson)
            : (throw '''$labelJson was not one of (List<InlayHintLabelPart>, String)'''));
    final paddingLeftJson = json['paddingLeft'];
    final paddingLeft = paddingLeftJson as bool?;
    final paddingRightJson = json['paddingRight'];
    final paddingRight = paddingRightJson as bool?;
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textEditsJson = json['textEdits'];
    final textEdits = (textEditsJson as List<Object?>?)
        ?.map((item) => TextEdit.fromJson(item as Map<String, Object?>))
        .toList();
    final tooltipJson = json['tooltip'];
    final tooltip = tooltipJson == null
        ? null
        : (MarkupContent.canParse(tooltipJson, nullLspJsonReporter)
            ? Either2<MarkupContent, String>.t1(
                MarkupContent.fromJson(tooltipJson as Map<String, Object?>))
            : (tooltipJson is String
                ? Either2<MarkupContent, String>.t2(tooltipJson)
                : (throw '''$tooltipJson was not one of (MarkupContent, String)''')));
    return InlayHint(
      data: data,
      kind: kind,
      label: label,
      paddingLeft: paddingLeft,
      paddingRight: paddingRight,
      position: position,
      textEdits: textEdits,
      tooltip: tooltip,
    );
  }

  /// A data entry field that is preserved on a inlay hint between a
  /// `textDocument/inlayHint` and a `inlayHint/resolve` request.
  final Object? data;

  /// The kind of this hint. Can be omitted in which case the client should fall
  /// back to a reasonable default.
  final InlayHintKind? kind;

  /// The label of this hint. A human readable string or an array of
  /// InlayHintLabelPart label parts.
  ///
  /// *Note* that neither the string nor the label part can be empty.
  final Either2<List<InlayHintLabelPart>, String> label;

  /// Render padding before the hint.
  ///
  /// Note: Padding should use the editor's background color, not the background
  /// color of the hint itself. That means padding can be used to visually
  /// align/separate an inlay hint.
  final bool? paddingLeft;

  /// Render padding after the hint.
  ///
  /// Note: Padding should use the editor's background color, not the background
  /// color of the hint itself. That means padding can be used to visually
  /// align/separate an inlay hint.
  final bool? paddingRight;

  /// The position of this hint.
  final Position position;

  /// Optional text edits that are performed when accepting this inlay hint.
  ///
  /// *Note* that edits are expected to change the document so that the inlay
  /// hint (or its nearest variant) is now part of the document and the inlay
  /// hint itself is now obsolete.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final List<TextEdit>? textEdits;

  /// The tooltip text when you hover over this item.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final Either2<MarkupContent, String>? tooltip;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['label'] = label;
    if (paddingLeft != null) {
      result['paddingLeft'] = paddingLeft;
    }
    if (paddingRight != null) {
      result['paddingRight'] = paddingRight;
    }
    result['position'] = position.toJson();
    if (textEdits != null) {
      result['textEdits'] = textEdits?.map((item) => item.toJson()).toList();
    }
    if (tooltip != null) {
      result['tooltip'] = tooltip;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !InlayHintKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type InlayHintKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final label = obj['label'];
        if (label == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (label is! List<Object?> ||
            label.any((item) => !InlayHintLabelPart.canParse(item, reporter)) &&
                label is! String) {
          reporter.reportError(
              'must be of type Either2<List<InlayHintLabelPart>, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('paddingLeft');
      try {
        final paddingLeft = obj['paddingLeft'];
        if (paddingLeft != null && paddingLeft is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('paddingRight');
      try {
        final paddingRight = obj['paddingRight'];
        if (paddingRight != null && paddingRight is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textEdits');
      try {
        final textEdits = obj['textEdits'];
        if (textEdits != null &&
            (textEdits is! List<Object?> ||
                textEdits.any((item) => !TextEdit.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<TextEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tooltip');
      try {
        final tooltip = obj['tooltip'];
        if (tooltip != null &&
            !MarkupContent.canParse(tooltip, reporter) &&
            tooltip is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHint');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlayHint && other.runtimeType == InlayHint) {
      return data == other.data &&
          kind == other.kind &&
          label == other.label &&
          paddingLeft == other.paddingLeft &&
          paddingRight == other.paddingRight &&
          position == other.position &&
          listEqual(
              textEdits, other.textEdits, (TextEdit a, TextEdit b) => a == b) &&
          tooltip == other.tooltip &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        data,
        kind,
        label,
        paddingLeft,
        paddingRight,
        position,
        lspHashCode(textEdits),
        tooltip,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint client capabilities.
///  @since 3.17.0
class InlayHintClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintClientCapabilities.canParse,
    InlayHintClientCapabilities.fromJson,
  );

  InlayHintClientCapabilities({
    this.dynamicRegistration,
    this.resolveSupport,
  });
  static InlayHintClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final resolveSupportJson = json['resolveSupport'];
    final resolveSupport = resolveSupportJson != null
        ? InlayHintClientCapabilitiesResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    return InlayHintClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      resolveSupport: resolveSupport,
    );
  }

  /// Whether inlay hints support dynamic registration.
  final bool? dynamicRegistration;

  /// Indicates which properties a client can resolve lazily on a inlay hint.
  final InlayHintClientCapabilitiesResolveSupport? resolveSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (resolveSupport != null) {
      result['resolveSupport'] = resolveSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveSupport');
      try {
        final resolveSupport = obj['resolveSupport'];
        if (resolveSupport != null &&
            !InlayHintClientCapabilitiesResolveSupport.canParse(
                resolveSupport, reporter)) {
          reporter.reportError(
              'must be of type InlayHintClientCapabilitiesResolveSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlayHintClientCapabilities &&
        other.runtimeType == InlayHintClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          resolveSupport == other.resolveSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        resolveSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InlayHintClientCapabilitiesResolveSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintClientCapabilitiesResolveSupport.canParse,
    InlayHintClientCapabilitiesResolveSupport.fromJson,
  );

  InlayHintClientCapabilitiesResolveSupport({
    required this.properties,
  });
  static InlayHintClientCapabilitiesResolveSupport fromJson(
      Map<String, Object?> json) {
    final propertiesJson = json['properties'];
    final properties = (propertiesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return InlayHintClientCapabilitiesResolveSupport(
      properties: properties,
    );
  }

  /// The properties that a client can resolve lazily.
  final List<String> properties;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['properties'] = properties;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('properties');
      try {
        if (!obj.containsKey('properties')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final properties = obj['properties'];
        if (properties == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (properties is! List<Object?> ||
            properties.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type InlayHintClientCapabilitiesResolveSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlayHintClientCapabilitiesResolveSupport &&
        other.runtimeType == InlayHintClientCapabilitiesResolveSupport) {
      return listEqual(
              properties, other.properties, (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(properties);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint kinds.
///  @since 3.17.0
class InlayHintKind implements ToJsonable {
  const InlayHintKind(this._value);
  const InlayHintKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// An inlay hint that is for a parameter.
  static const Parameter = InlayHintKind(2);

  /// An inlay hint that for a type annotation.
  static const Type = InlayHintKind(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is InlayHintKind && other._value == _value;
}

/// An inlay hint label part allows for interactive and composite labels of
/// inlay hints.
///  @since 3.17.0
class InlayHintLabelPart implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintLabelPart.canParse,
    InlayHintLabelPart.fromJson,
  );

  InlayHintLabelPart({
    this.command,
    this.location,
    this.tooltip,
    required this.value,
  });
  static InlayHintLabelPart fromJson(Map<String, Object?> json) {
    final commandJson = json['command'];
    final command = commandJson != null
        ? Command.fromJson(commandJson as Map<String, Object?>)
        : null;
    final locationJson = json['location'];
    final location = locationJson != null
        ? Location.fromJson(locationJson as Map<String, Object?>)
        : null;
    final tooltipJson = json['tooltip'];
    final tooltip = tooltipJson == null
        ? null
        : (MarkupContent.canParse(tooltipJson, nullLspJsonReporter)
            ? Either2<MarkupContent, String>.t1(
                MarkupContent.fromJson(tooltipJson as Map<String, Object?>))
            : (tooltipJson is String
                ? Either2<MarkupContent, String>.t2(tooltipJson)
                : (throw '''$tooltipJson was not one of (MarkupContent, String)''')));
    final valueJson = json['value'];
    final value = valueJson as String;
    return InlayHintLabelPart(
      command: command,
      location: location,
      tooltip: tooltip,
      value: value,
    );
  }

  /// An optional command for this label part.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final Command? command;

  /// An optional source code location that represents this label part.
  ///
  /// The editor will use this location for the hover and for code navigation
  /// features: This part will become a clickable link that resolves to the
  /// definition of the symbol at the given location (not necessarily the
  /// location itself), it shows the hover that shows at the given location, and
  /// it shows a context menu with further code navigation commands.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final Location? location;

  /// The tooltip text when you hover over this label part. Depending on the
  /// client capability `inlayHint.resolveSupport` clients might resolve this
  /// property late using the resolve request.
  final Either2<MarkupContent, String>? tooltip;

  /// The value of this label part.
  final String value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (command != null) {
      result['command'] = command?.toJson();
    }
    if (location != null) {
      result['location'] = location?.toJson();
    }
    if (tooltip != null) {
      result['tooltip'] = tooltip;
    }
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('command');
      try {
        final command = obj['command'];
        if (command != null && !Command.canParse(command, reporter)) {
          reporter.reportError('must be of type Command');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('location');
      try {
        final location = obj['location'];
        if (location != null && !Location.canParse(location, reporter)) {
          reporter.reportError('must be of type Location');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tooltip');
      try {
        final tooltip = obj['tooltip'];
        if (tooltip != null &&
            !MarkupContent.canParse(tooltip, reporter) &&
            tooltip is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final value = obj['value'];
        if (value == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (value is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintLabelPart');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlayHintLabelPart &&
        other.runtimeType == InlayHintLabelPart) {
      return command == other.command &&
          location == other.location &&
          tooltip == other.tooltip &&
          value == other.value &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        command,
        location,
        tooltip,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint options used during static registration.
///  @since 3.17.0
class InlayHintOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintOptions.canParse,
    InlayHintOptions.fromJson,
  );

  InlayHintOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static InlayHintOptions fromJson(Map<String, Object?> json) {
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlayHintOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The server provides support to resolve additional information for an inlay
  /// hint item.
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlayHintOptions && other.runtimeType == InlayHintOptions) {
      return resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in inlay hint requests.
///  @since 3.17.0
class InlayHintParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintParams.canParse,
    InlayHintParams.fromJson,
  );

  InlayHintParams({
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static InlayHintParams fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return InlayHintParams(
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The visible document range for which inlay hints should be computed.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlayHintParams && other.runtimeType == InlayHintParams) {
      return range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint options used during static or dynamic registration.
///  @since 3.17.0
class InlayHintRegistrationOptions
    implements
        InlayHintOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintRegistrationOptions.canParse,
    InlayHintRegistrationOptions.fromJson,
  );

  InlayHintRegistrationOptions({
    this.documentSelector,
    this.id,
    this.resolveProvider,
    this.workDoneProgress,
  });
  static InlayHintRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlayHintRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// The server provides support to resolve additional information for an inlay
  /// hint item.
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlayHintRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlayHintRegistrationOptions &&
        other.runtimeType == InlayHintRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          id == other.id &&
          resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client workspace capabilities specific to inlay hints.
///  @since 3.17.0
class InlayHintWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintWorkspaceClientCapabilities.canParse,
    InlayHintWorkspaceClientCapabilities.fromJson,
  );

  InlayHintWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static InlayHintWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return InlayHintWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// inlay hints currently shown. It should be used with absolute care and is
  /// useful for situation where a server for example detects a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('refreshSupport');
      try {
        final refreshSupport = obj['refreshSupport'];
        if (refreshSupport != null && refreshSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type InlayHintWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlayHintWorkspaceClientCapabilities &&
        other.runtimeType == InlayHintWorkspaceClientCapabilities) {
      return refreshSupport == other.refreshSupport && true;
    }
    return false;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to inline values.
///  @since 3.17.0
class InlineValueClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueClientCapabilities.canParse,
    InlineValueClientCapabilities.fromJson,
  );

  InlineValueClientCapabilities({
    this.dynamicRegistration,
  });
  static InlineValueClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return InlineValueClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration for inline value
  /// providers.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlineValueClientCapabilities &&
        other.runtimeType == InlineValueClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.17.0
class InlineValueContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueContext.canParse,
    InlineValueContext.fromJson,
  );

  InlineValueContext({
    required this.frameId,
    required this.stoppedLocation,
  });
  static InlineValueContext fromJson(Map<String, Object?> json) {
    final frameIdJson = json['frameId'];
    final frameId = frameIdJson as int;
    final stoppedLocationJson = json['stoppedLocation'];
    final stoppedLocation =
        Range.fromJson(stoppedLocationJson as Map<String, Object?>);
    return InlineValueContext(
      frameId: frameId,
      stoppedLocation: stoppedLocation,
    );
  }

  /// The stack frame (as a DAP Id) where the execution has stopped.
  final int frameId;

  /// The document range where execution has stopped. Typically the end position
  /// of the range denotes the line where the inline values are shown.
  final Range stoppedLocation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['frameId'] = frameId;
    result['stoppedLocation'] = stoppedLocation.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('frameId');
      try {
        if (!obj.containsKey('frameId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final frameId = obj['frameId'];
        if (frameId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (frameId is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('stoppedLocation');
      try {
        if (!obj.containsKey('stoppedLocation')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final stoppedLocation = obj['stoppedLocation'];
        if (stoppedLocation == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(stoppedLocation, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlineValueContext &&
        other.runtimeType == InlineValueContext) {
      return frameId == other.frameId &&
          stoppedLocation == other.stoppedLocation &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        frameId,
        stoppedLocation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provide an inline value through an expression evaluation.
///
/// If only a range is specified, the expression will be extracted from the
/// underlying document.
///
/// An optional expression can be used to override the extracted expression.
///  @since 3.17.0
class InlineValueEvaluatableExpression implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueEvaluatableExpression.canParse,
    InlineValueEvaluatableExpression.fromJson,
  );

  InlineValueEvaluatableExpression({
    this.expression,
    required this.range,
  });
  static InlineValueEvaluatableExpression fromJson(Map<String, Object?> json) {
    final expressionJson = json['expression'];
    final expression = expressionJson as String?;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return InlineValueEvaluatableExpression(
      expression: expression,
      range: range,
    );
  }

  /// If specified the expression overrides the extracted expression.
  final String? expression;

  /// The document range for which the inline value applies. The range is used
  /// to extract the evaluatable expression from the underlying document.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (expression != null) {
      result['expression'] = expression;
    }
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('expression');
      try {
        final expression = obj['expression'];
        if (expression != null && expression is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueEvaluatableExpression');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlineValueEvaluatableExpression &&
        other.runtimeType == InlineValueEvaluatableExpression) {
      return expression == other.expression && range == other.range && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        expression,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inline value options used during static registration.
///  @since 3.17.0
class InlineValueOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueOptions.canParse,
    InlineValueOptions.fromJson,
  );

  InlineValueOptions({
    this.workDoneProgress,
  });
  static InlineValueOptions fromJson(Map<String, Object?> json) {
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlineValueOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlineValueOptions &&
        other.runtimeType == InlineValueOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in inline value requests.
///  @since 3.17.0
class InlineValueParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueParams.canParse,
    InlineValueParams.fromJson,
  );

  InlineValueParams({
    required this.context,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static InlineValueParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context =
        InlineValueContext.fromJson(contextJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return InlineValueParams(
      context: context,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// Additional information about the context in which inline values were
  /// requested.
  final InlineValueContext context;

  /// The document range for which inline values should be computed.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['context'] = context.toJson();
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('context');
      try {
        if (!obj.containsKey('context')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final context = obj['context'];
        if (context == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!InlineValueContext.canParse(context, reporter)) {
          reporter.reportError('must be of type InlineValueContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlineValueParams && other.runtimeType == InlineValueParams) {
      return context == other.context &&
          range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        context,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inline value options used during static or dynamic registration.
///  @since 3.17.0
class InlineValueRegistrationOptions
    implements
        InlineValueOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueRegistrationOptions.canParse,
    InlineValueRegistrationOptions.fromJson,
  );

  InlineValueRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static InlineValueRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlineValueRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlineValueRegistrationOptions &&
        other.runtimeType == InlineValueRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provide inline value as text.
///  @since 3.17.0
class InlineValueText implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueText.canParse,
    InlineValueText.fromJson,
  );

  InlineValueText({
    required this.range,
    required this.text,
  });
  static InlineValueText fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textJson = json['text'];
    final text = textJson as String;
    return InlineValueText(
      range: range,
      text: text,
    );
  }

  /// The document range for which the inline value applies.
  final Range range;

  /// The text of the inline value.
  final String text;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    result['text'] = text;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final text = obj['text'];
        if (text == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (text is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueText');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlineValueText && other.runtimeType == InlineValueText) {
      return range == other.range && text == other.text && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        range,
        text,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provide inline value through a variable lookup.
///
/// If only a range is specified, the variable name will be extracted from the
/// underlying document.
///
/// An optional variable name can be used to override the extracted name.
///  @since 3.17.0
class InlineValueVariableLookup implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueVariableLookup.canParse,
    InlineValueVariableLookup.fromJson,
  );

  InlineValueVariableLookup({
    required this.caseSensitiveLookup,
    required this.range,
    this.variableName,
  });
  static InlineValueVariableLookup fromJson(Map<String, Object?> json) {
    final caseSensitiveLookupJson = json['caseSensitiveLookup'];
    final caseSensitiveLookup = caseSensitiveLookupJson as bool;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final variableNameJson = json['variableName'];
    final variableName = variableNameJson as String?;
    return InlineValueVariableLookup(
      caseSensitiveLookup: caseSensitiveLookup,
      range: range,
      variableName: variableName,
    );
  }

  /// How to perform the lookup.
  final bool caseSensitiveLookup;

  /// The document range for which the inline value applies. The range is used
  /// to extract the variable name from the underlying document.
  final Range range;

  /// If specified the name of the variable to look up.
  final String? variableName;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['caseSensitiveLookup'] = caseSensitiveLookup;
    result['range'] = range.toJson();
    if (variableName != null) {
      result['variableName'] = variableName;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('caseSensitiveLookup');
      try {
        if (!obj.containsKey('caseSensitiveLookup')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final caseSensitiveLookup = obj['caseSensitiveLookup'];
        if (caseSensitiveLookup == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (caseSensitiveLookup is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('variableName');
      try {
        final variableName = obj['variableName'];
        if (variableName != null && variableName is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InlineValueVariableLookup');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlineValueVariableLookup &&
        other.runtimeType == InlineValueVariableLookup) {
      return caseSensitiveLookup == other.caseSensitiveLookup &&
          range == other.range &&
          variableName == other.variableName &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        caseSensitiveLookup,
        range,
        variableName,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client workspace capabilities specific to inline values.
///  @since 3.17.0
class InlineValueWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueWorkspaceClientCapabilities.canParse,
    InlineValueWorkspaceClientCapabilities.fromJson,
  );

  InlineValueWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static InlineValueWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return InlineValueWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// inline values currently shown. It should be used with absolute care and is
  /// useful for situation where a server for example detect a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('refreshSupport');
      try {
        final refreshSupport = obj['refreshSupport'];
        if (refreshSupport != null && refreshSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type InlineValueWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InlineValueWorkspaceClientCapabilities &&
        other.runtimeType == InlineValueWorkspaceClientCapabilities) {
      return refreshSupport == other.refreshSupport && true;
    }
    return false;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A special text edit to provide an insert and a replace operation.
///  @since 3.16.0
class InsertReplaceEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InsertReplaceEdit.canParse,
    InsertReplaceEdit.fromJson,
  );

  InsertReplaceEdit({
    required this.insert,
    required this.newText,
    required this.replace,
  });
  static InsertReplaceEdit fromJson(Map<String, Object?> json) {
    final insertJson = json['insert'];
    final insert = Range.fromJson(insertJson as Map<String, Object?>);
    final newTextJson = json['newText'];
    final newText = newTextJson as String;
    final replaceJson = json['replace'];
    final replace = Range.fromJson(replaceJson as Map<String, Object?>);
    return InsertReplaceEdit(
      insert: insert,
      newText: newText,
      replace: replace,
    );
  }

  /// The range if the insert is requested
  final Range insert;

  /// The string to be inserted.
  final String newText;

  /// The range if the replace is requested.
  final Range replace;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['insert'] = insert.toJson();
    result['newText'] = newText;
    result['replace'] = replace.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('insert');
      try {
        if (!obj.containsKey('insert')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final insert = obj['insert'];
        if (insert == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(insert, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('newText');
      try {
        if (!obj.containsKey('newText')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newText = obj['newText'];
        if (newText == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('replace');
      try {
        if (!obj.containsKey('replace')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final replace = obj['replace'];
        if (replace == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(replace, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InsertReplaceEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is InsertReplaceEdit && other.runtimeType == InsertReplaceEdit) {
      return insert == other.insert &&
          newText == other.newText &&
          replace == other.replace &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        insert,
        newText,
        replace,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines whether the insert text in a completion item should be interpreted
/// as plain text or a snippet.
class InsertTextFormat implements ToJsonable {
  const InsertTextFormat._(this._value);
  const InsertTextFormat.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 1:
      case 2:
        return true;
    }
    return false;
  }

  /// The primary text to be inserted is treated as a plain string.
  static const PlainText = InsertTextFormat._(1);

  /// The primary text to be inserted is treated as a snippet.
  ///
  /// A snippet can define tab stops and placeholders with `$1`, `$2` and
  /// `${3:foo}`. `$0` defines the final tab stop, it defaults to the end of the
  /// snippet. Placeholders with equal identifiers are linked, that is typing in
  /// one will update others too.
  static const Snippet = InsertTextFormat._(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is InsertTextFormat && other._value == _value;
}

/// How whitespace and indentation is handled during completion item insertion.
///  @since 3.16.0
class InsertTextMode implements ToJsonable {
  const InsertTextMode(this._value);
  const InsertTextMode.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// The editor adjusts leading whitespace of new lines so that they match the
  /// indentation up to the cursor of the line for which the item is accepted.
  ///
  /// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a multi
  /// line completion item is indented using 2 tabs and all following lines
  /// inserted will be indented using 2 tabs as well.
  static const adjustIndentation = InsertTextMode(2);

  /// The insertion or replace strings is taken as it is. If the value is multi
  /// line the lines below the cursor will be inserted using the indentation
  /// defined in the string value. The client will not apply any kind of
  /// adjustments to the string.
  static const asIs = InsertTextMode(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is InsertTextMode && other._value == _value;
}

class LinkedEditingRangeClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeClientCapabilities.canParse,
    LinkedEditingRangeClientCapabilities.fromJson,
  );

  LinkedEditingRangeClientCapabilities({
    this.dynamicRegistration,
  });
  static LinkedEditingRangeClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return LinkedEditingRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type LinkedEditingRangeClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LinkedEditingRangeOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is LinkedEditingRangeOptions &&
        other.runtimeType == LinkedEditingRangeOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LinkedEditingRangeParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeParams.canParse,
    LinkedEditingRangeParams.fromJson,
  );

  LinkedEditingRangeParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static LinkedEditingRangeParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return LinkedEditingRangeParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LinkedEditingRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is LinkedEditingRangeParams &&
        other.runtimeType == LinkedEditingRangeParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LinkedEditingRangeRegistrationOptions
    implements
        LinkedEditingRangeOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeRegistrationOptions.canParse,
    LinkedEditingRangeRegistrationOptions.fromJson,
  );

  LinkedEditingRangeRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static LinkedEditingRangeRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return LinkedEditingRangeRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type LinkedEditingRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is LinkedEditingRangeRegistrationOptions &&
        other.runtimeType == LinkedEditingRangeRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LinkedEditingRanges implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRanges.canParse,
    LinkedEditingRanges.fromJson,
  );

  LinkedEditingRanges({
    required this.ranges,
    this.wordPattern,
  });
  static LinkedEditingRanges fromJson(Map<String, Object?> json) {
    final rangesJson = json['ranges'];
    final ranges = (rangesJson as List<Object?>)
        .map((item) => Range.fromJson(item as Map<String, Object?>))
        .toList();
    final wordPatternJson = json['wordPattern'];
    final wordPattern = wordPatternJson as String?;
    return LinkedEditingRanges(
      ranges: ranges,
      wordPattern: wordPattern,
    );
  }

  /// A list of ranges that can be renamed together. The ranges must have
  /// identical length and contain identical text content. The ranges cannot
  /// overlap.
  final List<Range> ranges;

  /// An optional word pattern (regular expression) that describes valid
  /// contents for the given ranges. If no pattern is provided, the client
  /// configuration's word pattern will be used.
  final String? wordPattern;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['ranges'] = ranges.map((item) => item.toJson()).toList();
    if (wordPattern != null) {
      result['wordPattern'] = wordPattern;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ranges');
      try {
        if (!obj.containsKey('ranges')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final ranges = obj['ranges'];
        if (ranges == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (ranges is! List<Object?> ||
            ranges.any((item) => !Range.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Range>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('wordPattern');
      try {
        final wordPattern = obj['wordPattern'];
        if (wordPattern != null && wordPattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LinkedEditingRanges');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is LinkedEditingRanges &&
        other.runtimeType == LinkedEditingRanges) {
      return listEqual(ranges, other.ranges, (Range a, Range b) => a == b) &&
          wordPattern == other.wordPattern &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(ranges),
        wordPattern,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class Location implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Location.canParse,
    Location.fromJson,
  );

  Location({
    required this.range,
    required this.uri,
  });
  static Location fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return Location(
      range: range,
      uri: uri,
    );
  }

  final Range range;
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Location');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is Location && other.runtimeType == Location) {
      return range == other.range && uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        range,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LocationLink implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LocationLink.canParse,
    LocationLink.fromJson,
  );

  LocationLink({
    this.originSelectionRange,
    required this.targetRange,
    required this.targetSelectionRange,
    required this.targetUri,
  });
  static LocationLink fromJson(Map<String, Object?> json) {
    final originSelectionRangeJson = json['originSelectionRange'];
    final originSelectionRange = originSelectionRangeJson != null
        ? Range.fromJson(originSelectionRangeJson as Map<String, Object?>)
        : null;
    final targetRangeJson = json['targetRange'];
    final targetRange = Range.fromJson(targetRangeJson as Map<String, Object?>);
    final targetSelectionRangeJson = json['targetSelectionRange'];
    final targetSelectionRange =
        Range.fromJson(targetSelectionRangeJson as Map<String, Object?>);
    final targetUriJson = json['targetUri'];
    final targetUri = targetUriJson as String;
    return LocationLink(
      originSelectionRange: originSelectionRange,
      targetRange: targetRange,
      targetSelectionRange: targetSelectionRange,
      targetUri: targetUri,
    );
  }

  /// Span of the origin of this link.
  ///
  /// Used as the underlined span for mouse interaction. Defaults to the word
  /// range at the mouse position.
  final Range? originSelectionRange;

  /// The full target range of this link. If the target for example is a symbol
  /// then target range is the range enclosing this symbol not including
  /// leading/trailing whitespace but everything else like comments. This
  /// information is typically used to highlight the range in the editor.
  final Range targetRange;

  /// The range that should be selected and revealed when this link is being
  /// followed, e.g the name of a function. Must be contained by the the
  /// `targetRange`. See also `DocumentSymbol#range`
  final Range targetSelectionRange;

  /// The target resource identifier of this link.
  final String targetUri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (originSelectionRange != null) {
      result['originSelectionRange'] = originSelectionRange?.toJson();
    }
    result['targetRange'] = targetRange.toJson();
    result['targetSelectionRange'] = targetSelectionRange.toJson();
    result['targetUri'] = targetUri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('originSelectionRange');
      try {
        final originSelectionRange = obj['originSelectionRange'];
        if (originSelectionRange != null &&
            !Range.canParse(originSelectionRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('targetRange');
      try {
        if (!obj.containsKey('targetRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final targetRange = obj['targetRange'];
        if (targetRange == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(targetRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('targetSelectionRange');
      try {
        if (!obj.containsKey('targetSelectionRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final targetSelectionRange = obj['targetSelectionRange'];
        if (targetSelectionRange == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(targetSelectionRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('targetUri');
      try {
        if (!obj.containsKey('targetUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final targetUri = obj['targetUri'];
        if (targetUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (targetUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LocationLink');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is LocationLink && other.runtimeType == LocationLink) {
      return originSelectionRange == other.originSelectionRange &&
          targetRange == other.targetRange &&
          targetSelectionRange == other.targetSelectionRange &&
          targetUri == other.targetUri &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        originSelectionRange,
        targetRange,
        targetSelectionRange,
        targetUri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LogMessageParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LogMessageParams.canParse,
    LogMessageParams.fromJson,
  );

  LogMessageParams({
    required this.message,
    required this.type,
  });
  static LogMessageParams fromJson(Map<String, Object?> json) {
    final messageJson = json['message'];
    final message = messageJson as String;
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    return LogMessageParams(
      message: message,
      type: type,
    );
  }

  /// The actual message
  final String message;

  /// The message type.
  final MessageType type;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['message'] = message;
    result['type'] = type.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final type = obj['type'];
        if (type == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MessageType.canParse(type, reporter)) {
          reporter.reportError('must be of type MessageType');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LogMessageParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is LogMessageParams && other.runtimeType == LogMessageParams) {
      return message == other.message && type == other.type && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        message,
        type,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LogTraceParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LogTraceParams.canParse,
    LogTraceParams.fromJson,
  );

  LogTraceParams({
    required this.message,
    this.verbose,
  });
  static LogTraceParams fromJson(Map<String, Object?> json) {
    final messageJson = json['message'];
    final message = messageJson as String;
    final verboseJson = json['verbose'];
    final verbose = verboseJson as String?;
    return LogTraceParams(
      message: message,
      verbose: verbose,
    );
  }

  /// The message to be logged.
  final String message;

  /// Additional information that can be computed if the `trace` configuration
  /// is set to `'verbose'`
  final String? verbose;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['message'] = message;
    if (verbose != null) {
      result['verbose'] = verbose;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('verbose');
      try {
        final verbose = obj['verbose'];
        if (verbose != null && verbose is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LogTraceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is LogTraceParams && other.runtimeType == LogTraceParams) {
      return message == other.message && verbose == other.verbose && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        message,
        verbose,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to the used markdown parser.
///  @since 3.16.0
class MarkdownClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MarkdownClientCapabilities.canParse,
    MarkdownClientCapabilities.fromJson,
  );

  MarkdownClientCapabilities({
    this.allowedTags,
    required this.parser,
    this.version,
  });
  static MarkdownClientCapabilities fromJson(Map<String, Object?> json) {
    final allowedTagsJson = json['allowedTags'];
    final allowedTags = (allowedTagsJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final parserJson = json['parser'];
    final parser = parserJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return MarkdownClientCapabilities(
      allowedTags: allowedTags,
      parser: parser,
      version: version,
    );
  }

  /// A list of HTML tags that the client allows / supports in Markdown.
  ///  @since 3.17.0
  final List<String>? allowedTags;

  /// The name of the parser.
  final String parser;

  /// The version of the parser.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (allowedTags != null) {
      result['allowedTags'] = allowedTags;
    }
    result['parser'] = parser;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('allowedTags');
      try {
        final allowedTags = obj['allowedTags'];
        if (allowedTags != null &&
            (allowedTags is! List<Object?> ||
                allowedTags.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('parser');
      try {
        if (!obj.containsKey('parser')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final parser = obj['parser'];
        if (parser == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (parser is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MarkdownClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is MarkdownClientCapabilities &&
        other.runtimeType == MarkdownClientCapabilities) {
      return listEqual(
              allowedTags, other.allowedTags, (String a, String b) => a == b) &&
          parser == other.parser &&
          version == other.version &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(allowedTags),
        parser,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A `MarkupContent` literal represents a string value which content is
/// interpreted base on its kind flag. Currently the protocol supports
/// `plaintext` and `markdown` as markup kinds.
///
/// If the kind is `markdown` then the value can contain fenced code blocks like
/// in GitHub issues.
///
/// Here is an example how such a string can be constructed using JavaScript /
/// TypeScript: ```typescript let markdown: MarkdownContent = {
/// 	kind: MarkupKind.Markdown,
/// 	value: [
/// 		'# Header',
/// 		'Some text',
/// 		'```typescript',
/// 		'someCode();',
/// 		'```'
/// 	].join('\n') }; ```
///
/// *Please Note* that clients might sanitize the return markdown. A client
/// could decide to remove HTML from the markdown to avoid script execution.
class MarkupContent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MarkupContent.canParse,
    MarkupContent.fromJson,
  );

  MarkupContent({
    required this.kind,
    required this.value,
  });
  static MarkupContent fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = MarkupKind.fromJson(kindJson as String);
    final valueJson = json['value'];
    final value = valueJson as String;
    return MarkupContent(
      kind: kind,
      value: value,
    );
  }

  /// The type of the Markup
  final MarkupKind kind;

  /// The content itself
  final String value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind.toJson();
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MarkupKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type MarkupKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final value = obj['value'];
        if (value == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (value is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MarkupContent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 implements ToJsonable {
  const MarkupKind._(this._value);
  const MarkupKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'markdown':
      case 'plaintext':
        return true;
    }
    return false;
  }

  /// Markdown is supported as a content format
  static const Markdown = MarkupKind._('markdown');

  /// Plain text is supported as a content format
  static const PlainText = MarkupKind._('plaintext');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is MarkupKind && other._value == _value;
}

class MessageActionItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MessageActionItem.canParse,
    MessageActionItem.fromJson,
  );

  MessageActionItem({
    required this.title,
  });
  static MessageActionItem fromJson(Map<String, Object?> json) {
    final titleJson = json['title'];
    final title = titleJson as String;
    return MessageActionItem(
      title: title,
    );
  }

  /// A short title like 'Retry', 'Open Log' etc.
  final String title;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['title'] = title;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('title');
      try {
        if (!obj.containsKey('title')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final title = obj['title'];
        if (title == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (title is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MessageActionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 implements ToJsonable {
  const MessageType(this._value);
  const MessageType.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// An error message.
  static const Error = MessageType(1);

  /// An information message.
  static const Info = MessageType(3);

  /// A log message.
  static const Log = MessageType(4);

  /// A warning message.
  static const Warning = MessageType(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is MessageType && other._value == _value;
}

/// Valid LSP methods known at the time of code generation from the spec.
class Method implements ToJsonable {
  const Method(this._value);
  const Method.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// Constant for the 'callHierarchy/incomingCalls' method.
  static const callHierarchy_incomingCalls =
      Method('callHierarchy/incomingCalls');

  /// Constant for the 'callHierarchy/outgoingCalls' method.
  static const callHierarchy_outgoingCalls =
      Method('callHierarchy/outgoingCalls');

  /// Constant for the '$/cancelRequest' method.
  static const cancelRequest = Method(r'$/cancelRequest');

  /// Constant for the 'client/registerCapability' method.
  static const client_registerCapability = Method('client/registerCapability');

  /// Constant for the 'client/unregisterCapability' method.
  static const client_unregisterCapability =
      Method('client/unregisterCapability');

  /// Constant for the 'codeAction/resolve' method.
  static const codeAction_resolve = Method('codeAction/resolve');

  /// Constant for the 'codeLens/resolve' method.
  static const codeLens_resolve = Method('codeLens/resolve');

  /// Constant for the 'completionItem/resolve' method.
  static const completionItem_resolve = Method('completionItem/resolve');

  /// Constant for the 'documentLink/resolve' method.
  static const documentLink_resolve = Method('documentLink/resolve');

  /// Constant for the 'exit' method.
  static const exit = Method('exit');

  /// Constant for the 'initialize' method.
  static const initialize = Method('initialize');

  /// Constant for the 'initialized' method.
  static const initialized = Method('initialized');

  /// Constant for the 'inlayHint/resolve' method.
  static const inlayHint_resolve = Method('inlayHint/resolve');

  /// Constant for the '$/logTrace' method.
  static const logTrace = Method(r'$/logTrace');

  /// Constant for the 'notebookDocument/didChange' method.
  static const notebookDocument_didChange =
      Method('notebookDocument/didChange');

  /// Constant for the 'notebookDocument/didClose' method.
  static const notebookDocument_didClose = Method('notebookDocument/didClose');

  /// Constant for the 'notebookDocument/didOpen' method.
  static const notebookDocument_didOpen = Method('notebookDocument/didOpen');

  /// Constant for the 'notebookDocument/didSave' method.
  static const notebookDocument_didSave = Method('notebookDocument/didSave');

  /// Constant for the '$/progress' method.
  static const progress = Method(r'$/progress');

  /// Constant for the '$/setTrace' method.
  static const setTrace = Method(r'$/setTrace');

  /// Constant for the 'shutdown' method.
  static const shutdown = Method('shutdown');

  /// Constant for the 'telemetry/event' method.
  static const telemetry_event = Method('telemetry/event');

  /// Constant for the 'textDocument/codeAction' method.
  static const textDocument_codeAction = Method('textDocument/codeAction');

  /// Constant for the 'textDocument/codeLens' method.
  static const textDocument_codeLens = Method('textDocument/codeLens');

  /// Constant for the 'textDocument/colorPresentation' method.
  static const textDocument_colorPresentation =
      Method('textDocument/colorPresentation');

  /// Constant for the 'textDocument/completion' method.
  static const textDocument_completion = Method('textDocument/completion');

  /// Constant for the 'textDocument/declaration' method.
  static const textDocument_declaration = Method('textDocument/declaration');

  /// Constant for the 'textDocument/definition' method.
  static const textDocument_definition = Method('textDocument/definition');

  /// Constant for the 'textDocument/diagnostic' method.
  static const textDocument_diagnostic = Method('textDocument/diagnostic');

  /// Constant for the 'textDocument/didChange' method.
  static const textDocument_didChange = Method('textDocument/didChange');

  /// Constant for the 'textDocument/didClose' method.
  static const textDocument_didClose = Method('textDocument/didClose');

  /// Constant for the 'textDocument/didOpen' method.
  static const textDocument_didOpen = Method('textDocument/didOpen');

  /// Constant for the 'textDocument/didSave' method.
  static const textDocument_didSave = Method('textDocument/didSave');

  /// Constant for the 'textDocument/documentColor' method.
  static const textDocument_documentColor =
      Method('textDocument/documentColor');

  /// Constant for the 'textDocument/documentHighlight' method.
  static const textDocument_documentHighlight =
      Method('textDocument/documentHighlight');

  /// Constant for the 'textDocument/documentLink' method.
  static const textDocument_documentLink = Method('textDocument/documentLink');

  /// Constant for the 'textDocument/documentSymbol' method.
  static const textDocument_documentSymbol =
      Method('textDocument/documentSymbol');

  /// Constant for the 'textDocument/foldingRange' method.
  static const textDocument_foldingRange = Method('textDocument/foldingRange');

  /// Constant for the 'textDocument/formatting' method.
  static const textDocument_formatting = Method('textDocument/formatting');

  /// Constant for the 'textDocument/hover' method.
  static const textDocument_hover = Method('textDocument/hover');

  /// Constant for the 'textDocument/implementation' method.
  static const textDocument_implementation =
      Method('textDocument/implementation');

  /// Constant for the 'textDocument/inlayHint' method.
  static const textDocument_inlayHint = Method('textDocument/inlayHint');

  /// Constant for the 'textDocument/inlineValue' method.
  static const textDocument_inlineValue = Method('textDocument/inlineValue');

  /// Constant for the 'textDocument/linkedEditingRange' method.
  static const textDocument_linkedEditingRange =
      Method('textDocument/linkedEditingRange');

  /// Constant for the 'textDocument/moniker' method.
  static const textDocument_moniker = Method('textDocument/moniker');

  /// Constant for the 'textDocument/onTypeFormatting' method.
  static const textDocument_onTypeFormatting =
      Method('textDocument/onTypeFormatting');

  /// Constant for the 'textDocument/prepareCallHierarchy' method.
  static const textDocument_prepareCallHierarchy =
      Method('textDocument/prepareCallHierarchy');

  /// Constant for the 'textDocument/prepareRename' method.
  static const textDocument_prepareRename =
      Method('textDocument/prepareRename');

  /// Constant for the 'textDocument/prepareTypeHierarchy' method.
  static const textDocument_prepareTypeHierarchy =
      Method('textDocument/prepareTypeHierarchy');

  /// Constant for the 'textDocument/publishDiagnostics' method.
  static const textDocument_publishDiagnostics =
      Method('textDocument/publishDiagnostics');

  /// Constant for the 'textDocument/rangeFormatting' method.
  static const textDocument_rangeFormatting =
      Method('textDocument/rangeFormatting');

  /// Constant for the 'textDocument/references' method.
  static const textDocument_references = Method('textDocument/references');

  /// Constant for the 'textDocument/rename' method.
  static const textDocument_rename = Method('textDocument/rename');

  /// Constant for the 'textDocument/selectionRange' method.
  static const textDocument_selectionRange =
      Method('textDocument/selectionRange');

  /// Constant for the 'textDocument/semanticTokens/full' method.
  static const textDocument_semanticTokens_full =
      Method('textDocument/semanticTokens/full');

  /// Constant for the 'textDocument/semanticTokens/full/delta' method.
  static const textDocument_semanticTokens_full_delta =
      Method('textDocument/semanticTokens/full/delta');

  /// Constant for the 'textDocument/semanticTokens/range' method.
  static const textDocument_semanticTokens_range =
      Method('textDocument/semanticTokens/range');

  /// Constant for the 'textDocument/signatureHelp' method.
  static const textDocument_signatureHelp =
      Method('textDocument/signatureHelp');

  /// Constant for the 'textDocument/typeDefinition' method.
  static const textDocument_typeDefinition =
      Method('textDocument/typeDefinition');

  /// Constant for the 'textDocument/willSave' method.
  static const textDocument_willSave = Method('textDocument/willSave');

  /// Constant for the 'textDocument/willSaveWaitUntil' method.
  static const textDocument_willSaveWaitUntil =
      Method('textDocument/willSaveWaitUntil');

  /// Constant for the 'typeHierarchy/subtypes' method.
  static const typeHierarchy_subtypes = Method('typeHierarchy/subtypes');

  /// Constant for the 'typeHierarchy/supertypes' method.
  static const typeHierarchy_supertypes = Method('typeHierarchy/supertypes');

  /// Constant for the 'window/logMessage' method.
  static const window_logMessage = Method('window/logMessage');

  /// Constant for the 'window/showDocument' method.
  static const window_showDocument = Method('window/showDocument');

  /// Constant for the 'window/showMessage' method.
  static const window_showMessage = Method('window/showMessage');

  /// Constant for the 'window/showMessageRequest' method.
  static const window_showMessageRequest = Method('window/showMessageRequest');

  /// Constant for the 'window/workDoneProgress/cancel' method.
  static const window_workDoneProgress_cancel =
      Method('window/workDoneProgress/cancel');

  /// Constant for the 'window/workDoneProgress/create' method.
  static const window_workDoneProgress_create =
      Method('window/workDoneProgress/create');

  /// Constant for the 'workspace/applyEdit' method.
  static const workspace_applyEdit = Method('workspace/applyEdit');

  /// Constant for the 'workspace/codeLens/refresh' method.
  static const workspace_codeLens_refresh =
      Method('workspace/codeLens/refresh');

  /// Constant for the 'workspace/configuration' method.
  static const workspace_configuration = Method('workspace/configuration');

  /// Constant for the 'workspace/diagnostic' method.
  static const workspace_diagnostic = Method('workspace/diagnostic');

  /// Constant for the 'workspace/diagnostic/refresh' method.
  static const workspace_diagnostic_refresh =
      Method('workspace/diagnostic/refresh');

  /// Constant for the 'workspace/didChangeConfiguration' method.
  static const workspace_didChangeConfiguration =
      Method('workspace/didChangeConfiguration');

  /// Constant for the 'workspace/didChangeWatchedFiles' method.
  static const workspace_didChangeWatchedFiles =
      Method('workspace/didChangeWatchedFiles');

  /// Constant for the 'workspace/didChangeWorkspaceFolders' method.
  static const workspace_didChangeWorkspaceFolders =
      Method('workspace/didChangeWorkspaceFolders');

  /// Constant for the 'workspace/didCreateFiles' method.
  static const workspace_didCreateFiles = Method('workspace/didCreateFiles');

  /// Constant for the 'workspace/didDeleteFiles' method.
  static const workspace_didDeleteFiles = Method('workspace/didDeleteFiles');

  /// Constant for the 'workspace/didRenameFiles' method.
  static const workspace_didRenameFiles = Method('workspace/didRenameFiles');

  /// Constant for the 'workspace/executeCommand' method.
  static const workspace_executeCommand = Method('workspace/executeCommand');

  /// Constant for the 'workspace/inlayHint/refresh' method.
  static const workspace_inlayHint_refresh =
      Method('workspace/inlayHint/refresh');

  /// Constant for the 'workspace/inlineValue/refresh' method.
  static const workspace_inlineValue_refresh =
      Method('workspace/inlineValue/refresh');

  /// Constant for the 'workspace/semanticTokens/refresh' method.
  static const workspace_semanticTokens_refresh =
      Method('workspace/semanticTokens/refresh');

  /// Constant for the 'workspace/symbol' method.
  static const workspace_symbol = Method('workspace/symbol');

  /// Constant for the 'workspace/willCreateFiles' method.
  static const workspace_willCreateFiles = Method('workspace/willCreateFiles');

  /// Constant for the 'workspace/willDeleteFiles' method.
  static const workspace_willDeleteFiles = Method('workspace/willDeleteFiles');

  /// Constant for the 'workspace/willRenameFiles' method.
  static const workspace_willRenameFiles = Method('workspace/willRenameFiles');

  /// Constant for the 'workspace/workspaceFolders' method.
  static const workspace_workspaceFolders =
      Method('workspace/workspaceFolders');

  /// Constant for the 'workspaceSymbol/resolve' method.
  static const workspaceSymbol_resolve = Method('workspaceSymbol/resolve');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) => other is Method && other._value == _value;
}

/// Moniker definition to match LSIF 0.5 moniker definition.
class Moniker implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Moniker.canParse,
    Moniker.fromJson,
  );

  Moniker({
    required this.identifier,
    this.kind,
    required this.scheme,
    required this.unique,
  });
  static Moniker fromJson(Map<String, Object?> json) {
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? MonikerKind.fromJson(kindJson as String) : null;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    final uniqueJson = json['unique'];
    final unique = UniquenessLevel.fromJson(uniqueJson as String);
    return Moniker(
      identifier: identifier,
      kind: kind,
      scheme: scheme,
      unique: unique,
    );
  }

  /// The identifier of the moniker. The value is opaque in LSIF however schema
  /// owners are allowed to define the structure if they want.
  final String identifier;

  /// The moniker kind if known.
  final MonikerKind? kind;

  /// The scheme of the moniker. For example tsc or .Net
  final String scheme;

  /// The scope in which the moniker is unique
  final UniquenessLevel unique;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['identifier'] = identifier;
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['scheme'] = scheme;
    result['unique'] = unique.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('identifier');
      try {
        if (!obj.containsKey('identifier')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final identifier = obj['identifier'];
        if (identifier == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (identifier is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        final kind = obj['kind'];
        if (kind != null && !MonikerKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type MonikerKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        if (!obj.containsKey('scheme')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final scheme = obj['scheme'];
        if (scheme == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('unique');
      try {
        if (!obj.containsKey('unique')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final unique = obj['unique'];
        if (unique == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!UniquenessLevel.canParse(unique, reporter)) {
          reporter.reportError('must be of type UniquenessLevel');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Moniker');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is Moniker && other.runtimeType == Moniker) {
      return identifier == other.identifier &&
          kind == other.kind &&
          scheme == other.scheme &&
          unique == other.unique &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        identifier,
        kind,
        scheme,
        unique,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class MonikerClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerClientCapabilities.canParse,
    MonikerClientCapabilities.fromJson,
  );

  MonikerClientCapabilities({
    this.dynamicRegistration,
  });
  static MonikerClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return MonikerClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 implements ToJsonable {
  const MonikerKind(this._value);
  const MonikerKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// The moniker represents a symbol that is exported from a project
  static const export = MonikerKind('export');

  /// The moniker represent a symbol that is imported into a project
  static const import = MonikerKind('import');

  /// The moniker represents a symbol that is local to a project (e.g. a local
  /// variable of a function, a class not visible outside the project, ...)
  static const local = MonikerKind('local');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is MonikerKind && other._value == _value;
}

class MonikerOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerOptions.canParse,
    MonikerOptions.fromJson,
  );

  MonikerOptions({
    this.workDoneProgress,
  });
  static MonikerOptions fromJson(Map<String, Object?> json) {
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return MonikerOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerParams.canParse,
    MonikerParams.fromJson,
  );

  MonikerParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static MonikerParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return MonikerParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is MonikerParams && other.runtimeType == MonikerParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class MonikerRegistrationOptions
    implements MonikerOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerRegistrationOptions.canParse,
    MonikerRegistrationOptions.fromJson,
  );

  MonikerRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static MonikerRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return MonikerRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is MonikerRegistrationOptions &&
        other.runtimeType == MonikerRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A notebook cell.
///
/// A cell's document URI must be unique across ALL notebook cells and can
/// therefore be used to uniquely identify a notebook cell or the cell's text
/// document.
///  @since 3.17.0
class NotebookCell implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookCell.canParse,
    NotebookCell.fromJson,
  );

  NotebookCell({
    required this.document,
    this.executionSummary,
    required this.kind,
    this.metadata,
  });
  static NotebookCell fromJson(Map<String, Object?> json) {
    final documentJson = json['document'];
    final document = documentJson as String;
    final executionSummaryJson = json['executionSummary'];
    final executionSummary = executionSummaryJson != null
        ? ExecutionSummary.fromJson(
            executionSummaryJson as Map<String, Object?>)
        : null;
    final kindJson = json['kind'];
    final kind = NotebookCellKind.fromJson(kindJson as int);
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    return NotebookCell(
      document: document,
      executionSummary: executionSummary,
      kind: kind,
      metadata: metadata,
    );
  }

  /// The URI of the cell's text document content.
  final String document;

  /// Additional execution summary information if supported by the client.
  final ExecutionSummary? executionSummary;

  /// The cell's kind
  final NotebookCellKind kind;

  /// Additional metadata stored with the cell.
  final Object? metadata;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['document'] = document;
    if (executionSummary != null) {
      result['executionSummary'] = executionSummary?.toJson();
    }
    result['kind'] = kind.toJson();
    if (metadata != null) {
      result['metadata'] = metadata;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('document');
      try {
        if (!obj.containsKey('document')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final document = obj['document'];
        if (document == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (document is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executionSummary');
      try {
        final executionSummary = obj['executionSummary'];
        if (executionSummary != null &&
            !ExecutionSummary.canParse(executionSummary, reporter)) {
          reporter.reportError('must be of type ExecutionSummary');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookCellKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type NotebookCellKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookCell');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookCell && other.runtimeType == NotebookCell) {
      return document == other.document &&
          executionSummary == other.executionSummary &&
          kind == other.kind &&
          metadata == other.metadata &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        document,
        executionSummary,
        kind,
        metadata,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A change describing how to move a `NotebookCell` array from state S to S'.
///  @since 3.17.0
class NotebookCellArrayChange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookCellArrayChange.canParse,
    NotebookCellArrayChange.fromJson,
  );

  NotebookCellArrayChange({
    this.cells,
    required this.deleteCount,
    required this.start,
  });
  static NotebookCellArrayChange fromJson(Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>?)
        ?.map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final deleteCountJson = json['deleteCount'];
    final deleteCount = deleteCountJson as int;
    final startJson = json['start'];
    final start = startJson as int;
    return NotebookCellArrayChange(
      cells: cells,
      deleteCount: deleteCount,
      start: start,
    );
  }

  /// The new cells, if any
  final List<NotebookCell>? cells;

  /// The deleted cells
  final int deleteCount;

  /// The start oftest of the cell that changed.
  final int start;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cells != null) {
      result['cells'] = cells?.map((item) => item.toJson()).toList();
    }
    result['deleteCount'] = deleteCount;
    result['start'] = start;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        final cells = obj['cells'];
        if (cells != null &&
            (cells is! List<Object?> ||
                cells.any((item) => !NotebookCell.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<NotebookCell>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deleteCount');
      try {
        if (!obj.containsKey('deleteCount')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final deleteCount = obj['deleteCount'];
        if (deleteCount == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (deleteCount is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('start');
      try {
        if (!obj.containsKey('start')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final start = obj['start'];
        if (start == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (start is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookCellArrayChange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookCellArrayChange &&
        other.runtimeType == NotebookCellArrayChange) {
      return listEqual(
              cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
          deleteCount == other.deleteCount &&
          start == other.start &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        deleteCount,
        start,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A notebook cell kind.
///  @since 3.17.0
class NotebookCellKind implements ToJsonable {
  const NotebookCellKind(this._value);
  const NotebookCellKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// A code-cell is source code.
  static const Code = NotebookCellKind(2);

  /// A markup-cell is formatted source that is used for display.
  static const Markup = NotebookCellKind(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is NotebookCellKind && other._value == _value;
}

/// A notebook cell text document filter denotes a cell text document by
/// different properties.
///  @since 3.17.0
class NotebookCellTextDocumentFilter implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookCellTextDocumentFilter.canParse,
    NotebookCellTextDocumentFilter.fromJson,
  );

  NotebookCellTextDocumentFilter({
    this.language,
    required this.notebook,
  });
  static NotebookCellTextDocumentFilter fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String?;
    final notebookJson = json['notebook'];
    final notebook = NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter) ||
            NotebookDocumentFilter2.canParse(
                notebookJson, nullLspJsonReporter) ||
            NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter)
        ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t1(
            NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter)
                ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t1(NotebookDocumentFilter1.fromJson(
                    notebookJson as Map<String, Object?>))
                : (NotebookDocumentFilter2.canParse(notebookJson, nullLspJsonReporter)
                    ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t2(NotebookDocumentFilter2.fromJson(
                        notebookJson as Map<String, Object?>))
                    : (NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter)
                        ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t3(NotebookDocumentFilter3.fromJson(notebookJson as Map<String, Object?>))
                        : (throw '''$notebookJson was not one of (NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3)'''))))
        : (notebookJson is String ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t2(notebookJson) : (throw '''$notebookJson was not one of (Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String)'''));
    return NotebookCellTextDocumentFilter(
      language: language,
      notebook: notebook,
    );
  }

  /// A language id like `python`.
  ///
  /// Will be matched against the language id of the notebook cell document. '*'
  /// matches every language.
  final String? language;

  /// A filter that matches against the notebook containing the notebook cell.
  /// If a string value is provided it matches against the notebook type. '*'
  /// matches every notebook.
  final Either2<
      Either3<NotebookDocumentFilter1, NotebookDocumentFilter2,
          NotebookDocumentFilter3>,
      String> notebook;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (language != null) {
      result['language'] = language;
    }
    result['notebook'] = notebook;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        final language = obj['language'];
        if (language != null && language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebook');
      try {
        if (!obj.containsKey('notebook')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebook = obj['notebook'];
        if (notebook == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocumentFilter1.canParse(notebook, reporter) &&
            !NotebookDocumentFilter2.canParse(notebook, reporter) &&
            !NotebookDocumentFilter3.canParse(notebook, reporter) &&
            notebook is! String) {
          reporter.reportError(
              'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookCellTextDocumentFilter');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookCellTextDocumentFilter &&
        other.runtimeType == NotebookCellTextDocumentFilter) {
      return language == other.language && notebook == other.notebook && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        language,
        notebook,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A notebook document.
///  @since 3.17.0
class NotebookDocument implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocument.canParse,
    NotebookDocument.fromJson,
  );

  NotebookDocument({
    required this.cells,
    this.metadata,
    required this.notebookType,
    required this.uri,
    required this.version,
  });
  static NotebookDocument fromJson(Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>)
        .map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return NotebookDocument(
      cells: cells,
      metadata: metadata,
      notebookType: notebookType,
      uri: uri,
      version: version,
    );
  }

  /// The cells of a notebook.
  final List<NotebookCell> cells;

  /// Additional metadata stored with the notebook document.
  final Object? metadata;

  /// The type of the notebook.
  final String notebookType;

  /// The notebook document's uri.
  final String uri;

  /// The version number of this document (it will increase after each change,
  /// including undo/redo).
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cells'] = cells.map((item) => item.toJson()).toList();
    if (metadata != null) {
      result['metadata'] = metadata;
    }
    result['notebookType'] = notebookType;
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        if (!obj.containsKey('cells')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final cells = obj['cells'];
        if (cells == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (cells is! List<Object?> ||
            cells.any((item) => !NotebookCell.canParse(item, reporter))) {
          reporter.reportError('must be of type List<NotebookCell>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookType');
      try {
        if (!obj.containsKey('notebookType')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookType = obj['notebookType'];
        if (notebookType == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (notebookType is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocument');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocument && other.runtimeType == NotebookDocument) {
      return listEqual(
              cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
          metadata == other.metadata &&
          notebookType == other.notebookType &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        metadata,
        notebookType,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A change event for a notebook document.
///  @since 3.17.0
class NotebookDocumentChangeEvent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEvent.canParse,
    NotebookDocumentChangeEvent.fromJson,
  );

  NotebookDocumentChangeEvent({
    this.cells,
    this.metadata,
  });
  static NotebookDocumentChangeEvent fromJson(Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = cellsJson != null
        ? NotebookDocumentChangeEventCells.fromJson(
            cellsJson as Map<String, Object?>)
        : null;
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    return NotebookDocumentChangeEvent(
      cells: cells,
      metadata: metadata,
    );
  }

  /// Changes to cells
  final NotebookDocumentChangeEventCells? cells;

  /// The changed meta data if any.
  final Object? metadata;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cells != null) {
      result['cells'] = cells?.toJson();
    }
    if (metadata != null) {
      result['metadata'] = metadata;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        final cells = obj['cells'];
        if (cells != null &&
            !NotebookDocumentChangeEventCells.canParse(cells, reporter)) {
          reporter
              .reportError('must be of type NotebookDocumentChangeEventCells');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentChangeEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentChangeEvent &&
        other.runtimeType == NotebookDocumentChangeEvent) {
      return cells == other.cells && metadata == other.metadata && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        cells,
        metadata,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentChangeEventCells implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEventCells.canParse,
    NotebookDocumentChangeEventCells.fromJson,
  );

  NotebookDocumentChangeEventCells({
    this.data,
    this.structure,
    this.textContent,
  });
  static NotebookDocumentChangeEventCells fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = (dataJson as List<Object?>?)
        ?.map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final structureJson = json['structure'];
    final structure = structureJson != null
        ? NotebookDocumentChangeEventCellsStructure.fromJson(
            structureJson as Map<String, Object?>)
        : null;
    final textContentJson = json['textContent'];
    final textContent = (textContentJson as List<Object?>?)
        ?.map((item) => NotebookDocumentChangeEventCellsTextContent.fromJson(
            item as Map<String, Object?>))
        .toList();
    return NotebookDocumentChangeEventCells(
      data: data,
      structure: structure,
      textContent: textContent,
    );
  }

  /// Changes to notebook cells properties like its kind, execution summary or
  /// metadata.
  final List<NotebookCell>? data;

  /// Changes to the cell structure to add or remove cells.
  final NotebookDocumentChangeEventCellsStructure? structure;

  /// Changes to the text content of notebook cells.
  final List<NotebookDocumentChangeEventCellsTextContent>? textContent;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data?.map((item) => item.toJson()).toList();
    }
    if (structure != null) {
      result['structure'] = structure?.toJson();
    }
    if (textContent != null) {
      result['textContent'] =
          textContent?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('data');
      try {
        final data = obj['data'];
        if (data != null &&
            (data is! List<Object?> ||
                data.any((item) => !NotebookCell.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<NotebookCell>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('structure');
      try {
        final structure = obj['structure'];
        if (structure != null &&
            !NotebookDocumentChangeEventCellsStructure.canParse(
                structure, reporter)) {
          reporter.reportError(
              'must be of type NotebookDocumentChangeEventCellsStructure');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textContent');
      try {
        final textContent = obj['textContent'];
        if (textContent != null &&
            (textContent is! List<Object?> ||
                textContent.any((item) =>
                    !NotebookDocumentChangeEventCellsTextContent.canParse(
                        item, reporter)))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentChangeEventCellsTextContent>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentChangeEventCells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentChangeEventCells &&
        other.runtimeType == NotebookDocumentChangeEventCells) {
      return listEqual(
              data, other.data, (NotebookCell a, NotebookCell b) => a == b) &&
          structure == other.structure &&
          listEqual(
              textContent,
              other.textContent,
              (NotebookDocumentChangeEventCellsTextContent a,
                      NotebookDocumentChangeEventCellsTextContent b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        structure,
        lspHashCode(textContent),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentChangeEventCellsStructure implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEventCellsStructure.canParse,
    NotebookDocumentChangeEventCellsStructure.fromJson,
  );

  NotebookDocumentChangeEventCellsStructure({
    required this.array,
    this.didClose,
    this.didOpen,
  });
  static NotebookDocumentChangeEventCellsStructure fromJson(
      Map<String, Object?> json) {
    final arrayJson = json['array'];
    final array =
        NotebookCellArrayChange.fromJson(arrayJson as Map<String, Object?>);
    final didCloseJson = json['didClose'];
    final didClose = (didCloseJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentIdentifier.fromJson(item as Map<String, Object?>))
        .toList();
    final didOpenJson = json['didOpen'];
    final didOpen = (didOpenJson as List<Object?>?)
        ?.map((item) => TextDocumentItem.fromJson(item as Map<String, Object?>))
        .toList();
    return NotebookDocumentChangeEventCellsStructure(
      array: array,
      didClose: didClose,
      didOpen: didOpen,
    );
  }

  /// The change to the cell array.
  final NotebookCellArrayChange array;

  /// Additional closed cell text documents.
  final List<TextDocumentIdentifier>? didClose;

  /// Additional opened cell text documents.
  final List<TextDocumentItem>? didOpen;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['array'] = array.toJson();
    if (didClose != null) {
      result['didClose'] = didClose?.map((item) => item.toJson()).toList();
    }
    if (didOpen != null) {
      result['didOpen'] = didOpen?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('array');
      try {
        if (!obj.containsKey('array')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final array = obj['array'];
        if (array == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookCellArrayChange.canParse(array, reporter)) {
          reporter.reportError('must be of type NotebookCellArrayChange');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didClose');
      try {
        final didClose = obj['didClose'];
        if (didClose != null &&
            (didClose is! List<Object?> ||
                didClose.any((item) =>
                    !TextDocumentIdentifier.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<TextDocumentIdentifier>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didOpen');
      try {
        final didOpen = obj['didOpen'];
        if (didOpen != null &&
            (didOpen is! List<Object?> ||
                didOpen.any(
                    (item) => !TextDocumentItem.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<TextDocumentItem>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentChangeEventCellsStructure');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentChangeEventCellsStructure &&
        other.runtimeType == NotebookDocumentChangeEventCellsStructure) {
      return array == other.array &&
          listEqual(didClose, other.didClose,
              (TextDocumentIdentifier a, TextDocumentIdentifier b) => a == b) &&
          listEqual(didOpen, other.didOpen,
              (TextDocumentItem a, TextDocumentItem b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        array,
        lspHashCode(didClose),
        lspHashCode(didOpen),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentChangeEventCellsTextContent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEventCellsTextContent.canParse,
    NotebookDocumentChangeEventCellsTextContent.fromJson,
  );

  NotebookDocumentChangeEventCellsTextContent({
    required this.changes,
    required this.document,
  });
  static NotebookDocumentChangeEventCellsTextContent fromJson(
      Map<String, Object?> json) {
    final changesJson = json['changes'];
    final changes = (changesJson as List<Object?>)
        .map((item) => TextDocumentContentChangeEvent1.canParse(
                item, nullLspJsonReporter)
            ? Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>.t1(
                TextDocumentContentChangeEvent1.fromJson(
                    item as Map<String, Object?>))
            : (TextDocumentContentChangeEvent2.canParse(item, nullLspJsonReporter)
                ? Either2<TextDocumentContentChangeEvent1,
                        TextDocumentContentChangeEvent2>.t2(
                    TextDocumentContentChangeEvent2.fromJson(item as Map<String, Object?>))
                : (throw '''$item was not one of (TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2)''')))
        .toList();
    final documentJson = json['document'];
    final document = VersionedTextDocumentIdentifier.fromJson(
        documentJson as Map<String, Object?>);
    return NotebookDocumentChangeEventCellsTextContent(
      changes: changes,
      document: document,
    );
  }

  final List<
      Either2<TextDocumentContentChangeEvent1,
          TextDocumentContentChangeEvent2>> changes;
  final VersionedTextDocumentIdentifier document;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['changes'] = changes;
    result['document'] = document.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('changes');
      try {
        if (!obj.containsKey('changes')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final changes = obj['changes'];
        if (changes == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (changes is! List<Object?> ||
            changes.any((item) =>
                !TextDocumentContentChangeEvent1.canParse(item, reporter) &&
                !TextDocumentContentChangeEvent2.canParse(item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('document');
      try {
        if (!obj.containsKey('document')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final document = obj['document'];
        if (document == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!VersionedTextDocumentIdentifier.canParse(document, reporter)) {
          reporter
              .reportError('must be of type VersionedTextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentChangeEventCellsTextContent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentChangeEventCellsTextContent &&
        other.runtimeType == NotebookDocumentChangeEventCellsTextContent) {
      return listEqual(
              changes,
              other.changes,
              (Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          a,
                      Either2<TextDocumentContentChangeEvent1,
                              TextDocumentContentChangeEvent2>
                          b) =>
                  a == b) &&
          document == other.document &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(changes),
        document,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Capabilities specific to the notebook document support.
///  @since 3.17.0
class NotebookDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentClientCapabilities.canParse,
    NotebookDocumentClientCapabilities.fromJson,
  );

  NotebookDocumentClientCapabilities({
    required this.synchronization,
  });
  static NotebookDocumentClientCapabilities fromJson(
      Map<String, Object?> json) {
    final synchronizationJson = json['synchronization'];
    final synchronization = NotebookDocumentSyncClientCapabilities.fromJson(
        synchronizationJson as Map<String, Object?>);
    return NotebookDocumentClientCapabilities(
      synchronization: synchronization,
    );
  }

  /// Capabilities specific to notebook document synchronization
  ///  @since 3.17.0
  final NotebookDocumentSyncClientCapabilities synchronization;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['synchronization'] = synchronization.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('synchronization');
      try {
        if (!obj.containsKey('synchronization')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final synchronization = obj['synchronization'];
        if (synchronization == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocumentSyncClientCapabilities.canParse(
            synchronization, reporter)) {
          reporter.reportError(
              'must be of type NotebookDocumentSyncClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type NotebookDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentClientCapabilities &&
        other.runtimeType == NotebookDocumentClientCapabilities) {
      return synchronization == other.synchronization && true;
    }
    return false;
  }

  @override
  int get hashCode => synchronization.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentFilter1 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentFilter1.canParse,
    NotebookDocumentFilter1.fromJson,
  );

  NotebookDocumentFilter1({
    required this.notebookType,
    this.pattern,
    this.scheme,
  });
  static NotebookDocumentFilter1 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return NotebookDocumentFilter1(
      notebookType: notebookType,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The type of the enclosing notebook.
  final String notebookType;

  /// A glob pattern.
  final String? pattern;

  /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['notebookType'] = notebookType;
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookType');
      try {
        if (!obj.containsKey('notebookType')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookType = obj['notebookType'];
        if (notebookType == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (notebookType is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        final pattern = obj['pattern'];
        if (pattern != null && pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentFilter1');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentFilter1 &&
        other.runtimeType == NotebookDocumentFilter1) {
      return notebookType == other.notebookType &&
          pattern == other.pattern &&
          scheme == other.scheme &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        notebookType,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentFilter2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentFilter2.canParse,
    NotebookDocumentFilter2.fromJson,
  );

  NotebookDocumentFilter2({
    this.notebookType,
    this.pattern,
    required this.scheme,
  });
  static NotebookDocumentFilter2 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    return NotebookDocumentFilter2(
      notebookType: notebookType,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The type of the enclosing notebook.
  final String? notebookType;

  /// A glob pattern.
  final String? pattern;

  /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
  final String scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (notebookType != null) {
      result['notebookType'] = notebookType;
    }
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    result['scheme'] = scheme;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookType');
      try {
        final notebookType = obj['notebookType'];
        if (notebookType != null && notebookType is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        final pattern = obj['pattern'];
        if (pattern != null && pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        if (!obj.containsKey('scheme')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final scheme = obj['scheme'];
        if (scheme == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentFilter2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentFilter2 &&
        other.runtimeType == NotebookDocumentFilter2) {
      return notebookType == other.notebookType &&
          pattern == other.pattern &&
          scheme == other.scheme &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        notebookType,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentFilter3 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentFilter3.canParse,
    NotebookDocumentFilter3.fromJson,
  );

  NotebookDocumentFilter3({
    this.notebookType,
    required this.pattern,
    this.scheme,
  });
  static NotebookDocumentFilter3 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return NotebookDocumentFilter3(
      notebookType: notebookType,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The type of the enclosing notebook.
  final String? notebookType;

  /// A glob pattern.
  final String pattern;

  /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (notebookType != null) {
      result['notebookType'] = notebookType;
    }
    result['pattern'] = pattern;
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookType');
      try {
        final notebookType = obj['notebookType'];
        if (notebookType != null && notebookType is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        if (!obj.containsKey('pattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final pattern = obj['pattern'];
        if (pattern == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentFilter3');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentFilter3 &&
        other.runtimeType == NotebookDocumentFilter3) {
      return notebookType == other.notebookType &&
          pattern == other.pattern &&
          scheme == other.scheme &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        notebookType,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A literal to identify a notebook document in the client.
///  @since 3.17.0
class NotebookDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentIdentifier.canParse,
    NotebookDocumentIdentifier.fromJson,
  );

  NotebookDocumentIdentifier({
    required this.uri,
  });
  static NotebookDocumentIdentifier fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return NotebookDocumentIdentifier(
      uri: uri,
    );
  }

  /// The notebook document's uri.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentIdentifier &&
        other.runtimeType == NotebookDocumentIdentifier) {
      return uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Notebook specific client capabilities.
///  @since 3.17.0
class NotebookDocumentSyncClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncClientCapabilities.canParse,
    NotebookDocumentSyncClientCapabilities.fromJson,
  );

  NotebookDocumentSyncClientCapabilities({
    this.dynamicRegistration,
    this.executionSummarySupport,
  });
  static NotebookDocumentSyncClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final executionSummarySupportJson = json['executionSummarySupport'];
    final executionSummarySupport = executionSummarySupportJson as bool?;
    return NotebookDocumentSyncClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      executionSummarySupport: executionSummarySupport,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  /// The client supports sending execution summary data per cell.
  final bool? executionSummarySupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (executionSummarySupport != null) {
      result['executionSummarySupport'] = executionSummarySupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executionSummarySupport');
      try {
        final executionSummarySupport = obj['executionSummarySupport'];
        if (executionSummarySupport != null &&
            executionSummarySupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncClientCapabilities &&
        other.runtimeType == NotebookDocumentSyncClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          executionSummarySupport == other.executionSummarySupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        executionSummarySupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Options specific to a notebook plus its cells to be synced to the server.
///
/// If a selector provider a notebook document filter but no cell selector all
/// cells of a matching notebook document will be synced.
///
/// If a selector provides no notebook document filter but only a cell selector
/// all notebook document that contain at least one matching cell will be
/// synced.
///  @since 3.17.0
class NotebookDocumentSyncOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptions.canParse,
    NotebookDocumentSyncOptions.fromJson,
  );

  NotebookDocumentSyncOptions({
    required this.notebookSelector,
    this.save,
  });
  static NotebookDocumentSyncOptions fromJson(Map<String, Object?> json) {
    if (NotebookDocumentSyncRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return NotebookDocumentSyncRegistrationOptions.fromJson(json);
    }
    final notebookSelectorJson = json['notebookSelector'];
    final notebookSelector = (notebookSelectorJson as List<Object?>)
        .map((item) => NotebookDocumentSyncOptionsNotebookSelector.canParse(
                item, nullLspJsonReporter)
            ? Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>.t1(
                NotebookDocumentSyncOptionsNotebookSelector.fromJson(
                    item as Map<String, Object?>))
            : (NotebookDocumentSyncOptionsNotebookSelector2.canParse(item, nullLspJsonReporter)
                ? Either2<NotebookDocumentSyncOptionsNotebookSelector,
                        NotebookDocumentSyncOptionsNotebookSelector2>.t2(
                    NotebookDocumentSyncOptionsNotebookSelector2.fromJson(item as Map<String, Object?>))
                : (throw '''$item was not one of (NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2)''')))
        .toList();
    final saveJson = json['save'];
    final save = saveJson as bool?;
    return NotebookDocumentSyncOptions(
      notebookSelector: notebookSelector,
      save: save,
    );
  }

  /// The notebooks to be synced
  final List<
      Either2<NotebookDocumentSyncOptionsNotebookSelector,
          NotebookDocumentSyncOptionsNotebookSelector2>> notebookSelector;

  /// Whether save notification should be forwarded to the server. Will only be
  /// honored if mode === `notebook`.
  final bool? save;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['notebookSelector'] = notebookSelector;
    if (save != null) {
      result['save'] = save;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('notebookSelector');
      try {
        if (!obj.containsKey('notebookSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookSelector = obj['notebookSelector'];
        if (notebookSelector == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (notebookSelector is! List<Object?> ||
            notebookSelector.any((item) =>
                !NotebookDocumentSyncOptionsNotebookSelector.canParse(
                    item, reporter) &&
                !NotebookDocumentSyncOptionsNotebookSelector2.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('save');
      try {
        final save = obj['save'];
        if (save != null && save is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotebookDocumentSyncOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncOptions &&
        other.runtimeType == NotebookDocumentSyncOptions) {
      return listEqual(
              notebookSelector,
              other.notebookSelector,
              (Either2<NotebookDocumentSyncOptionsNotebookSelector,
                              NotebookDocumentSyncOptionsNotebookSelector2>
                          a,
                      Either2<NotebookDocumentSyncOptionsNotebookSelector,
                              NotebookDocumentSyncOptionsNotebookSelector2>
                          b) =>
                  a == b) &&
          save == other.save &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(notebookSelector),
        save,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelector implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelector.canParse,
    NotebookDocumentSyncOptionsNotebookSelector.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelector({
    this.cells,
    required this.notebook,
  });
  static NotebookDocumentSyncOptionsNotebookSelector fromJson(
      Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>?)
        ?.map((item) =>
            NotebookDocumentSyncOptionsNotebookSelectorCells.fromJson(
                item as Map<String, Object?>))
        .toList();
    final notebookJson = json['notebook'];
    final notebook = NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter) ||
            NotebookDocumentFilter2.canParse(
                notebookJson, nullLspJsonReporter) ||
            NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter)
        ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t1(
            NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter)
                ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t1(NotebookDocumentFilter1.fromJson(
                    notebookJson as Map<String, Object?>))
                : (NotebookDocumentFilter2.canParse(notebookJson, nullLspJsonReporter)
                    ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t2(NotebookDocumentFilter2.fromJson(
                        notebookJson as Map<String, Object?>))
                    : (NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter)
                        ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t3(NotebookDocumentFilter3.fromJson(notebookJson as Map<String, Object?>))
                        : (throw '''$notebookJson was not one of (NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3)'''))))
        : (notebookJson is String ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t2(notebookJson) : (throw '''$notebookJson was not one of (Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String)'''));
    return NotebookDocumentSyncOptionsNotebookSelector(
      cells: cells,
      notebook: notebook,
    );
  }

  /// The cells of the matching notebook to be synced.
  final List<NotebookDocumentSyncOptionsNotebookSelectorCells>? cells;

  /// The notebook to be synced If a string value is provided it matches against
  /// the notebook type. '*' matches every notebook.
  final Either2<
      Either3<NotebookDocumentFilter1, NotebookDocumentFilter2,
          NotebookDocumentFilter3>,
      String> notebook;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cells != null) {
      result['cells'] = cells?.map((item) => item.toJson()).toList();
    }
    result['notebook'] = notebook;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        final cells = obj['cells'];
        if (cells != null &&
            (cells is! List<Object?> ||
                cells.any((item) =>
                    !NotebookDocumentSyncOptionsNotebookSelectorCells.canParse(
                        item, reporter)))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentSyncOptionsNotebookSelectorCells>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebook');
      try {
        if (!obj.containsKey('notebook')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebook = obj['notebook'];
        if (notebook == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!NotebookDocumentFilter1.canParse(notebook, reporter) &&
            !NotebookDocumentFilter2.canParse(notebook, reporter) &&
            !NotebookDocumentFilter3.canParse(notebook, reporter) &&
            notebook is! String) {
          reporter.reportError(
              'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelector');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncOptionsNotebookSelector &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelector) {
      return listEqual(
              cells,
              other.cells,
              (NotebookDocumentSyncOptionsNotebookSelectorCells a,
                      NotebookDocumentSyncOptionsNotebookSelectorCells b) =>
                  a == b) &&
          notebook == other.notebook &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        notebook,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelector2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelector2.canParse,
    NotebookDocumentSyncOptionsNotebookSelector2.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelector2({
    required this.cells,
    this.notebook,
  });
  static NotebookDocumentSyncOptionsNotebookSelector2 fromJson(
      Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>)
        .map((item) =>
            NotebookDocumentSyncOptionsNotebookSelector2Cells.fromJson(
                item as Map<String, Object?>))
        .toList();
    final notebookJson = json['notebook'];
    final notebook = notebookJson == null
        ? null
        : (NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter) ||
                NotebookDocumentFilter2.canParse(
                    notebookJson, nullLspJsonReporter) ||
                NotebookDocumentFilter3.canParse(
                    notebookJson, nullLspJsonReporter)
            ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t1(
                NotebookDocumentFilter1.canParse(notebookJson, nullLspJsonReporter)
                    ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t1(
                        NotebookDocumentFilter1.fromJson(
                            notebookJson as Map<String, Object?>))
                    : (NotebookDocumentFilter2.canParse(notebookJson, nullLspJsonReporter)
                        ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t2(
                            NotebookDocumentFilter2.fromJson(notebookJson as Map<String, Object?>))
                        : (NotebookDocumentFilter3.canParse(notebookJson, nullLspJsonReporter) ? Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>.t3(NotebookDocumentFilter3.fromJson(notebookJson as Map<String, Object?>)) : (throw '''$notebookJson was not one of (NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3)'''))))
            : (notebookJson is String ? Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>.t2(notebookJson) : (throw '''$notebookJson was not one of (Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String)''')));
    return NotebookDocumentSyncOptionsNotebookSelector2(
      cells: cells,
      notebook: notebook,
    );
  }

  /// The cells of the matching notebook to be synced.
  final List<NotebookDocumentSyncOptionsNotebookSelector2Cells> cells;

  /// The notebook to be synced If a string value is provided it matches against
  /// the notebook type. '*' matches every notebook.
  final Either2<
      Either3<NotebookDocumentFilter1, NotebookDocumentFilter2,
          NotebookDocumentFilter3>,
      String>? notebook;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cells'] = cells.map((item) => item.toJson()).toList();
    if (notebook != null) {
      result['notebook'] = notebook;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cells');
      try {
        if (!obj.containsKey('cells')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final cells = obj['cells'];
        if (cells == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (cells is! List<Object?> ||
            cells.any((item) =>
                !NotebookDocumentSyncOptionsNotebookSelector2Cells.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<NotebookDocumentSyncOptionsNotebookSelector2Cells>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebook');
      try {
        final notebook = obj['notebook'];
        if (notebook != null &&
            !NotebookDocumentFilter1.canParse(notebook, reporter) &&
            !NotebookDocumentFilter2.canParse(notebook, reporter) &&
            !NotebookDocumentFilter3.canParse(notebook, reporter) &&
            notebook is! String) {
          reporter.reportError(
              'must be of type Either2<Either3<NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3>, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelector2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncOptionsNotebookSelector2 &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelector2) {
      return listEqual(
              cells,
              other.cells,
              (NotebookDocumentSyncOptionsNotebookSelector2Cells a,
                      NotebookDocumentSyncOptionsNotebookSelector2Cells b) =>
                  a == b) &&
          notebook == other.notebook &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        notebook,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelector2Cells implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelector2Cells.canParse,
    NotebookDocumentSyncOptionsNotebookSelector2Cells.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelector2Cells({
    required this.language,
  });
  static NotebookDocumentSyncOptionsNotebookSelector2Cells fromJson(
      Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String;
    return NotebookDocumentSyncOptionsNotebookSelector2Cells(
      language: language,
    );
  }

  final String language;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['language'] = language;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        if (!obj.containsKey('language')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final language = obj['language'];
        if (language == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelector2Cells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncOptionsNotebookSelector2Cells &&
        other.runtimeType ==
            NotebookDocumentSyncOptionsNotebookSelector2Cells) {
      return language == other.language && true;
    }
    return false;
  }

  @override
  int get hashCode => language.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelectorCells implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelectorCells.canParse,
    NotebookDocumentSyncOptionsNotebookSelectorCells.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelectorCells({
    required this.language,
  });
  static NotebookDocumentSyncOptionsNotebookSelectorCells fromJson(
      Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String;
    return NotebookDocumentSyncOptionsNotebookSelectorCells(
      language: language,
    );
  }

  final String language;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['language'] = language;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        if (!obj.containsKey('language')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final language = obj['language'];
        if (language == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelectorCells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncOptionsNotebookSelectorCells &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelectorCells) {
      return language == other.language && true;
    }
    return false;
  }

  @override
  int get hashCode => language.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options specific to a notebook.
///  @since 3.17.0
class NotebookDocumentSyncRegistrationOptions
    implements
        NotebookDocumentSyncOptions,
        StaticRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncRegistrationOptions.canParse,
    NotebookDocumentSyncRegistrationOptions.fromJson,
  );

  NotebookDocumentSyncRegistrationOptions({
    this.id,
    required this.notebookSelector,
    this.save,
  });
  static NotebookDocumentSyncRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final idJson = json['id'];
    final id = idJson as String?;
    final notebookSelectorJson = json['notebookSelector'];
    final notebookSelector = (notebookSelectorJson as List<Object?>)
        .map((item) => NotebookDocumentSyncOptionsNotebookSelector.canParse(
                item, nullLspJsonReporter)
            ? Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>.t1(
                NotebookDocumentSyncOptionsNotebookSelector.fromJson(
                    item as Map<String, Object?>))
            : (NotebookDocumentSyncOptionsNotebookSelector2.canParse(item, nullLspJsonReporter)
                ? Either2<NotebookDocumentSyncOptionsNotebookSelector,
                        NotebookDocumentSyncOptionsNotebookSelector2>.t2(
                    NotebookDocumentSyncOptionsNotebookSelector2.fromJson(item as Map<String, Object?>))
                : (throw '''$item was not one of (NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2)''')))
        .toList();
    final saveJson = json['save'];
    final save = saveJson as bool?;
    return NotebookDocumentSyncRegistrationOptions(
      id: id,
      notebookSelector: notebookSelector,
      save: save,
    );
  }

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// The notebooks to be synced
  @override
  final List<
      Either2<NotebookDocumentSyncOptionsNotebookSelector,
          NotebookDocumentSyncOptionsNotebookSelector2>> notebookSelector;

  /// Whether save notification should be forwarded to the server. Will only be
  /// honored if mode === `notebook`.
  @override
  final bool? save;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (id != null) {
      result['id'] = id;
    }
    result['notebookSelector'] = notebookSelector;
    if (save != null) {
      result['save'] = save;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookSelector');
      try {
        if (!obj.containsKey('notebookSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final notebookSelector = obj['notebookSelector'];
        if (notebookSelector == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (notebookSelector is! List<Object?> ||
            notebookSelector.any((item) =>
                !NotebookDocumentSyncOptionsNotebookSelector.canParse(
                    item, reporter) &&
                !NotebookDocumentSyncOptionsNotebookSelector2.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('save');
      try {
        final save = obj['save'];
        if (save != null && save is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotebookDocumentSyncRegistrationOptions &&
        other.runtimeType == NotebookDocumentSyncRegistrationOptions) {
      return id == other.id &&
          listEqual(
              notebookSelector,
              other.notebookSelector,
              (Either2<NotebookDocumentSyncOptionsNotebookSelector,
                              NotebookDocumentSyncOptionsNotebookSelector2>
                          a,
                      Either2<NotebookDocumentSyncOptionsNotebookSelector,
                              NotebookDocumentSyncOptionsNotebookSelector2>
                          b) =>
                  a == b) &&
          save == other.save &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        id,
        lspHashCode(notebookSelector),
        save,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class OptionalVersionedTextDocumentIdentifier
    implements TextDocumentIdentifier, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    OptionalVersionedTextDocumentIdentifier.canParse,
    OptionalVersionedTextDocumentIdentifier.fromJson,
  );

  OptionalVersionedTextDocumentIdentifier({
    required this.uri,
    this.version,
  });
  static OptionalVersionedTextDocumentIdentifier fromJson(
      Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return OptionalVersionedTextDocumentIdentifier(
      uri: uri,
      version: version,
    );
  }

  /// The text document's URI.
  @override
  final String uri;

  /// The version number of this document. If 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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version != null && version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type OptionalVersionedTextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is OptionalVersionedTextDocumentIdentifier &&
        other.runtimeType == OptionalVersionedTextDocumentIdentifier) {
      return uri == other.uri && version == other.version && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a parameter of a callable-signature. A parameter can have a label
/// and a doc-comment.
class ParameterInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ParameterInformation.canParse,
    ParameterInformation.fromJson,
  );

  ParameterInformation({
    this.documentation,
    required this.label,
  });
  static ParameterInformation fromJson(Map<String, Object?> json) {
    final documentationJson = json['documentation'];
    final documentation = documentationJson == null
        ? null
        : (MarkupContent.canParse(documentationJson, nullLspJsonReporter)
            ? Either2<MarkupContent, String>.t1(MarkupContent.fromJson(
                documentationJson as Map<String, Object?>))
            : (documentationJson is String
                ? Either2<MarkupContent, String>.t2(documentationJson)
                : (throw '''$documentationJson was not one of (MarkupContent, String)''')));
    final labelJson = json['label'];
    final label = labelJson as String;
    return ParameterInformation(
      documentation: documentation,
      label: label,
    );
  }

  /// The human-readable doc-comment of this parameter. Will be shown in the UI
  /// but can be omitted.
  final Either2<MarkupContent, String>? documentation;

  /// The label of this parameter information.
  ///
  /// Either a string or an inclusive start and exclusive end offsets within its
  /// containing signature label. (see SignatureInformation.label). The offsets
  /// are based on a UTF-16 string representation as `Position` and `Range`
  /// does.
  ///
  /// *Note*: a label of type string should be a substring of its containing
  /// signature label. Its intended use case is to highlight the parameter label
  /// part in the `SignatureInformation.label`.
  final String label;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (documentation != null) {
      result['documentation'] = documentation;
    }
    result['label'] = label;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentation');
      try {
        final documentation = obj['documentation'];
        if (documentation != null &&
            !MarkupContent.canParse(documentation, reporter) &&
            documentation is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final label = obj['label'];
        if (label == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ParameterInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ParameterInformation &&
        other.runtimeType == ParameterInformation) {
      return documentation == other.documentation &&
          label == other.label &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        documentation,
        label,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PartialResultParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PartialResultParams.canParse,
    PartialResultParams.fromJson,
  );

  PartialResultParams({
    this.partialResultToken,
  });
  static PartialResultParams fromJson(Map<String, Object?> json) {
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (DocumentDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return DocumentDiagnosticParams.fromJson(json);
    }
    if (WorkspaceDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceDiagnosticParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (TypeHierarchySubtypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySubtypesParams.fromJson(json);
    }
    if (TypeHierarchySupertypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySupertypesParams.fromJson(json);
    }
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    return PartialResultParams(
      partialResultToken: partialResultToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<int, String>? partialResultToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PartialResultParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 PlaceholderAndRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PlaceholderAndRange.canParse,
    PlaceholderAndRange.fromJson,
  );

  PlaceholderAndRange({
    required this.placeholder,
    required this.range,
  });
  static PlaceholderAndRange fromJson(Map<String, Object?> json) {
    final placeholderJson = json['placeholder'];
    final placeholder = placeholderJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return PlaceholderAndRange(
      placeholder: placeholder,
      range: range,
    );
  }

  final String placeholder;
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['placeholder'] = placeholder;
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('placeholder');
      try {
        if (!obj.containsKey('placeholder')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final placeholder = obj['placeholder'];
        if (placeholder == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (placeholder is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PlaceholderAndRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PlaceholderAndRange &&
        other.runtimeType == PlaceholderAndRange) {
      return placeholder == other.placeholder && range == other.range && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        placeholder,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class Position implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Position.canParse,
    Position.fromJson,
  );

  Position({
    required this.character,
    required this.line,
  });
  static Position fromJson(Map<String, Object?> json) {
    final characterJson = json['character'];
    final character = characterJson as int;
    final lineJson = json['line'];
    final line = lineJson as int;
    return Position(
      character: character,
      line: line,
    );
  }

  /// Character offset on a line in a document (zero-based). The meaning of this
  /// offset is determined by the negotiated `PositionEncodingKind`.
  ///
  /// If the character value is greater than the line length it defaults back to
  /// the line length.
  final int character;

  /// Line position in a document (zero-based).
  final int line;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['character'] = character;
    result['line'] = line;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('character');
      try {
        if (!obj.containsKey('character')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final character = obj['character'];
        if (character == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (character is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('line');
      try {
        if (!obj.containsKey('line')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final line = obj['line'];
        if (line == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (line is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Position');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is Position && other.runtimeType == Position) {
      return character == other.character && line == other.line && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        character,
        line,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A set of predefined position encoding kinds.
///  @since 3.17.0
class PositionEncodingKind implements ToJsonable {
  const PositionEncodingKind(this._value);
  const PositionEncodingKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// Character offsets count UTF-16 code units.
  ///
  /// This is the default and must always be supported by servers
  static const UTF16 = PositionEncodingKind('utf-16');

  /// Character offsets count UTF-32 code units.
  ///
  /// Implementation note: these are the same as Unicode code points, so this
  /// `PositionEncodingKind` may also be used for an encoding-agnostic
  /// representation of character offsets.
  static const UTF32 = PositionEncodingKind('utf-32');

  /// Character offsets count UTF-8 code units.
  static const UTF8 = PositionEncodingKind('utf-8');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is PositionEncodingKind && other._value == _value;
}

class PrepareRenameParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PrepareRenameParams.canParse,
    PrepareRenameParams.fromJson,
  );

  PrepareRenameParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static PrepareRenameParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return PrepareRenameParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PrepareRenameParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PrepareRenameParams &&
        other.runtimeType == PrepareRenameParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PrepareSupportDefaultBehavior implements ToJsonable {
  const PrepareSupportDefaultBehavior(this._value);
  const PrepareSupportDefaultBehavior.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// The client's default behavior is to select the identifier according to the
  /// language's syntax rule.
  static const Identifier = PrepareSupportDefaultBehavior(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is PrepareSupportDefaultBehavior && other._value == _value;
}

/// A previous result id in a workspace pull request.
///  @since 3.17.0
class PreviousResultId implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PreviousResultId.canParse,
    PreviousResultId.fromJson,
  );

  PreviousResultId({
    required this.uri,
    required this.value,
  });
  static PreviousResultId fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final valueJson = json['value'];
    final value = valueJson as String;
    return PreviousResultId(
      uri: uri,
      value: value,
    );
  }

  /// The URI for which the client knowns a result id.
  final String uri;

  /// The value of the previous result id.
  final String value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final value = obj['value'];
        if (value == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (value is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PreviousResultId');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PreviousResultId && other.runtimeType == PreviousResultId) {
      return uri == other.uri && value == other.value && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ProgressParams<T> implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ProgressParams.canParse,
    ProgressParams.fromJson,
  );

  ProgressParams({
    required this.token,
    this.value,
  });
  static ProgressParams<T> fromJson<T>(Map<String, Object?> json) {
    final tokenJson = json['token'];
    final token = tokenJson is int
        ? Either2<int, String>.t1(tokenJson)
        : (tokenJson is String
            ? Either2<int, String>.t2(tokenJson)
            : (throw '''$tokenJson was not one of (int, String)'''));
    final valueJson = json['value'];
    final value = valueJson;
    return ProgressParams<T>(
      token: token,
      value: value,
    );
  }

  /// The progress token provided by the client or server.
  final Either2<int, String> token;

  /// The progress data.
  final Object? value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['token'] = token;
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('token');
      try {
        if (!obj.containsKey('token')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final token = obj['token'];
        if (token == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (token is! int && token is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ProgressParams<T>');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ProgressParams && other.runtimeType == ProgressParams) {
      return token == other.token && value == other.value && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        token,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PublishDiagnosticsClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PublishDiagnosticsClientCapabilities.canParse,
    PublishDiagnosticsClientCapabilities.fromJson,
  );

  PublishDiagnosticsClientCapabilities({
    this.codeDescriptionSupport,
    this.dataSupport,
    this.relatedInformation,
    this.tagSupport,
    this.versionSupport,
  });
  static PublishDiagnosticsClientCapabilities fromJson(
      Map<String, Object?> json) {
    final codeDescriptionSupportJson = json['codeDescriptionSupport'];
    final codeDescriptionSupport = codeDescriptionSupportJson as bool?;
    final dataSupportJson = json['dataSupport'];
    final dataSupport = dataSupportJson as bool?;
    final relatedInformationJson = json['relatedInformation'];
    final relatedInformation = relatedInformationJson as bool?;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? PublishDiagnosticsClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    final versionSupportJson = json['versionSupport'];
    final versionSupport = versionSupportJson as bool?;
    return PublishDiagnosticsClientCapabilities(
      codeDescriptionSupport: codeDescriptionSupport,
      dataSupport: dataSupport,
      relatedInformation: relatedInformation,
      tagSupport: tagSupport,
      versionSupport: versionSupport,
    );
  }

  /// Client supports a codeDescription property
  ///  @since 3.16.0
  final bool? codeDescriptionSupport;

  /// Whether code action supports the `data` property which is preserved
  /// between a `textDocument/publishDiagnostics` and `textDocument/codeAction`
  /// request.
  ///  @since 3.16.0
  final bool? dataSupport;

  /// Whether the clients accepts diagnostics with related information.
  final bool? relatedInformation;

  /// Client supports the tag property to provide meta data about a diagnostic.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///  @since 3.15.0
  final PublishDiagnosticsClientCapabilitiesTagSupport? tagSupport;

  /// Whether the client interprets the version property of the
  /// `textDocument/publishDiagnostics` notification's parameter.
  ///  @since 3.15.0
  final bool? versionSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (codeDescriptionSupport != null) {
      result['codeDescriptionSupport'] = codeDescriptionSupport;
    }
    if (dataSupport != null) {
      result['dataSupport'] = dataSupport;
    }
    if (relatedInformation != null) {
      result['relatedInformation'] = relatedInformation;
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    if (versionSupport != null) {
      result['versionSupport'] = versionSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('codeDescriptionSupport');
      try {
        final codeDescriptionSupport = obj['codeDescriptionSupport'];
        if (codeDescriptionSupport != null && codeDescriptionSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dataSupport');
      try {
        final dataSupport = obj['dataSupport'];
        if (dataSupport != null && dataSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('relatedInformation');
      try {
        final relatedInformation = obj['relatedInformation'];
        if (relatedInformation != null && relatedInformation is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        final tagSupport = obj['tagSupport'];
        if (tagSupport != null &&
            !PublishDiagnosticsClientCapabilitiesTagSupport.canParse(
                tagSupport, reporter)) {
          reporter.reportError(
              'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('versionSupport');
      try {
        final versionSupport = obj['versionSupport'];
        if (versionSupport != null && versionSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type PublishDiagnosticsClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PublishDiagnosticsClientCapabilities &&
        other.runtimeType == PublishDiagnosticsClientCapabilities) {
      return codeDescriptionSupport == other.codeDescriptionSupport &&
          dataSupport == other.dataSupport &&
          relatedInformation == other.relatedInformation &&
          tagSupport == other.tagSupport &&
          versionSupport == other.versionSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        codeDescriptionSupport,
        dataSupport,
        relatedInformation,
        tagSupport,
        versionSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PublishDiagnosticsClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PublishDiagnosticsClientCapabilitiesTagSupport.canParse,
    PublishDiagnosticsClientCapabilitiesTagSupport.fromJson,
  );

  PublishDiagnosticsClientCapabilitiesTagSupport({
    required this.valueSet,
  });
  static PublishDiagnosticsClientCapabilitiesTagSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => DiagnosticTag.fromJson(item as int))
        .toList();
    return PublishDiagnosticsClientCapabilitiesTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<DiagnosticTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final valueSet = obj['valueSet'];
        if (valueSet == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (valueSet is! List<Object?> ||
            valueSet.any((item) => !DiagnosticTag.canParse(item, reporter))) {
          reporter.reportError('must be of type List<DiagnosticTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PublishDiagnosticsClientCapabilitiesTagSupport &&
        other.runtimeType == PublishDiagnosticsClientCapabilitiesTagSupport) {
      return listEqual(valueSet, other.valueSet,
              (DiagnosticTag a, DiagnosticTag b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PublishDiagnosticsParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PublishDiagnosticsParams.canParse,
    PublishDiagnosticsParams.fromJson,
  );

  PublishDiagnosticsParams({
    required this.diagnostics,
    required this.uri,
    this.version,
  });
  static PublishDiagnosticsParams fromJson(Map<String, Object?> json) {
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = (diagnosticsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return PublishDiagnosticsParams(
      diagnostics: diagnostics,
      uri: uri,
      version: version,
    );
  }

  /// An array of diagnostic information items.
  final List<Diagnostic> diagnostics;

  /// The URI for which diagnostic information is reported.
  final String uri;

  /// Optional the version number of the document the diagnostics are published
  /// for.
  ///  @since 3.15.0
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['diagnostics'] = diagnostics.map((item) => item.toJson()).toList();
    result['uri'] = uri;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('diagnostics');
      try {
        if (!obj.containsKey('diagnostics')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final diagnostics = obj['diagnostics'];
        if (diagnostics == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (diagnostics is! List<Object?> ||
            diagnostics.any((item) => !Diagnostic.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PublishDiagnosticsParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PublishDiagnosticsParams &&
        other.runtimeType == PublishDiagnosticsParams) {
      return listEqual(diagnostics, other.diagnostics,
              (Diagnostic a, Diagnostic b) => a == b) &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(diagnostics),
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class Range implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Range.canParse,
    Range.fromJson,
  );

  Range({
    required this.end,
    required this.start,
  });
  static Range fromJson(Map<String, Object?> json) {
    final endJson = json['end'];
    final end = Position.fromJson(endJson as Map<String, Object?>);
    final startJson = json['start'];
    final start = Position.fromJson(startJson as Map<String, Object?>);
    return Range(
      end: end,
      start: start,
    );
  }

  /// The range's end position.
  final Position end;

  /// The range's start position.
  final Position start;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['end'] = end.toJson();
    result['start'] = start.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('end');
      try {
        if (!obj.containsKey('end')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final end = obj['end'];
        if (end == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(end, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('start');
      try {
        if (!obj.containsKey('start')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final start = obj['start'];
        if (start == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(start, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Range');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is Range && other.runtimeType == Range) {
      return end == other.end && start == other.start && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        end,
        start,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ReferenceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceClientCapabilities.canParse,
    ReferenceClientCapabilities.fromJson,
  );

  ReferenceClientCapabilities({
    this.dynamicRegistration,
  });
  static ReferenceClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return ReferenceClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether references supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['includeDeclaration'] = includeDeclaration;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('includeDeclaration');
      try {
        if (!obj.containsKey('includeDeclaration')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final includeDeclaration = obj['includeDeclaration'];
        if (includeDeclaration == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (includeDeclaration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceParams.canParse,
    ReferenceParams.fromJson,
  );

  ReferenceParams({
    required this.context,
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static ReferenceParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context =
        ReferenceContext.fromJson(contextJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return ReferenceParams(
      context: context,
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  final ReferenceContext context;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['context'] = context.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('context');
      try {
        if (!obj.containsKey('context')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final context = obj['context'];
        if (context == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!ReferenceContext.canParse(context, reporter)) {
          reporter.reportError('must be of type ReferenceContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ReferenceParams && other.runtimeType == ReferenceParams) {
      return context == other.context &&
          partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        context,
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ReferenceRegistrationOptions
    implements ReferenceOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceRegistrationOptions.canParse,
    ReferenceRegistrationOptions.fromJson,
  );

  ReferenceRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static ReferenceRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ReferenceRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ReferenceRegistrationOptions &&
        other.runtimeType == ReferenceRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['id'] = id;
    result['method'] = method;
    if (registerOptions != null) {
      result['registerOptions'] = registerOptions;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final id = obj['id'];
        if (id == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('method');
      try {
        if (!obj.containsKey('method')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final method = obj['method'];
        if (method == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (method is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Registration');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['registrations'] =
        registrations.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('registrations');
      try {
        if (!obj.containsKey('registrations')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final registrations = obj['registrations'];
        if (registrations == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (registrations is! List<Object?> ||
            registrations
                .any((item) => !Registration.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Registration>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RegistrationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['engine'] = engine;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('engine');
      try {
        if (!obj.containsKey('engine')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final engine = obj['engine'];
        if (engine == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (engine is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        final version = obj['version'];
        if (version != null && version is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type RegularExpressionsClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RegularExpressionsClientCapabilities &&
        other.runtimeType == RegularExpressionsClientCapabilities) {
      return engine == other.engine && version == other.version && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        engine,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A full diagnostic report with a set of related documents.
///  @since 3.17.0
class RelatedFullDocumentDiagnosticReport
    implements FullDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RelatedFullDocumentDiagnosticReport.canParse,
    RelatedFullDocumentDiagnosticReport.fromJson,
  );

  RelatedFullDocumentDiagnosticReport({
    required this.items,
    this.kind = 'full',
    this.relatedDocuments,
    this.resultId,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static RelatedFullDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>?)
        ?.map((key, value) => MapEntry(
            key as String,
            FullDocumentDiagnosticReport.canParse(value, nullLspJsonReporter)
                ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t1(
                    FullDocumentDiagnosticReport.fromJson(
                        value as Map<String, Object?>))
                : (UnchangedDocumentDiagnosticReport.canParse(
                        value, nullLspJsonReporter)
                    ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t2(
                        UnchangedDocumentDiagnosticReport.fromJson(
                            value as Map<String, Object?>))
                    : (throw '''$value was not one of (FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport)'''))));
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return RelatedFullDocumentDiagnosticReport(
      items: items,
      kind: kind,
      relatedDocuments: relatedDocuments,
      resultId: resultId,
    );
  }

  /// The actual items.
  @override
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  @override
  final String kind;

  /// Diagnostics of related documents. This information is useful in
  /// programming languages where code in a file A can generate diagnostics in a
  /// file B which A depends on. An example of such a language is C/C++ where
  /// marco definitions in a file a.cpp and result in errors in a header file
  /// b.hpp.
  ///  @since 3.17.0
  final Map<
      String,
      Either2<FullDocumentDiagnosticReport,
          UnchangedDocumentDiagnosticReport>>? relatedDocuments;

  /// An optional result id. If provided it will be sent on the next diagnostic
  /// request for the same document.
  @override
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    result['kind'] = kind;
    if (relatedDocuments != null) {
      result['relatedDocuments'] = relatedDocuments;
    }
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) => !Diagnostic.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'full') {
          reporter.reportError('must be the literal \'full\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('relatedDocuments');
      try {
        final relatedDocuments = obj['relatedDocuments'];
        if (relatedDocuments != null &&
            (relatedDocuments is! Map ||
                (relatedDocuments.keys.any((item) =>
                    item is! String ||
                    relatedDocuments.values.any((item) =>
                        !FullDocumentDiagnosticReport.canParse(
                            item, reporter) &&
                        !UnchangedDocumentDiagnosticReport.canParse(
                            item, reporter)))))) {
          reporter.reportError(
              'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type RelatedFullDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RelatedFullDocumentDiagnosticReport &&
        other.runtimeType == RelatedFullDocumentDiagnosticReport) {
      return listEqual(
              items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
          kind == other.kind &&
          mapEqual(
              relatedDocuments,
              other.relatedDocuments,
              (Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          a,
                      Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(items),
        kind,
        lspHashCode(relatedDocuments),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An unchanged diagnostic report with a set of related documents.
///  @since 3.17.0
class RelatedUnchangedDocumentDiagnosticReport
    implements UnchangedDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RelatedUnchangedDocumentDiagnosticReport.canParse,
    RelatedUnchangedDocumentDiagnosticReport.fromJson,
  );

  RelatedUnchangedDocumentDiagnosticReport({
    this.kind = 'unchanged',
    this.relatedDocuments,
    required this.resultId,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static RelatedUnchangedDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>?)
        ?.map((key, value) => MapEntry(
            key as String,
            FullDocumentDiagnosticReport.canParse(value, nullLspJsonReporter)
                ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t1(
                    FullDocumentDiagnosticReport.fromJson(
                        value as Map<String, Object?>))
                : (UnchangedDocumentDiagnosticReport.canParse(
                        value, nullLspJsonReporter)
                    ? Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>.t2(
                        UnchangedDocumentDiagnosticReport.fromJson(
                            value as Map<String, Object?>))
                    : (throw '''$value was not one of (FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport)'''))));
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    return RelatedUnchangedDocumentDiagnosticReport(
      kind: kind,
      relatedDocuments: relatedDocuments,
      resultId: resultId,
    );
  }

  /// A document diagnostic report indicating no changes to the last result. A
  /// server can only return `unchanged` if result ids are provided.
  @override
  final String kind;

  /// Diagnostics of related documents. This information is useful in
  /// programming languages where code in a file A can generate diagnostics in a
  /// file B which A depends on. An example of such a language is C/C++ where
  /// marco definitions in a file a.cpp and result in errors in a header file
  /// b.hpp.
  ///  @since 3.17.0
  final Map<
      String,
      Either2<FullDocumentDiagnosticReport,
          UnchangedDocumentDiagnosticReport>>? relatedDocuments;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  @override
  final String resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    if (relatedDocuments != null) {
      result['relatedDocuments'] = relatedDocuments;
    }
    result['resultId'] = resultId;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'unchanged') {
          reporter.reportError('must be the literal \'unchanged\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('relatedDocuments');
      try {
        final relatedDocuments = obj['relatedDocuments'];
        if (relatedDocuments != null &&
            (relatedDocuments is! Map ||
                (relatedDocuments.keys.any((item) =>
                    item is! String ||
                    relatedDocuments.values.any((item) =>
                        !FullDocumentDiagnosticReport.canParse(
                            item, reporter) &&
                        !UnchangedDocumentDiagnosticReport.canParse(
                            item, reporter)))))) {
          reporter.reportError(
              'must be of type Map<String, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        if (!obj.containsKey('resultId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final resultId = obj['resultId'];
        if (resultId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type RelatedUnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RelatedUnchangedDocumentDiagnosticReport &&
        other.runtimeType == RelatedUnchangedDocumentDiagnosticReport) {
      return kind == other.kind &&
          mapEqual(
              relatedDocuments,
              other.relatedDocuments,
              (Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          a,
                      Either2<FullDocumentDiagnosticReport,
                              UnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        lspHashCode(relatedDocuments),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A relative pattern is a helper to construct glob patterns that are matched
/// relatively to a base URI. The common value for a `baseUri` is a workspace
/// folder root, but it can be another absolute URI as well.
///  @since 3.17.0
class RelativePattern implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RelativePattern.canParse,
    RelativePattern.fromJson,
  );

  RelativePattern({
    required this.baseUri,
    required this.pattern,
  });
  static RelativePattern fromJson(Map<String, Object?> json) {
    final baseUriJson = json['baseUri'];
    final baseUri = baseUriJson is String
        ? Either2<String, WorkspaceFolder>.t1(baseUriJson)
        : (WorkspaceFolder.canParse(baseUriJson, nullLspJsonReporter)
            ? Either2<String, WorkspaceFolder>.t2(
                WorkspaceFolder.fromJson(baseUriJson as Map<String, Object?>))
            : (throw '''$baseUriJson was not one of (String, WorkspaceFolder)'''));
    final patternJson = json['pattern'];
    final pattern = patternJson as String;
    return RelativePattern(
      baseUri: baseUri,
      pattern: pattern,
    );
  }

  /// A workspace folder or a base URI to which this pattern will be matched
  /// against relatively.
  final Either2<String, WorkspaceFolder> baseUri;

  /// The actual glob pattern;
  final String pattern;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['baseUri'] = baseUri;
    result['pattern'] = pattern;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('baseUri');
      try {
        if (!obj.containsKey('baseUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final baseUri = obj['baseUri'];
        if (baseUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (baseUri is! String &&
            !WorkspaceFolder.canParse(baseUri, reporter)) {
          reporter
              .reportError('must be of type Either2<String, WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        if (!obj.containsKey('pattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final pattern = obj['pattern'];
        if (pattern == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RelativePattern');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RelativePattern && other.runtimeType == RelativePattern) {
      return baseUri == other.baseUri && pattern == other.pattern && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        baseUri,
        pattern,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RenameClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameClientCapabilities.canParse,
    RenameClientCapabilities.fromJson,
  );

  RenameClientCapabilities({
    this.dynamicRegistration,
    this.honorsChangeAnnotations,
    this.prepareSupport,
    this.prepareSupportDefaultBehavior,
  });
  static RenameClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final honorsChangeAnnotationsJson = json['honorsChangeAnnotations'];
    final honorsChangeAnnotations = honorsChangeAnnotationsJson as bool?;
    final prepareSupportJson = json['prepareSupport'];
    final prepareSupport = prepareSupportJson as bool?;
    final prepareSupportDefaultBehaviorJson =
        json['prepareSupportDefaultBehavior'];
    final prepareSupportDefaultBehavior =
        prepareSupportDefaultBehaviorJson != null
            ? PrepareSupportDefaultBehavior.fromJson(
                prepareSupportDefaultBehaviorJson as int)
            : null;
    return RenameClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      honorsChangeAnnotations: honorsChangeAnnotations,
      prepareSupport: prepareSupport,
      prepareSupportDefaultBehavior: prepareSupportDefaultBehavior,
    );
  }

  /// Whether rename supports dynamic registration.
  final bool? dynamicRegistration;

  /// Whether th client honors the change annotations in text edits and resource
  /// operations returned via the rename request's workspace edit by for example
  /// presenting the workspace edit in the user interface and asking for
  /// confirmation.
  ///  @since 3.16.0
  final bool? honorsChangeAnnotations;

  /// Client supports testing for validity of rename operations before
  /// execution.
  ///  @since version 3.12.0
  final bool? prepareSupport;

  /// Client supports the default behavior result (`{ defaultBehavior: boolean
  /// }`).
  ///
  /// The value indicates the default behavior used by the client.
  ///  @since version 3.16.0
  final PrepareSupportDefaultBehavior? prepareSupportDefaultBehavior;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (honorsChangeAnnotations != null) {
      result['honorsChangeAnnotations'] = honorsChangeAnnotations;
    }
    if (prepareSupport != null) {
      result['prepareSupport'] = prepareSupport;
    }
    if (prepareSupportDefaultBehavior != null) {
      result['prepareSupportDefaultBehavior'] =
          prepareSupportDefaultBehavior?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('honorsChangeAnnotations');
      try {
        final honorsChangeAnnotations = obj['honorsChangeAnnotations'];
        if (honorsChangeAnnotations != null &&
            honorsChangeAnnotations is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('prepareSupport');
      try {
        final prepareSupport = obj['prepareSupport'];
        if (prepareSupport != null && prepareSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('prepareSupportDefaultBehavior');
      try {
        final prepareSupportDefaultBehavior =
            obj['prepareSupportDefaultBehavior'];
        if (prepareSupportDefaultBehavior != null &&
            !PrepareSupportDefaultBehavior.canParse(
                prepareSupportDefaultBehavior, reporter)) {
          reporter.reportError('must be of type PrepareSupportDefaultBehavior');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameClientCapabilities &&
        other.runtimeType == RenameClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          honorsChangeAnnotations == other.honorsChangeAnnotations &&
          prepareSupport == other.prepareSupport &&
          prepareSupportDefaultBehavior ==
              other.prepareSupportDefaultBehavior &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        honorsChangeAnnotations,
        prepareSupport,
        prepareSupportDefaultBehavior,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Rename file operation
class RenameFile implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFile.canParse,
    RenameFile.fromJson,
  );

  RenameFile({
    this.annotationId,
    this.kind = 'rename',
    required this.newUri,
    required this.oldUri,
    this.options,
  }) {
    if (kind != 'rename') {
      throw 'kind may only be the literal \'rename\'';
    }
  }
  static RenameFile fromJson(Map<String, Object?> json) {
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final newUriJson = json['newUri'];
    final newUri = newUriJson as String;
    final oldUriJson = json['oldUri'];
    final oldUri = oldUriJson as String;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? RenameFileOptions.fromJson(optionsJson as Map<String, Object?>)
        : null;
    return RenameFile(
      annotationId: annotationId,
      kind: kind,
      newUri: newUri,
      oldUri: oldUri,
      options: options,
    );
  }

  /// An optional annotation identifier describing the operation.
  ///  @since 3.16.0
  final String? annotationId;

  /// A rename
  final String kind;

  /// The new location.
  final String newUri;

  /// The old (existing) location.
  final String oldUri;

  /// Rename options.
  final RenameFileOptions? options;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (annotationId != null) {
      result['annotationId'] = annotationId;
    }
    result['kind'] = kind;
    result['newUri'] = newUri;
    result['oldUri'] = oldUri;
    if (options != null) {
      result['options'] = options?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('annotationId');
      try {
        final annotationId = obj['annotationId'];
        if (annotationId != null && annotationId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'rename') {
          reporter.reportError('must be the literal \'rename\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('newUri');
      try {
        if (!obj.containsKey('newUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newUri = obj['newUri'];
        if (newUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('oldUri');
      try {
        if (!obj.containsKey('oldUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final oldUri = obj['oldUri'];
        if (oldUri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (oldUri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        final options = obj['options'];
        if (options != null && !RenameFileOptions.canParse(options, reporter)) {
          reporter.reportError('must be of type RenameFileOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameFile');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameFile && other.runtimeType == RenameFile) {
      return annotationId == other.annotationId &&
          kind == other.kind &&
          newUri == other.newUri &&
          oldUri == other.oldUri &&
          options == other.options &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        annotationId,
        kind,
        newUri,
        oldUri,
        options,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Rename file options
class RenameFileOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFileOptions.canParse,
    RenameFileOptions.fromJson,
  );

  RenameFileOptions({
    this.ignoreIfExists,
    this.overwrite,
  });
  static RenameFileOptions fromJson(Map<String, Object?> json) {
    final ignoreIfExistsJson = json['ignoreIfExists'];
    final ignoreIfExists = ignoreIfExistsJson as bool?;
    final overwriteJson = json['overwrite'];
    final overwrite = overwriteJson as bool?;
    return RenameFileOptions(
      ignoreIfExists: ignoreIfExists,
      overwrite: overwrite,
    );
  }

  /// Ignores if target exists.
  final bool? ignoreIfExists;

  /// Overwrite target if existing. Overwrite wins over `ignoreIfExists`
  final bool? overwrite;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (ignoreIfExists != null) {
      result['ignoreIfExists'] = ignoreIfExists;
    }
    if (overwrite != null) {
      result['overwrite'] = overwrite;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('ignoreIfExists');
      try {
        final ignoreIfExists = obj['ignoreIfExists'];
        if (ignoreIfExists != null && ignoreIfExists is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('overwrite');
      try {
        final overwrite = obj['overwrite'];
        if (overwrite != null && overwrite is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameFileOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameFileOptions && other.runtimeType == RenameFileOptions) {
      return ignoreIfExists == other.ignoreIfExists &&
          overwrite == other.overwrite &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        ignoreIfExists,
        overwrite,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters sent in notifications/requests for user-initiated renames of
/// files.
///  @since 3.16.0
class RenameFilesParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFilesParams.canParse,
    RenameFilesParams.fromJson,
  );

  RenameFilesParams({
    required this.files,
  });
  static RenameFilesParams fromJson(Map<String, Object?> json) {
    final filesJson = json['files'];
    final files = (filesJson as List<Object?>)
        .map((item) => FileRename.fromJson(item as Map<String, Object?>))
        .toList();
    return RenameFilesParams(
      files: files,
    );
  }

  /// An array of all files/folders renamed in this operation. When a folder is
  /// renamed, only the folder will be included, and not its children.
  final List<FileRename> files;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['files'] = files.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('files');
      try {
        if (!obj.containsKey('files')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final files = obj['files'];
        if (files == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (files is! List<Object?> ||
            files.any((item) => !FileRename.canParse(item, reporter))) {
          reporter.reportError('must be of type List<FileRename>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameFilesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (prepareProvider != null) {
      result['prepareProvider'] = prepareProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('prepareProvider');
      try {
        final prepareProvider = obj['prepareProvider'];
        if (prepareProvider != null && prepareProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameOptions && other.runtimeType == RenameOptions) {
      return prepareProvider == other.prepareProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        prepareProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RenameParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameParams.canParse,
    RenameParams.fromJson,
  );

  RenameParams({
    required this.newName,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static RenameParams fromJson(Map<String, Object?> json) {
    final newNameJson = json['newName'];
    final newName = newNameJson as String;
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return RenameParams(
      newName: newName,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The new name of the symbol. If the given name is not valid the request
  /// must return a [ResponseError] with an appropriate message set.
  final String newName;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['newName'] = newName;
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('newName');
      try {
        if (!obj.containsKey('newName')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newName = obj['newName'];
        if (newName == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newName is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameParams && other.runtimeType == RenameParams) {
      return newName == other.newName &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        newName,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RenameRegistrationOptions
    implements RenameOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameRegistrationOptions.canParse,
    RenameRegistrationOptions.fromJson,
  );

  RenameRegistrationOptions({
    this.documentSelector,
    this.prepareProvider,
    this.workDoneProgress,
  });
  static RenameRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final prepareProviderJson = json['prepareProvider'];
    final prepareProvider = prepareProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return RenameRegistrationOptions(
      documentSelector: documentSelector,
      prepareProvider: prepareProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// Renames should be checked and tested before being executed.
  @override
  final bool? prepareProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (prepareProvider != null) {
      result['prepareProvider'] = prepareProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('prepareProvider');
      try {
        final prepareProvider = obj['prepareProvider'];
        if (prepareProvider != null && prepareProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameRegistrationOptions &&
        other.runtimeType == RenameRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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 ResourceOperationKind implements ToJsonable {
  const ResourceOperationKind._(this._value);
  const ResourceOperationKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'create':
      case 'delete':
      case 'rename':
        return true;
    }
    return false;
  }

  /// Supports creating new files and folders.
  static const Create = ResourceOperationKind._('create');

  /// Supports deleting existing files and folders.
  static const Delete = ResourceOperationKind._('delete');

  /// Supports renaming existing files and folders.
  static const Rename = ResourceOperationKind._('rename');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is ResourceOperationKind && other._value == _value;
}

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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (includeText != null) {
      result['includeText'] = includeText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('includeText');
      try {
        final includeText = obj['includeText'];
        if (includeText != null && includeText is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SaveOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SaveOptions && other.runtimeType == SaveOptions) {
      return includeText == other.includeText && true;
    }
    return false;
  }

  @override
  int get hashCode => includeText.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRange.canParse,
    SelectionRange.fromJson,
  );

  SelectionRange({
    this.parent,
    required this.range,
  });
  static SelectionRange fromJson(Map<String, Object?> json) {
    final parentJson = json['parent'];
    final parent = parentJson != null
        ? SelectionRange.fromJson(parentJson as Map<String, Object?>)
        : null;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return SelectionRange(
      parent: parent,
      range: range,
    );
  }

  /// The parent selection range containing this range. Therefore `parent.range`
  /// must contain `this.range`.
  final SelectionRange? parent;

  /// The range ([Range]) of this selection range.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (parent != null) {
      result['parent'] = parent?.toJson();
    }
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('parent');
      try {
        final parent = obj['parent'];
        if (parent != null && !SelectionRange.canParse(parent, reporter)) {
          reporter.reportError('must be of type SelectionRange');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SelectionRange && other.runtimeType == SelectionRange) {
      return parent == other.parent && range == other.range && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        parent,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeClientCapabilities.canParse,
    SelectionRangeClientCapabilities.fromJson,
  );

  SelectionRangeClientCapabilities({
    this.dynamicRegistration,
  });
  static SelectionRangeClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return SelectionRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration for selection range
  /// providers. If this is set to `true` the client supports the new
  /// `SelectionRangeRegistrationOptions` return value for the corresponding
  /// server capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeParams.canParse,
    SelectionRangeParams.fromJson,
  );

  SelectionRangeParams({
    this.partialResultToken,
    required this.positions,
    required this.textDocument,
    this.workDoneToken,
  });
  static SelectionRangeParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionsJson = json['positions'];
    final positions = (positionsJson as List<Object?>)
        .map((item) => Position.fromJson(item as Map<String, Object?>))
        .toList();
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SelectionRangeParams(
      partialResultToken: partialResultToken,
      positions: positions,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The positions inside the text document.
  final List<Position> positions;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['positions'] = positions.map((item) => item.toJson()).toList();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('positions');
      try {
        if (!obj.containsKey('positions')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final positions = obj['positions'];
        if (positions == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (positions is! List<Object?> ||
            positions.any((item) => !Position.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Position>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SelectionRangeParams &&
        other.runtimeType == SelectionRangeParams) {
      return partialResultToken == other.partialResultToken &&
          listEqual(
              positions, other.positions, (Position a, Position b) => a == b) &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        lspHashCode(positions),
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeRegistrationOptions
    implements
        SelectionRangeOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeRegistrationOptions.canParse,
    SelectionRangeRegistrationOptions.fromJson,
  );

  SelectionRangeRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static SelectionRangeRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SelectionRangeRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SelectionRangeRegistrationOptions &&
        other.runtimeType == SelectionRangeRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokenModifiers implements ToJsonable {
  const SemanticTokenModifiers(this._value);
  const SemanticTokenModifiers.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  static const abstract = SemanticTokenModifiers('abstract');
  static const async = SemanticTokenModifiers('async');
  static const declaration = SemanticTokenModifiers('declaration');
  static const defaultLibrary = SemanticTokenModifiers('defaultLibrary');
  static const definition = SemanticTokenModifiers('definition');
  static const deprecated = SemanticTokenModifiers('deprecated');
  static const documentation = SemanticTokenModifiers('documentation');
  static const modification = SemanticTokenModifiers('modification');
  static const readonly = SemanticTokenModifiers('readonly');
  static const static = SemanticTokenModifiers('static');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SemanticTokenModifiers && other._value == _value;
}

class SemanticTokenTypes implements ToJsonable {
  const SemanticTokenTypes(this._value);
  const SemanticTokenTypes.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  static const class_ = SemanticTokenTypes('class');
  static const comment = SemanticTokenTypes('comment');

  /// @since 3.17.0
  static const decorator = SemanticTokenTypes('decorator');
  static const enum_ = SemanticTokenTypes('enum');
  static const enumMember = SemanticTokenTypes('enumMember');
  static const event = SemanticTokenTypes('event');
  static const function = SemanticTokenTypes('function');
  static const interface = SemanticTokenTypes('interface');
  static const keyword = SemanticTokenTypes('keyword');
  static const macro = SemanticTokenTypes('macro');
  static const method = SemanticTokenTypes('method');
  static const modifier = SemanticTokenTypes('modifier');
  static const namespace = SemanticTokenTypes('namespace');
  static const number = SemanticTokenTypes('number');
  static const operator = SemanticTokenTypes('operator');
  static const parameter = SemanticTokenTypes('parameter');
  static const property = SemanticTokenTypes('property');
  static const regexp = SemanticTokenTypes('regexp');
  static const string = SemanticTokenTypes('string');
  static const struct = SemanticTokenTypes('struct');

  /// Represents a generic type. Acts as a fallback for types which can't be
  /// mapped to a specific type like class or enum.
  static const type = SemanticTokenTypes('type');
  static const typeParameter = SemanticTokenTypes('typeParameter');
  static const variable = SemanticTokenTypes('variable');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SemanticTokenTypes && other._value == _value;
}

class SemanticTokens implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokens.canParse,
    SemanticTokens.fromJson,
  );

  SemanticTokens({
    required this.data,
    this.resultId,
  });
  static SemanticTokens fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>).map((item) => item as int).toList();
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return SemanticTokens(
      data: data,
      resultId: resultId,
    );
  }

  /// The actual tokens.
  final List<int> data;

  /// An optional result id. If provided and clients support delta updating the
  /// client will include the result id in the next semantic token request. A
  /// server can then instead of computing all semantic tokens again simply send
  /// a delta.
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['data'] = data;
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('data');
      try {
        if (!obj.containsKey('data')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final data = obj['data'];
        if (data == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (data is! List<Object?> || data.any((item) => item is! int)) {
          reporter.reportError('must be of type List<int>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokens');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokens && other.runtimeType == SemanticTokens) {
      return listEqual(data, other.data, (int a, int b) => a == b) &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilities.canParse,
    SemanticTokensClientCapabilities.fromJson,
  );

  SemanticTokensClientCapabilities({
    this.augmentsSyntaxTokens,
    this.dynamicRegistration,
    required this.formats,
    this.multilineTokenSupport,
    this.overlappingTokenSupport,
    required this.requests,
    this.serverCancelSupport,
    required this.tokenModifiers,
    required this.tokenTypes,
  });
  static SemanticTokensClientCapabilities fromJson(Map<String, Object?> json) {
    final augmentsSyntaxTokensJson = json['augmentsSyntaxTokens'];
    final augmentsSyntaxTokens = augmentsSyntaxTokensJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final formatsJson = json['formats'];
    final formats = (formatsJson as List<Object?>)
        .map((item) => TokenFormat.fromJson(item as String))
        .toList();
    final multilineTokenSupportJson = json['multilineTokenSupport'];
    final multilineTokenSupport = multilineTokenSupportJson as bool?;
    final overlappingTokenSupportJson = json['overlappingTokenSupport'];
    final overlappingTokenSupport = overlappingTokenSupportJson as bool?;
    final requestsJson = json['requests'];
    final requests = SemanticTokensClientCapabilitiesRequests.fromJson(
        requestsJson as Map<String, Object?>);
    final serverCancelSupportJson = json['serverCancelSupport'];
    final serverCancelSupport = serverCancelSupportJson as bool?;
    final tokenModifiersJson = json['tokenModifiers'];
    final tokenModifiers = (tokenModifiersJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    final tokenTypesJson = json['tokenTypes'];
    final tokenTypes = (tokenTypesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return SemanticTokensClientCapabilities(
      augmentsSyntaxTokens: augmentsSyntaxTokens,
      dynamicRegistration: dynamicRegistration,
      formats: formats,
      multilineTokenSupport: multilineTokenSupport,
      overlappingTokenSupport: overlappingTokenSupport,
      requests: requests,
      serverCancelSupport: serverCancelSupport,
      tokenModifiers: tokenModifiers,
      tokenTypes: tokenTypes,
    );
  }

  /// Whether the client uses semantic tokens to augment existing syntax tokens.
  /// If set to `true` client side created syntax tokens and semantic tokens are
  /// both used for colorization. If set to `false` the client only uses the
  /// returned semantic tokens for colorization.
  ///
  /// If the value is `undefined` then the client behavior is not specified.
  ///  @since 3.17.0
  final bool? augmentsSyntaxTokens;

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  /// The formats the clients supports.
  final List<TokenFormat> formats;

  /// Whether the client supports tokens that can span multiple lines.
  final bool? multilineTokenSupport;

  /// Whether the client supports tokens that can overlap each other.
  final bool? overlappingTokenSupport;

  /// Which requests the client supports and might send to the server depending
  /// on the server's capability. Please note that clients might not show
  /// semantic tokens or degrade some of the user experience if a range or full
  /// request is advertised by the client but not provided by the server. If for
  /// example the client capability `requests.full` and `request.range` are both
  /// set to true but the server only provides a range provider the client might
  /// not render a minimap correctly or might even decide to not show any
  /// semantic tokens at all.
  final SemanticTokensClientCapabilitiesRequests requests;

  /// Whether the client allows the server to actively cancel a semantic token
  /// request, e.g. supports returning ErrorCodes.ServerCancelled. If a server
  /// does the client needs to retrigger the request.
  ///  @since 3.17.0
  final bool? serverCancelSupport;

  /// The token modifiers that the client supports.
  final List<String> tokenModifiers;

  /// The token types that the client supports.
  final List<String> tokenTypes;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (augmentsSyntaxTokens != null) {
      result['augmentsSyntaxTokens'] = augmentsSyntaxTokens;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    result['formats'] = formats.map((item) => item.toJson()).toList();
    if (multilineTokenSupport != null) {
      result['multilineTokenSupport'] = multilineTokenSupport;
    }
    if (overlappingTokenSupport != null) {
      result['overlappingTokenSupport'] = overlappingTokenSupport;
    }
    result['requests'] = requests.toJson();
    if (serverCancelSupport != null) {
      result['serverCancelSupport'] = serverCancelSupport;
    }
    result['tokenModifiers'] = tokenModifiers;
    result['tokenTypes'] = tokenTypes;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('augmentsSyntaxTokens');
      try {
        final augmentsSyntaxTokens = obj['augmentsSyntaxTokens'];
        if (augmentsSyntaxTokens != null && augmentsSyntaxTokens is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('formats');
      try {
        if (!obj.containsKey('formats')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final formats = obj['formats'];
        if (formats == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (formats is! List<Object?> ||
            formats.any((item) => !TokenFormat.canParse(item, reporter))) {
          reporter.reportError('must be of type List<TokenFormat>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('multilineTokenSupport');
      try {
        final multilineTokenSupport = obj['multilineTokenSupport'];
        if (multilineTokenSupport != null && multilineTokenSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('overlappingTokenSupport');
      try {
        final overlappingTokenSupport = obj['overlappingTokenSupport'];
        if (overlappingTokenSupport != null &&
            overlappingTokenSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('requests');
      try {
        if (!obj.containsKey('requests')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final requests = obj['requests'];
        if (requests == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SemanticTokensClientCapabilitiesRequests.canParse(
            requests, reporter)) {
          reporter.reportError(
              'must be of type SemanticTokensClientCapabilitiesRequests');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('serverCancelSupport');
      try {
        final serverCancelSupport = obj['serverCancelSupport'];
        if (serverCancelSupport != null && serverCancelSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tokenModifiers');
      try {
        if (!obj.containsKey('tokenModifiers')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tokenModifiers = obj['tokenModifiers'];
        if (tokenModifiers == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tokenModifiers is! List<Object?> ||
            tokenModifiers.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tokenTypes');
      try {
        if (!obj.containsKey('tokenTypes')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tokenTypes = obj['tokenTypes'];
        if (tokenTypes == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tokenTypes is! List<Object?> ||
            tokenTypes.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilities &&
        other.runtimeType == SemanticTokensClientCapabilities) {
      return augmentsSyntaxTokens == other.augmentsSyntaxTokens &&
          dynamicRegistration == other.dynamicRegistration &&
          listEqual(formats, other.formats,
              (TokenFormat a, TokenFormat b) => a == b) &&
          multilineTokenSupport == other.multilineTokenSupport &&
          overlappingTokenSupport == other.overlappingTokenSupport &&
          requests == other.requests &&
          serverCancelSupport == other.serverCancelSupport &&
          listEqual(tokenModifiers, other.tokenModifiers,
              (String a, String b) => a == b) &&
          listEqual(
              tokenTypes, other.tokenTypes, (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        augmentsSyntaxTokens,
        dynamicRegistration,
        lspHashCode(formats),
        multilineTokenSupport,
        overlappingTokenSupport,
        requests,
        serverCancelSupport,
        lspHashCode(tokenModifiers),
        lspHashCode(tokenTypes),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequests implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesRequests.canParse,
    SemanticTokensClientCapabilitiesRequests.fromJson,
  );

  SemanticTokensClientCapabilitiesRequests({
    this.full,
    this.range,
  });
  static SemanticTokensClientCapabilitiesRequests fromJson(
      Map<String, Object?> json) {
    final fullJson = json['full'];
    final full = fullJson == null
        ? null
        : (fullJson is bool
            ? Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>.t1(
                fullJson)
            : (SemanticTokensClientCapabilitiesRequestsFull.canParse(
                    fullJson, nullLspJsonReporter)
                ? Either2<bool,
                        SemanticTokensClientCapabilitiesRequestsFull>.t2(
                    SemanticTokensClientCapabilitiesRequestsFull.fromJson(
                        fullJson as Map<String, Object?>))
                : (throw '''$fullJson was not one of (bool, SemanticTokensClientCapabilitiesRequestsFull)''')));
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : (rangeJson is bool
            ? Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>.t1(
                rangeJson)
            : (SemanticTokensClientCapabilitiesRequestsRange.canParse(
                    rangeJson, nullLspJsonReporter)
                ? Either2<bool,
                        SemanticTokensClientCapabilitiesRequestsRange>.t2(
                    SemanticTokensClientCapabilitiesRequestsRange.fromJson(
                        rangeJson as Map<String, Object?>))
                : (throw '''$rangeJson was not one of (bool, SemanticTokensClientCapabilitiesRequestsRange)''')));
    return SemanticTokensClientCapabilitiesRequests(
      full: full,
      range: range,
    );
  }

  /// The client will send the `textDocument/semanticTokens/full` request if the
  /// server provides a corresponding handler.
  final Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>? full;

  /// The client will send the `textDocument/semanticTokens/range` request if
  /// the server provides a corresponding handler.
  final Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>? range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (full != null) {
      result['full'] = full;
    }
    if (range != null) {
      result['range'] = range;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('full');
      try {
        final full = obj['full'];
        if (full != null &&
            full is! bool &&
            !SemanticTokensClientCapabilitiesRequestsFull.canParse(
                full, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        final range = obj['range'];
        if (range != null &&
            range is! bool &&
            !SemanticTokensClientCapabilitiesRequestsRange.canParse(
                range, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequests');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilitiesRequests &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequests) {
      return full == other.full && range == other.range && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        full,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequestsFull implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesRequestsFull.canParse,
    SemanticTokensClientCapabilitiesRequestsFull.fromJson,
  );

  SemanticTokensClientCapabilitiesRequestsFull({
    this.delta,
  });
  static SemanticTokensClientCapabilitiesRequestsFull fromJson(
      Map<String, Object?> json) {
    final deltaJson = json['delta'];
    final delta = deltaJson as bool?;
    return SemanticTokensClientCapabilitiesRequestsFull(
      delta: delta,
    );
  }

  /// The client will send the `textDocument/semanticTokens/full/delta` request
  /// if the server provides a corresponding handler.
  final bool? delta;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (delta != null) {
      result['delta'] = delta;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('delta');
      try {
        final delta = obj['delta'];
        if (delta != null && delta is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequestsFull');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilitiesRequestsFull &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequestsFull) {
      return delta == other.delta && true;
    }
    return false;
  }

  @override
  int get hashCode => delta.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequestsRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesRequestsRange.canParse,
    SemanticTokensClientCapabilitiesRequestsRange.fromJson,
  );

  static SemanticTokensClientCapabilitiesRequestsRange fromJson(
      Map<String, Object?> json) {
    return SemanticTokensClientCapabilitiesRequestsRange();
  }

  @override
  Map<String, Object?> toJson() => {};

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequestsRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilitiesRequestsRange &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequestsRange) {
      return true;
    }
    return false;
  }

  @override
  int get hashCode => 42;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensDelta implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensDelta.canParse,
    SemanticTokensDelta.fromJson,
  );

  SemanticTokensDelta({
    required this.edits,
    this.resultId,
  });
  static SemanticTokensDelta fromJson(Map<String, Object?> json) {
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map(
            (item) => SemanticTokensEdit.fromJson(item as Map<String, Object?>))
        .toList();
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return SemanticTokensDelta(
      edits: edits,
      resultId: resultId,
    );
  }

  /// The semantic token edits to transform a previous result into a new result.
  final List<SemanticTokensEdit> edits;
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['edits'] = edits.map((item) => item.toJson()).toList();
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('edits');
      try {
        if (!obj.containsKey('edits')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final edits = obj['edits'];
        if (edits == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (edits is! List<Object?> ||
            edits.any((item) => !SemanticTokensEdit.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SemanticTokensEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensDelta');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensDelta &&
        other.runtimeType == SemanticTokensDelta) {
      return listEqual(edits, other.edits,
              (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
          resultId == other.resultId &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(edits),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensDeltaParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensDeltaParams.canParse,
    SemanticTokensDeltaParams.fromJson,
  );

  SemanticTokensDeltaParams({
    this.partialResultToken,
    required this.previousResultId,
    required this.textDocument,
    this.workDoneToken,
  });
  static SemanticTokensDeltaParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final previousResultIdJson = json['previousResultId'];
    final previousResultId = previousResultIdJson as String;
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SemanticTokensDeltaParams(
      partialResultToken: partialResultToken,
      previousResultId: previousResultId,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The result id of a previous response. The result Id can either point to a
  /// full response or a delta response depending on what was received last.
  final String previousResultId;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['previousResultId'] = previousResultId;
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('previousResultId');
      try {
        if (!obj.containsKey('previousResultId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final previousResultId = obj['previousResultId'];
        if (previousResultId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (previousResultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensDeltaParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensDeltaParams &&
        other.runtimeType == SemanticTokensDeltaParams) {
      return partialResultToken == other.partialResultToken &&
          previousResultId == other.previousResultId &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        previousResultId,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensDeltaPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensDeltaPartialResult.canParse,
    SemanticTokensDeltaPartialResult.fromJson,
  );

  SemanticTokensDeltaPartialResult({
    required this.edits,
  });
  static SemanticTokensDeltaPartialResult fromJson(Map<String, Object?> json) {
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map(
            (item) => SemanticTokensEdit.fromJson(item as Map<String, Object?>))
        .toList();
    return SemanticTokensDeltaPartialResult(
      edits: edits,
    );
  }

  final List<SemanticTokensEdit> edits;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['edits'] = edits.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('edits');
      try {
        if (!obj.containsKey('edits')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final edits = obj['edits'];
        if (edits == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (edits is! List<Object?> ||
            edits.any((item) => !SemanticTokensEdit.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SemanticTokensEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensDeltaPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensDeltaPartialResult &&
        other.runtimeType == SemanticTokensDeltaPartialResult) {
      return listEqual(edits, other.edits,
              (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(edits);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensEdit.canParse,
    SemanticTokensEdit.fromJson,
  );

  SemanticTokensEdit({
    this.data,
    required this.deleteCount,
    required this.start,
  });
  static SemanticTokensEdit fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>?)?.map((item) => item as int).toList();
    final deleteCountJson = json['deleteCount'];
    final deleteCount = deleteCountJson as int;
    final startJson = json['start'];
    final start = startJson as int;
    return SemanticTokensEdit(
      data: data,
      deleteCount: deleteCount,
      start: start,
    );
  }

  /// The elements to insert.
  final List<int>? data;

  /// The count of elements to remove.
  final int deleteCount;

  /// The start offset of the edit.
  final int start;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    result['deleteCount'] = deleteCount;
    result['start'] = start;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('data');
      try {
        final data = obj['data'];
        if (data != null &&
            (data is! List<Object?> || data.any((item) => item is! int))) {
          reporter.reportError('must be of type List<int>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deleteCount');
      try {
        if (!obj.containsKey('deleteCount')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final deleteCount = obj['deleteCount'];
        if (deleteCount == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (deleteCount is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('start');
      try {
        if (!obj.containsKey('start')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final start = obj['start'];
        if (start == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (start is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensEdit &&
        other.runtimeType == SemanticTokensEdit) {
      return listEqual(data, other.data, (int a, int b) => a == b) &&
          deleteCount == other.deleteCount &&
          start == other.start &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        deleteCount,
        start,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensLegend implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensLegend.canParse,
    SemanticTokensLegend.fromJson,
  );

  SemanticTokensLegend({
    required this.tokenModifiers,
    required this.tokenTypes,
  });
  static SemanticTokensLegend fromJson(Map<String, Object?> json) {
    final tokenModifiersJson = json['tokenModifiers'];
    final tokenModifiers = (tokenModifiersJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    final tokenTypesJson = json['tokenTypes'];
    final tokenTypes = (tokenTypesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return SemanticTokensLegend(
      tokenModifiers: tokenModifiers,
      tokenTypes: tokenTypes,
    );
  }

  /// The token modifiers a server uses.
  final List<String> tokenModifiers;

  /// The token types a server uses.
  final List<String> tokenTypes;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['tokenModifiers'] = tokenModifiers;
    result['tokenTypes'] = tokenTypes;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('tokenModifiers');
      try {
        if (!obj.containsKey('tokenModifiers')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tokenModifiers = obj['tokenModifiers'];
        if (tokenModifiers == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tokenModifiers is! List<Object?> ||
            tokenModifiers.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tokenTypes');
      try {
        if (!obj.containsKey('tokenTypes')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final tokenTypes = obj['tokenTypes'];
        if (tokenTypes == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (tokenTypes is! List<Object?> ||
            tokenTypes.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensLegend');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensLegend &&
        other.runtimeType == SemanticTokensLegend) {
      return listEqual(tokenModifiers, other.tokenModifiers,
              (String a, String b) => a == b) &&
          listEqual(
              tokenTypes, other.tokenTypes, (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(tokenModifiers),
        lspHashCode(tokenTypes),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensOptions.canParse,
    SemanticTokensOptions.fromJson,
  );

  SemanticTokensOptions({
    this.full,
    required this.legend,
    this.range,
    this.workDoneProgress,
  });
  static SemanticTokensOptions fromJson(Map<String, Object?> json) {
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    final fullJson = json['full'];
    final full = fullJson == null
        ? null
        : (fullJson is bool
            ? Either2<bool, SemanticTokensOptionsFull>.t1(fullJson)
            : (SemanticTokensOptionsFull.canParse(fullJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensOptionsFull>.t2(
                    SemanticTokensOptionsFull.fromJson(
                        fullJson as Map<String, Object?>))
                : (throw '''$fullJson was not one of (bool, SemanticTokensOptionsFull)''')));
    final legendJson = json['legend'];
    final legend =
        SemanticTokensLegend.fromJson(legendJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : (rangeJson is bool
            ? Either2<bool, SemanticTokensOptionsRange>.t1(rangeJson)
            : (SemanticTokensOptionsRange.canParse(
                    rangeJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensOptionsRange>.t2(
                    SemanticTokensOptionsRange.fromJson(
                        rangeJson as Map<String, Object?>))
                : (throw '''$rangeJson was not one of (bool, SemanticTokensOptionsRange)''')));
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SemanticTokensOptions(
      full: full,
      legend: legend,
      range: range,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Server supports providing semantic tokens for a full document.
  final Either2<bool, SemanticTokensOptionsFull>? full;

  /// The legend used by the server
  final SemanticTokensLegend legend;

  /// Server supports providing semantic tokens for a specific range of a
  /// document.
  final Either2<bool, SemanticTokensOptionsRange>? range;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (full != null) {
      result['full'] = full;
    }
    result['legend'] = legend.toJson();
    if (range != null) {
      result['range'] = range;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('full');
      try {
        final full = obj['full'];
        if (full != null &&
            full is! bool &&
            !SemanticTokensOptionsFull.canParse(full, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('legend');
      try {
        if (!obj.containsKey('legend')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final legend = obj['legend'];
        if (legend == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SemanticTokensLegend.canParse(legend, reporter)) {
          reporter.reportError('must be of type SemanticTokensLegend');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        final range = obj['range'];
        if (range != null &&
            range is! bool &&
            !SemanticTokensOptionsRange.canParse(range, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensOptions &&
        other.runtimeType == SemanticTokensOptions) {
      return full == other.full &&
          legend == other.legend &&
          range == other.range &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        full,
        legend,
        range,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensOptionsFull implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensOptionsFull.canParse,
    SemanticTokensOptionsFull.fromJson,
  );

  SemanticTokensOptionsFull({
    this.delta,
  });
  static SemanticTokensOptionsFull fromJson(Map<String, Object?> json) {
    final deltaJson = json['delta'];
    final delta = deltaJson as bool?;
    return SemanticTokensOptionsFull(
      delta: delta,
    );
  }

  /// The server supports deltas for full documents.
  final bool? delta;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (delta != null) {
      result['delta'] = delta;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('delta');
      try {
        final delta = obj['delta'];
        if (delta != null && delta is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensOptionsFull');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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();
  }

  @override
  Map<String, Object?> toJson() => {};

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensOptionsRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensParams.canParse,
    SemanticTokensParams.fromJson,
  );

  SemanticTokensParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static SemanticTokensParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SemanticTokensParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensParams &&
        other.runtimeType == SemanticTokensParams) {
      return partialResultToken == other.partialResultToken &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensPartialResult.canParse,
    SemanticTokensPartialResult.fromJson,
  );

  SemanticTokensPartialResult({
    required this.data,
  });
  static SemanticTokensPartialResult fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>).map((item) => item as int).toList();
    return SemanticTokensPartialResult(
      data: data,
    );
  }

  final List<int> data;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['data'] = data;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('data');
      try {
        if (!obj.containsKey('data')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final data = obj['data'];
        if (data == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (data is! List<Object?> || data.any((item) => item is! int)) {
          reporter.reportError('must be of type List<int>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensRangeParams.canParse,
    SemanticTokensRangeParams.fromJson,
  );

  SemanticTokensRangeParams({
    this.partialResultToken,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static SemanticTokensRangeParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SemanticTokensRangeParams(
      partialResultToken: partialResultToken,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The range the semantic tokens are requested for.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensRangeParams &&
        other.runtimeType == SemanticTokensRangeParams) {
      return partialResultToken == other.partialResultToken &&
          range == other.range &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensRegistrationOptions
    implements
        SemanticTokensOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensRegistrationOptions.canParse,
    SemanticTokensRegistrationOptions.fromJson,
  );

  SemanticTokensRegistrationOptions({
    this.documentSelector,
    this.full,
    this.id,
    required this.legend,
    this.range,
    this.workDoneProgress,
  });
  static SemanticTokensRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final fullJson = json['full'];
    final full = fullJson == null
        ? null
        : (fullJson is bool
            ? Either2<bool, SemanticTokensOptionsFull>.t1(fullJson)
            : (SemanticTokensOptionsFull.canParse(fullJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensOptionsFull>.t2(
                    SemanticTokensOptionsFull.fromJson(
                        fullJson as Map<String, Object?>))
                : (throw '''$fullJson was not one of (bool, SemanticTokensOptionsFull)''')));
    final idJson = json['id'];
    final id = idJson as String?;
    final legendJson = json['legend'];
    final legend =
        SemanticTokensLegend.fromJson(legendJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : (rangeJson is bool
            ? Either2<bool, SemanticTokensOptionsRange>.t1(rangeJson)
            : (SemanticTokensOptionsRange.canParse(
                    rangeJson, nullLspJsonReporter)
                ? Either2<bool, SemanticTokensOptionsRange>.t2(
                    SemanticTokensOptionsRange.fromJson(
                        rangeJson as Map<String, Object?>))
                : (throw '''$rangeJson was not one of (bool, SemanticTokensOptionsRange)''')));
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SemanticTokensRegistrationOptions(
      documentSelector: documentSelector,
      full: full,
      id: id,
      legend: legend,
      range: range,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// Server supports providing semantic tokens for a full document.
  @override
  final Either2<bool, SemanticTokensOptionsFull>? full;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// The legend used by the server
  @override
  final SemanticTokensLegend legend;

  /// Server supports providing semantic tokens for a specific range of a
  /// document.
  @override
  final Either2<bool, SemanticTokensOptionsRange>? range;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (full != null) {
      result['full'] = full;
    }
    if (id != null) {
      result['id'] = id;
    }
    result['legend'] = legend.toJson();
    if (range != null) {
      result['range'] = range;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('full');
      try {
        final full = obj['full'];
        if (full != null &&
            full is! bool &&
            !SemanticTokensOptionsFull.canParse(full, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('legend');
      try {
        if (!obj.containsKey('legend')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final legend = obj['legend'];
        if (legend == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SemanticTokensLegend.canParse(legend, reporter)) {
          reporter.reportError('must be of type SemanticTokensLegend');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        final range = obj['range'];
        if (range != null &&
            range is! bool &&
            !SemanticTokensOptionsRange.canParse(range, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensRegistrationOptions &&
        other.runtimeType == SemanticTokensRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          full == other.full &&
          id == other.id &&
          legend == other.legend &&
          range == other.range &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        full,
        id,
        legend,
        range,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensWorkspaceClientCapabilities.canParse,
    SemanticTokensWorkspaceClientCapabilities.fromJson,
  );

  SemanticTokensWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static SemanticTokensWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return SemanticTokensWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// semantic tokens currently shown. It should be used with absolute care and
  /// is useful for situation where a server for example detect a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('refreshSupport');
      try {
        final refreshSupport = obj['refreshSupport'];
        if (refreshSupport != null && refreshSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensWorkspaceClientCapabilities &&
        other.runtimeType == SemanticTokensWorkspaceClientCapabilities) {
      return refreshSupport == other.refreshSupport && true;
    }
    return false;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ServerCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ServerCapabilities.canParse,
    ServerCapabilities.fromJson,
  );

  ServerCapabilities({
    this.callHierarchyProvider,
    this.codeActionProvider,
    this.codeLensProvider,
    this.colorProvider,
    this.completionProvider,
    this.declarationProvider,
    this.definitionProvider,
    this.diagnosticProvider,
    this.documentFormattingProvider,
    this.documentHighlightProvider,
    this.documentLinkProvider,
    this.documentOnTypeFormattingProvider,
    this.documentRangeFormattingProvider,
    this.documentSymbolProvider,
    this.executeCommandProvider,
    this.experimental,
    this.foldingRangeProvider,
    this.hoverProvider,
    this.implementationProvider,
    this.inlayHintProvider,
    this.inlineValueProvider,
    this.linkedEditingRangeProvider,
    this.monikerProvider,
    this.notebookDocumentSync,
    this.positionEncoding,
    this.referencesProvider,
    this.renameProvider,
    this.selectionRangeProvider,
    this.semanticTokensProvider,
    this.signatureHelpProvider,
    this.textDocumentSync,
    this.typeDefinitionProvider,
    this.typeHierarchyProvider,
    this.workspace,
    this.workspaceSymbolProvider,
  });
  static ServerCapabilities fromJson(Map<String, Object?> json) {
    final callHierarchyProviderJson = json['callHierarchyProvider'];
    final callHierarchyProvider = callHierarchyProviderJson == null
        ? null
        : (callHierarchyProviderJson is bool
            ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t1(
                callHierarchyProviderJson)
            : (CallHierarchyOptions.canParse(
                    callHierarchyProviderJson, nullLspJsonReporter)
                ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t2(
                    CallHierarchyOptions.fromJson(
                        callHierarchyProviderJson as Map<String, Object?>))
                : (CallHierarchyRegistrationOptions.canParse(
                        callHierarchyProviderJson, nullLspJsonReporter)
                    ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t3(
                        CallHierarchyRegistrationOptions.fromJson(
                            callHierarchyProviderJson as Map<String, Object?>))
                    : (throw '''$callHierarchyProviderJson was not one of (bool, CallHierarchyOptions, CallHierarchyRegistrationOptions)'''))));
    final codeActionProviderJson = json['codeActionProvider'];
    final codeActionProvider = codeActionProviderJson == null
        ? null
        : (codeActionProviderJson is bool
            ? Either2<bool, CodeActionOptions>.t1(codeActionProviderJson)
            : (CodeActionOptions.canParse(
                    codeActionProviderJson, nullLspJsonReporter)
                ? Either2<bool, CodeActionOptions>.t2(
                    CodeActionOptions.fromJson(
                        codeActionProviderJson as Map<String, Object?>))
                : (throw '''$codeActionProviderJson was not one of (bool, CodeActionOptions)''')));
    final codeLensProviderJson = json['codeLensProvider'];
    final codeLensProvider = codeLensProviderJson != null
        ? CodeLensOptions.fromJson(codeLensProviderJson as Map<String, Object?>)
        : null;
    final colorProviderJson = json['colorProvider'];
    final colorProvider = colorProviderJson == null
        ? null
        : (colorProviderJson is bool
            ? Either3<bool, DocumentColorOptions,
                DocumentColorRegistrationOptions>.t1(colorProviderJson)
            : (DocumentColorOptions.canParse(colorProviderJson, nullLspJsonReporter)
                ? Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>.t2(
                    DocumentColorOptions.fromJson(
                        colorProviderJson as Map<String, Object?>))
                : (DocumentColorRegistrationOptions.canParse(
                        colorProviderJson, nullLspJsonReporter)
                    ? Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>.t3(
                        DocumentColorRegistrationOptions.fromJson(
                            colorProviderJson as Map<String, Object?>))
                    : (throw '''$colorProviderJson was not one of (bool, DocumentColorOptions, DocumentColorRegistrationOptions)'''))));
    final completionProviderJson = json['completionProvider'];
    final completionProvider = completionProviderJson != null
        ? CompletionOptions.fromJson(
            completionProviderJson as Map<String, Object?>)
        : null;
    final declarationProviderJson = json['declarationProvider'];
    final declarationProvider = declarationProviderJson == null
        ? null
        : (declarationProviderJson is bool
            ? Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>.t1(
                declarationProviderJson)
            : (DeclarationOptions.canParse(
                    declarationProviderJson, nullLspJsonReporter)
                ? Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>.t2(
                    DeclarationOptions.fromJson(
                        declarationProviderJson as Map<String, Object?>))
                : (DeclarationRegistrationOptions.canParse(
                        declarationProviderJson, nullLspJsonReporter)
                    ? Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>.t3(
                        DeclarationRegistrationOptions.fromJson(
                            declarationProviderJson as Map<String, Object?>))
                    : (throw '''$declarationProviderJson was not one of (bool, DeclarationOptions, DeclarationRegistrationOptions)'''))));
    final definitionProviderJson = json['definitionProvider'];
    final definitionProvider = definitionProviderJson == null
        ? null
        : (definitionProviderJson is bool
            ? Either2<bool, DefinitionOptions>.t1(definitionProviderJson)
            : (DefinitionOptions.canParse(
                    definitionProviderJson, nullLspJsonReporter)
                ? Either2<bool, DefinitionOptions>.t2(
                    DefinitionOptions.fromJson(
                        definitionProviderJson as Map<String, Object?>))
                : (throw '''$definitionProviderJson was not one of (bool, DefinitionOptions)''')));
    final diagnosticProviderJson = json['diagnosticProvider'];
    final diagnosticProvider = diagnosticProviderJson == null
        ? null
        : (DiagnosticOptions.canParse(
                diagnosticProviderJson, nullLspJsonReporter)
            ? Either2<DiagnosticOptions, DiagnosticRegistrationOptions>.t1(
                DiagnosticOptions.fromJson(
                    diagnosticProviderJson as Map<String, Object?>))
            : (DiagnosticRegistrationOptions.canParse(
                    diagnosticProviderJson, nullLspJsonReporter)
                ? Either2<DiagnosticOptions, DiagnosticRegistrationOptions>.t2(
                    DiagnosticRegistrationOptions.fromJson(
                        diagnosticProviderJson as Map<String, Object?>))
                : (throw '''$diagnosticProviderJson was not one of (DiagnosticOptions, DiagnosticRegistrationOptions)''')));
    final documentFormattingProviderJson = json['documentFormattingProvider'];
    final documentFormattingProvider = documentFormattingProviderJson == null
        ? null
        : (documentFormattingProviderJson is bool
            ? Either2<bool, DocumentFormattingOptions>.t1(
                documentFormattingProviderJson)
            : (DocumentFormattingOptions.canParse(
                    documentFormattingProviderJson, nullLspJsonReporter)
                ? Either2<bool, DocumentFormattingOptions>.t2(
                    DocumentFormattingOptions.fromJson(
                        documentFormattingProviderJson as Map<String, Object?>))
                : (throw '''$documentFormattingProviderJson was not one of (bool, DocumentFormattingOptions)''')));
    final documentHighlightProviderJson = json['documentHighlightProvider'];
    final documentHighlightProvider = documentHighlightProviderJson == null
        ? null
        : (documentHighlightProviderJson is bool
            ? Either2<bool, DocumentHighlightOptions>.t1(
                documentHighlightProviderJson)
            : (DocumentHighlightOptions.canParse(
                    documentHighlightProviderJson, nullLspJsonReporter)
                ? Either2<bool, DocumentHighlightOptions>.t2(
                    DocumentHighlightOptions.fromJson(
                        documentHighlightProviderJson as Map<String, Object?>))
                : (throw '''$documentHighlightProviderJson was not one of (bool, DocumentHighlightOptions)''')));
    final documentLinkProviderJson = json['documentLinkProvider'];
    final documentLinkProvider = documentLinkProviderJson != null
        ? DocumentLinkOptions.fromJson(
            documentLinkProviderJson as Map<String, Object?>)
        : null;
    final documentOnTypeFormattingProviderJson =
        json['documentOnTypeFormattingProvider'];
    final documentOnTypeFormattingProvider =
        documentOnTypeFormattingProviderJson != null
            ? DocumentOnTypeFormattingOptions.fromJson(
                documentOnTypeFormattingProviderJson as Map<String, Object?>)
            : null;
    final documentRangeFormattingProviderJson =
        json['documentRangeFormattingProvider'];
    final documentRangeFormattingProvider = documentRangeFormattingProviderJson ==
            null
        ? null
        : (documentRangeFormattingProviderJson is bool
            ? Either2<bool, DocumentRangeFormattingOptions>.t1(
                documentRangeFormattingProviderJson)
            : (DocumentRangeFormattingOptions.canParse(
                    documentRangeFormattingProviderJson, nullLspJsonReporter)
                ? Either2<bool, DocumentRangeFormattingOptions>.t2(
                    DocumentRangeFormattingOptions.fromJson(
                        documentRangeFormattingProviderJson
                            as Map<String, Object?>))
                : (throw '''$documentRangeFormattingProviderJson was not one of (bool, DocumentRangeFormattingOptions)''')));
    final documentSymbolProviderJson = json['documentSymbolProvider'];
    final documentSymbolProvider = documentSymbolProviderJson == null
        ? null
        : (documentSymbolProviderJson is bool
            ? Either2<bool, DocumentSymbolOptions>.t1(
                documentSymbolProviderJson)
            : (DocumentSymbolOptions.canParse(
                    documentSymbolProviderJson, nullLspJsonReporter)
                ? Either2<bool, DocumentSymbolOptions>.t2(
                    DocumentSymbolOptions.fromJson(
                        documentSymbolProviderJson as Map<String, Object?>))
                : (throw '''$documentSymbolProviderJson was not one of (bool, DocumentSymbolOptions)''')));
    final executeCommandProviderJson = json['executeCommandProvider'];
    final executeCommandProvider = executeCommandProviderJson != null
        ? ExecuteCommandOptions.fromJson(
            executeCommandProviderJson as Map<String, Object?>)
        : null;
    final experimentalJson = json['experimental'];
    final experimental = experimentalJson;
    final foldingRangeProviderJson = json['foldingRangeProvider'];
    final foldingRangeProvider = foldingRangeProviderJson == null
        ? null
        : (foldingRangeProviderJson is bool
            ? Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>.t1(
                foldingRangeProviderJson)
            : (FoldingRangeOptions.canParse(
                    foldingRangeProviderJson, nullLspJsonReporter)
                ? Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>.t2(
                    FoldingRangeOptions.fromJson(
                        foldingRangeProviderJson as Map<String, Object?>))
                : (FoldingRangeRegistrationOptions.canParse(
                        foldingRangeProviderJson, nullLspJsonReporter)
                    ? Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>.t3(
                        FoldingRangeRegistrationOptions.fromJson(
                            foldingRangeProviderJson as Map<String, Object?>))
                    : (throw '''$foldingRangeProviderJson was not one of (bool, FoldingRangeOptions, FoldingRangeRegistrationOptions)'''))));
    final hoverProviderJson = json['hoverProvider'];
    final hoverProvider = hoverProviderJson == null
        ? null
        : (hoverProviderJson is bool
            ? Either2<bool, HoverOptions>.t1(hoverProviderJson)
            : (HoverOptions.canParse(hoverProviderJson, nullLspJsonReporter)
                ? Either2<bool, HoverOptions>.t2(HoverOptions.fromJson(
                    hoverProviderJson as Map<String, Object?>))
                : (throw '''$hoverProviderJson was not one of (bool, HoverOptions)''')));
    final implementationProviderJson = json['implementationProvider'];
    final implementationProvider = implementationProviderJson == null
        ? null
        : (implementationProviderJson is bool
            ? Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>.t1(
                implementationProviderJson)
            : (ImplementationOptions.canParse(
                    implementationProviderJson, nullLspJsonReporter)
                ? Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>.t2(
                    ImplementationOptions.fromJson(
                        implementationProviderJson as Map<String, Object?>))
                : (ImplementationRegistrationOptions.canParse(
                        implementationProviderJson, nullLspJsonReporter)
                    ? Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>.t3(
                        ImplementationRegistrationOptions.fromJson(
                            implementationProviderJson as Map<String, Object?>))
                    : (throw '''$implementationProviderJson was not one of (bool, ImplementationOptions, ImplementationRegistrationOptions)'''))));
    final inlayHintProviderJson = json['inlayHintProvider'];
    final inlayHintProvider = inlayHintProviderJson == null
        ? null
        : (inlayHintProviderJson is bool
            ? Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>.t1(
                inlayHintProviderJson)
            : (InlayHintOptions.canParse(
                    inlayHintProviderJson, nullLspJsonReporter)
                ? Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>.t2(
                    InlayHintOptions.fromJson(
                        inlayHintProviderJson as Map<String, Object?>))
                : (InlayHintRegistrationOptions.canParse(
                        inlayHintProviderJson, nullLspJsonReporter)
                    ? Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>.t3(
                        InlayHintRegistrationOptions.fromJson(
                            inlayHintProviderJson as Map<String, Object?>))
                    : (throw '''$inlayHintProviderJson was not one of (bool, InlayHintOptions, InlayHintRegistrationOptions)'''))));
    final inlineValueProviderJson = json['inlineValueProvider'];
    final inlineValueProvider = inlineValueProviderJson == null
        ? null
        : (inlineValueProviderJson is bool
            ? Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>.t1(
                inlineValueProviderJson)
            : (InlineValueOptions.canParse(
                    inlineValueProviderJson, nullLspJsonReporter)
                ? Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>.t2(
                    InlineValueOptions.fromJson(
                        inlineValueProviderJson as Map<String, Object?>))
                : (InlineValueRegistrationOptions.canParse(
                        inlineValueProviderJson, nullLspJsonReporter)
                    ? Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>.t3(
                        InlineValueRegistrationOptions.fromJson(
                            inlineValueProviderJson as Map<String, Object?>))
                    : (throw '''$inlineValueProviderJson was not one of (bool, InlineValueOptions, InlineValueRegistrationOptions)'''))));
    final linkedEditingRangeProviderJson = json['linkedEditingRangeProvider'];
    final linkedEditingRangeProvider = linkedEditingRangeProviderJson == null
        ? null
        : (linkedEditingRangeProviderJson is bool
            ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t1(
                linkedEditingRangeProviderJson)
            : (LinkedEditingRangeOptions.canParse(
                    linkedEditingRangeProviderJson, nullLspJsonReporter)
                ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t2(
                    LinkedEditingRangeOptions.fromJson(
                        linkedEditingRangeProviderJson as Map<String, Object?>))
                : (LinkedEditingRangeRegistrationOptions.canParse(
                        linkedEditingRangeProviderJson, nullLspJsonReporter)
                    ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t3(
                        LinkedEditingRangeRegistrationOptions.fromJson(
                            linkedEditingRangeProviderJson as Map<String, Object?>))
                    : (throw '''$linkedEditingRangeProviderJson was not one of (bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions)'''))));
    final monikerProviderJson = json['monikerProvider'];
    final monikerProvider = monikerProviderJson == null
        ? null
        : (monikerProviderJson is bool
            ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t1(
                monikerProviderJson)
            : (MonikerOptions.canParse(monikerProviderJson, nullLspJsonReporter)
                ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t2(
                    MonikerOptions.fromJson(
                        monikerProviderJson as Map<String, Object?>))
                : (MonikerRegistrationOptions.canParse(
                        monikerProviderJson, nullLspJsonReporter)
                    ? Either3<bool, MonikerOptions,
                            MonikerRegistrationOptions>.t3(
                        MonikerRegistrationOptions.fromJson(
                            monikerProviderJson as Map<String, Object?>))
                    : (throw '''$monikerProviderJson was not one of (bool, MonikerOptions, MonikerRegistrationOptions)'''))));
    final notebookDocumentSyncJson = json['notebookDocumentSync'];
    final notebookDocumentSync = notebookDocumentSyncJson == null
        ? null
        : (NotebookDocumentSyncOptions.canParse(notebookDocumentSyncJson, nullLspJsonReporter)
            ? Either2<NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions>.t1(
                NotebookDocumentSyncOptions.fromJson(
                    notebookDocumentSyncJson as Map<String, Object?>))
            : (NotebookDocumentSyncRegistrationOptions.canParse(
                    notebookDocumentSyncJson, nullLspJsonReporter)
                ? Either2<NotebookDocumentSyncOptions,
                        NotebookDocumentSyncRegistrationOptions>.t2(
                    NotebookDocumentSyncRegistrationOptions.fromJson(
                        notebookDocumentSyncJson as Map<String, Object?>))
                : (throw '''$notebookDocumentSyncJson was not one of (NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions)''')));
    final positionEncodingJson = json['positionEncoding'];
    final positionEncoding = positionEncodingJson != null
        ? PositionEncodingKind.fromJson(positionEncodingJson as String)
        : null;
    final referencesProviderJson = json['referencesProvider'];
    final referencesProvider = referencesProviderJson == null
        ? null
        : (referencesProviderJson is bool
            ? Either2<bool, ReferenceOptions>.t1(referencesProviderJson)
            : (ReferenceOptions.canParse(
                    referencesProviderJson, nullLspJsonReporter)
                ? Either2<bool, ReferenceOptions>.t2(ReferenceOptions.fromJson(
                    referencesProviderJson as Map<String, Object?>))
                : (throw '''$referencesProviderJson was not one of (bool, ReferenceOptions)''')));
    final renameProviderJson = json['renameProvider'];
    final renameProvider = renameProviderJson == null
        ? null
        : (renameProviderJson is bool
            ? Either2<bool, RenameOptions>.t1(renameProviderJson)
            : (RenameOptions.canParse(renameProviderJson, nullLspJsonReporter)
                ? Either2<bool, RenameOptions>.t2(RenameOptions.fromJson(
                    renameProviderJson as Map<String, Object?>))
                : (throw '''$renameProviderJson was not one of (bool, RenameOptions)''')));
    final selectionRangeProviderJson = json['selectionRangeProvider'];
    final selectionRangeProvider = selectionRangeProviderJson == null
        ? null
        : (selectionRangeProviderJson is bool
            ? Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>.t1(
                selectionRangeProviderJson)
            : (SelectionRangeOptions.canParse(
                    selectionRangeProviderJson, nullLspJsonReporter)
                ? Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>.t2(
                    SelectionRangeOptions.fromJson(
                        selectionRangeProviderJson as Map<String, Object?>))
                : (SelectionRangeRegistrationOptions.canParse(
                        selectionRangeProviderJson, nullLspJsonReporter)
                    ? Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>.t3(
                        SelectionRangeRegistrationOptions.fromJson(
                            selectionRangeProviderJson as Map<String, Object?>))
                    : (throw '''$selectionRangeProviderJson was not one of (bool, SelectionRangeOptions, SelectionRangeRegistrationOptions)'''))));
    final semanticTokensProviderJson = json['semanticTokensProvider'];
    final semanticTokensProvider = semanticTokensProviderJson == null
        ? null
        : (SemanticTokensOptions.canParse(
                semanticTokensProviderJson, nullLspJsonReporter)
            ? Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>.t1(
                SemanticTokensOptions.fromJson(
                    semanticTokensProviderJson as Map<String, Object?>))
            : (SemanticTokensRegistrationOptions.canParse(
                    semanticTokensProviderJson, nullLspJsonReporter)
                ? Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>.t2(
                    SemanticTokensRegistrationOptions.fromJson(
                        semanticTokensProviderJson as Map<String, Object?>))
                : (throw '''$semanticTokensProviderJson was not one of (SemanticTokensOptions, SemanticTokensRegistrationOptions)''')));
    final signatureHelpProviderJson = json['signatureHelpProvider'];
    final signatureHelpProvider = signatureHelpProviderJson != null
        ? SignatureHelpOptions.fromJson(
            signatureHelpProviderJson as Map<String, Object?>)
        : null;
    final textDocumentSyncJson = json['textDocumentSync'];
    final textDocumentSync = textDocumentSyncJson == null
        ? null
        : (TextDocumentSyncKind.canParse(
                textDocumentSyncJson, nullLspJsonReporter)
            ? Either2<TextDocumentSyncKind, TextDocumentSyncOptions>.t1(
                TextDocumentSyncKind.fromJson(textDocumentSyncJson as int))
            : (TextDocumentSyncOptions.canParse(
                    textDocumentSyncJson, nullLspJsonReporter)
                ? Either2<TextDocumentSyncKind, TextDocumentSyncOptions>.t2(
                    TextDocumentSyncOptions.fromJson(
                        textDocumentSyncJson as Map<String, Object?>))
                : (throw '''$textDocumentSyncJson was not one of (TextDocumentSyncKind, TextDocumentSyncOptions)''')));
    final typeDefinitionProviderJson = json['typeDefinitionProvider'];
    final typeDefinitionProvider = typeDefinitionProviderJson == null
        ? null
        : (typeDefinitionProviderJson is bool
            ? Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>.t1(
                typeDefinitionProviderJson)
            : (TypeDefinitionOptions.canParse(
                    typeDefinitionProviderJson, nullLspJsonReporter)
                ? Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>.t2(
                    TypeDefinitionOptions.fromJson(
                        typeDefinitionProviderJson as Map<String, Object?>))
                : (TypeDefinitionRegistrationOptions.canParse(
                        typeDefinitionProviderJson, nullLspJsonReporter)
                    ? Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>.t3(
                        TypeDefinitionRegistrationOptions.fromJson(
                            typeDefinitionProviderJson as Map<String, Object?>))
                    : (throw '''$typeDefinitionProviderJson was not one of (bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions)'''))));
    final typeHierarchyProviderJson = json['typeHierarchyProvider'];
    final typeHierarchyProvider = typeHierarchyProviderJson == null
        ? null
        : (typeHierarchyProviderJson is bool
            ? Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>.t1(
                typeHierarchyProviderJson)
            : (TypeHierarchyOptions.canParse(
                    typeHierarchyProviderJson, nullLspJsonReporter)
                ? Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>.t2(
                    TypeHierarchyOptions.fromJson(
                        typeHierarchyProviderJson as Map<String, Object?>))
                : (TypeHierarchyRegistrationOptions.canParse(
                        typeHierarchyProviderJson, nullLspJsonReporter)
                    ? Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>.t3(
                        TypeHierarchyRegistrationOptions.fromJson(
                            typeHierarchyProviderJson as Map<String, Object?>))
                    : (throw '''$typeHierarchyProviderJson was not one of (bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions)'''))));
    final workspaceJson = json['workspace'];
    final workspace = workspaceJson != null
        ? ServerCapabilitiesWorkspace.fromJson(
            workspaceJson as Map<String, Object?>)
        : null;
    final workspaceSymbolProviderJson = json['workspaceSymbolProvider'];
    final workspaceSymbolProvider = workspaceSymbolProviderJson == null
        ? null
        : (workspaceSymbolProviderJson is bool
            ? Either2<bool, WorkspaceSymbolOptions>.t1(
                workspaceSymbolProviderJson)
            : (WorkspaceSymbolOptions.canParse(
                    workspaceSymbolProviderJson, nullLspJsonReporter)
                ? Either2<bool, WorkspaceSymbolOptions>.t2(
                    WorkspaceSymbolOptions.fromJson(
                        workspaceSymbolProviderJson as Map<String, Object?>))
                : (throw '''$workspaceSymbolProviderJson was not one of (bool, WorkspaceSymbolOptions)''')));
    return ServerCapabilities(
      callHierarchyProvider: callHierarchyProvider,
      codeActionProvider: codeActionProvider,
      codeLensProvider: codeLensProvider,
      colorProvider: colorProvider,
      completionProvider: completionProvider,
      declarationProvider: declarationProvider,
      definitionProvider: definitionProvider,
      diagnosticProvider: diagnosticProvider,
      documentFormattingProvider: documentFormattingProvider,
      documentHighlightProvider: documentHighlightProvider,
      documentLinkProvider: documentLinkProvider,
      documentOnTypeFormattingProvider: documentOnTypeFormattingProvider,
      documentRangeFormattingProvider: documentRangeFormattingProvider,
      documentSymbolProvider: documentSymbolProvider,
      executeCommandProvider: executeCommandProvider,
      experimental: experimental,
      foldingRangeProvider: foldingRangeProvider,
      hoverProvider: hoverProvider,
      implementationProvider: implementationProvider,
      inlayHintProvider: inlayHintProvider,
      inlineValueProvider: inlineValueProvider,
      linkedEditingRangeProvider: linkedEditingRangeProvider,
      monikerProvider: monikerProvider,
      notebookDocumentSync: notebookDocumentSync,
      positionEncoding: positionEncoding,
      referencesProvider: referencesProvider,
      renameProvider: renameProvider,
      selectionRangeProvider: selectionRangeProvider,
      semanticTokensProvider: semanticTokensProvider,
      signatureHelpProvider: signatureHelpProvider,
      textDocumentSync: textDocumentSync,
      typeDefinitionProvider: typeDefinitionProvider,
      typeHierarchyProvider: typeHierarchyProvider,
      workspace: workspace,
      workspaceSymbolProvider: workspaceSymbolProvider,
    );
  }

  /// The server provides call hierarchy support.
  ///  @since 3.16.0
  final Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>?
      callHierarchyProvider;

  /// The server provides code actions. The `CodeActionOptions` return type is
  /// only valid if the client signals code action literal support via the
  /// property `textDocument.codeAction.codeActionLiteralSupport`.
  final Either2<bool, CodeActionOptions>? codeActionProvider;

  /// The server provides code lens.
  final CodeLensOptions? codeLensProvider;

  /// The server provides color provider support.
  ///  @since 3.6.0
  final Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>?
      colorProvider;

  /// The server provides completion support.
  final CompletionOptions? completionProvider;

  /// The server provides go to declaration support.
  ///  @since 3.14.0
  final Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>?
      declarationProvider;

  /// The server provides goto definition support.
  final Either2<bool, DefinitionOptions>? definitionProvider;

  /// The server has support for pull model diagnostics.
  ///  @since 3.17.0
  final Either2<DiagnosticOptions, DiagnosticRegistrationOptions>?
      diagnosticProvider;

  /// The server provides document formatting.
  final Either2<bool, DocumentFormattingOptions>? documentFormattingProvider;

  /// The server provides document highlight support.
  final Either2<bool, DocumentHighlightOptions>? documentHighlightProvider;

  /// The server provides document link support.
  final DocumentLinkOptions? documentLinkProvider;

  /// The server provides document formatting on typing.
  final DocumentOnTypeFormattingOptions? documentOnTypeFormattingProvider;

  /// The server provides document range formatting.
  final Either2<bool, DocumentRangeFormattingOptions>?
      documentRangeFormattingProvider;

  /// The server provides document symbol support.
  final Either2<bool, DocumentSymbolOptions>? documentSymbolProvider;

  /// The server provides execute command support.
  final ExecuteCommandOptions? executeCommandProvider;

  /// Experimental server capabilities.
  final Object? experimental;

  /// The server provides folding provider support.
  ///  @since 3.10.0
  final Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>?
      foldingRangeProvider;

  /// The server provides hover support.
  final Either2<bool, HoverOptions>? hoverProvider;

  /// The server provides goto implementation support.
  ///  @since 3.6.0
  final Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>?
      implementationProvider;

  /// The server provides inlay hints.
  ///  @since 3.17.0
  final Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>?
      inlayHintProvider;

  /// The server provides inline values.
  ///  @since 3.17.0
  final Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>?
      inlineValueProvider;

  /// The server provides linked editing range support.
  ///  @since 3.16.0
  final Either3<bool, LinkedEditingRangeOptions,
      LinkedEditingRangeRegistrationOptions>? linkedEditingRangeProvider;

  /// Whether server provides moniker support.
  ///  @since 3.16.0
  final Either3<bool, MonikerOptions, MonikerRegistrationOptions>?
      monikerProvider;

  /// Defines how notebook documents are synced.
  ///  @since 3.17.0
  final Either2<NotebookDocumentSyncOptions,
      NotebookDocumentSyncRegistrationOptions>? notebookDocumentSync;

  /// The position encoding the server picked from the encodings offered by the
  /// client via the client capability `general.positionEncodings`.
  ///
  /// If the client didn't provide any position encodings the only valid value
  /// that a server can return is 'utf-16'.
  ///
  /// If omitted it defaults to 'utf-16'.
  ///  @since 3.17.0
  final PositionEncodingKind? positionEncoding;

  /// The server provides find references support.
  final Either2<bool, ReferenceOptions>? referencesProvider;

  /// The server provides rename support. RenameOptions may only be specified if
  /// the client states that it supports `prepareSupport` in its initial
  /// `initialize` request.
  final Either2<bool, RenameOptions>? renameProvider;

  /// The server provides selection range support.
  ///  @since 3.15.0
  final Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>?
      selectionRangeProvider;

  /// The server provides semantic tokens support.
  ///  @since 3.16.0
  final Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>?
      semanticTokensProvider;

  /// The server provides signature help support.
  final SignatureHelpOptions? signatureHelpProvider;

  /// Defines how text documents are synced. Is either a detailed structure
  /// defining each notification or for backwards compatibility the
  /// TextDocumentSyncKind number. If omitted it defaults to
  /// `TextDocumentSyncKind.None`.
  final Either2<TextDocumentSyncKind, TextDocumentSyncOptions>?
      textDocumentSync;

  /// The server provides goto type definition support.
  ///  @since 3.6.0
  final Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>?
      typeDefinitionProvider;

  /// The server provides type hierarchy support.
  ///  @since 3.17.0
  final Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>?
      typeHierarchyProvider;

  /// Workspace specific server capabilities
  final ServerCapabilitiesWorkspace? workspace;

  /// The server provides workspace symbol support.
  final Either2<bool, WorkspaceSymbolOptions>? workspaceSymbolProvider;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (callHierarchyProvider != null) {
      result['callHierarchyProvider'] = callHierarchyProvider;
    }
    if (codeActionProvider != null) {
      result['codeActionProvider'] = codeActionProvider;
    }
    if (codeLensProvider != null) {
      result['codeLensProvider'] = codeLensProvider?.toJson();
    }
    if (colorProvider != null) {
      result['colorProvider'] = colorProvider;
    }
    if (completionProvider != null) {
      result['completionProvider'] = completionProvider?.toJson();
    }
    if (declarationProvider != null) {
      result['declarationProvider'] = declarationProvider;
    }
    if (definitionProvider != null) {
      result['definitionProvider'] = definitionProvider;
    }
    if (diagnosticProvider != null) {
      result['diagnosticProvider'] = diagnosticProvider;
    }
    if (documentFormattingProvider != null) {
      result['documentFormattingProvider'] = documentFormattingProvider;
    }
    if (documentHighlightProvider != null) {
      result['documentHighlightProvider'] = documentHighlightProvider;
    }
    if (documentLinkProvider != null) {
      result['documentLinkProvider'] = documentLinkProvider?.toJson();
    }
    if (documentOnTypeFormattingProvider != null) {
      result['documentOnTypeFormattingProvider'] =
          documentOnTypeFormattingProvider?.toJson();
    }
    if (documentRangeFormattingProvider != null) {
      result['documentRangeFormattingProvider'] =
          documentRangeFormattingProvider;
    }
    if (documentSymbolProvider != null) {
      result['documentSymbolProvider'] = documentSymbolProvider;
    }
    if (executeCommandProvider != null) {
      result['executeCommandProvider'] = executeCommandProvider?.toJson();
    }
    if (experimental != null) {
      result['experimental'] = experimental;
    }
    if (foldingRangeProvider != null) {
      result['foldingRangeProvider'] = foldingRangeProvider;
    }
    if (hoverProvider != null) {
      result['hoverProvider'] = hoverProvider;
    }
    if (implementationProvider != null) {
      result['implementationProvider'] = implementationProvider;
    }
    if (inlayHintProvider != null) {
      result['inlayHintProvider'] = inlayHintProvider;
    }
    if (inlineValueProvider != null) {
      result['inlineValueProvider'] = inlineValueProvider;
    }
    if (linkedEditingRangeProvider != null) {
      result['linkedEditingRangeProvider'] = linkedEditingRangeProvider;
    }
    if (monikerProvider != null) {
      result['monikerProvider'] = monikerProvider;
    }
    if (notebookDocumentSync != null) {
      result['notebookDocumentSync'] = notebookDocumentSync;
    }
    if (positionEncoding != null) {
      result['positionEncoding'] = positionEncoding?.toJson();
    }
    if (referencesProvider != null) {
      result['referencesProvider'] = referencesProvider;
    }
    if (renameProvider != null) {
      result['renameProvider'] = renameProvider;
    }
    if (selectionRangeProvider != null) {
      result['selectionRangeProvider'] = selectionRangeProvider;
    }
    if (semanticTokensProvider != null) {
      result['semanticTokensProvider'] = semanticTokensProvider;
    }
    if (signatureHelpProvider != null) {
      result['signatureHelpProvider'] = signatureHelpProvider?.toJson();
    }
    if (textDocumentSync != null) {
      result['textDocumentSync'] = textDocumentSync;
    }
    if (typeDefinitionProvider != null) {
      result['typeDefinitionProvider'] = typeDefinitionProvider;
    }
    if (typeHierarchyProvider != null) {
      result['typeHierarchyProvider'] = typeHierarchyProvider;
    }
    if (workspace != null) {
      result['workspace'] = workspace?.toJson();
    }
    if (workspaceSymbolProvider != null) {
      result['workspaceSymbolProvider'] = workspaceSymbolProvider;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('callHierarchyProvider');
      try {
        final callHierarchyProvider = obj['callHierarchyProvider'];
        if (callHierarchyProvider != null &&
            callHierarchyProvider is! bool &&
            !CallHierarchyOptions.canParse(callHierarchyProvider, reporter) &&
            !CallHierarchyRegistrationOptions.canParse(
                callHierarchyProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeActionProvider');
      try {
        final codeActionProvider = obj['codeActionProvider'];
        if (codeActionProvider != null &&
            codeActionProvider is! bool &&
            !CodeActionOptions.canParse(codeActionProvider, reporter)) {
          reporter
              .reportError('must be of type Either2<bool, CodeActionOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeLensProvider');
      try {
        final codeLensProvider = obj['codeLensProvider'];
        if (codeLensProvider != null &&
            !CodeLensOptions.canParse(codeLensProvider, reporter)) {
          reporter.reportError('must be of type CodeLensOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('colorProvider');
      try {
        final colorProvider = obj['colorProvider'];
        if (colorProvider != null &&
            colorProvider is! bool &&
            !DocumentColorOptions.canParse(colorProvider, reporter) &&
            !DocumentColorRegistrationOptions.canParse(
                colorProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completionProvider');
      try {
        final completionProvider = obj['completionProvider'];
        if (completionProvider != null &&
            !CompletionOptions.canParse(completionProvider, reporter)) {
          reporter.reportError('must be of type CompletionOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('declarationProvider');
      try {
        final declarationProvider = obj['declarationProvider'];
        if (declarationProvider != null &&
            declarationProvider is! bool &&
            !DeclarationOptions.canParse(declarationProvider, reporter) &&
            !DeclarationRegistrationOptions.canParse(
                declarationProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('definitionProvider');
      try {
        final definitionProvider = obj['definitionProvider'];
        if (definitionProvider != null &&
            definitionProvider is! bool &&
            !DefinitionOptions.canParse(definitionProvider, reporter)) {
          reporter
              .reportError('must be of type Either2<bool, DefinitionOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('diagnosticProvider');
      try {
        final diagnosticProvider = obj['diagnosticProvider'];
        if (diagnosticProvider != null &&
            !DiagnosticOptions.canParse(diagnosticProvider, reporter) &&
            !DiagnosticRegistrationOptions.canParse(
                diagnosticProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<DiagnosticOptions, DiagnosticRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentFormattingProvider');
      try {
        final documentFormattingProvider = obj['documentFormattingProvider'];
        if (documentFormattingProvider != null &&
            documentFormattingProvider is! bool &&
            !DocumentFormattingOptions.canParse(
                documentFormattingProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentFormattingOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentHighlightProvider');
      try {
        final documentHighlightProvider = obj['documentHighlightProvider'];
        if (documentHighlightProvider != null &&
            documentHighlightProvider is! bool &&
            !DocumentHighlightOptions.canParse(
                documentHighlightProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentHighlightOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentLinkProvider');
      try {
        final documentLinkProvider = obj['documentLinkProvider'];
        if (documentLinkProvider != null &&
            !DocumentLinkOptions.canParse(documentLinkProvider, reporter)) {
          reporter.reportError('must be of type DocumentLinkOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentOnTypeFormattingProvider');
      try {
        final documentOnTypeFormattingProvider =
            obj['documentOnTypeFormattingProvider'];
        if (documentOnTypeFormattingProvider != null &&
            !DocumentOnTypeFormattingOptions.canParse(
                documentOnTypeFormattingProvider, reporter)) {
          reporter
              .reportError('must be of type DocumentOnTypeFormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentRangeFormattingProvider');
      try {
        final documentRangeFormattingProvider =
            obj['documentRangeFormattingProvider'];
        if (documentRangeFormattingProvider != null &&
            documentRangeFormattingProvider is! bool &&
            !DocumentRangeFormattingOptions.canParse(
                documentRangeFormattingProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentRangeFormattingOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSymbolProvider');
      try {
        final documentSymbolProvider = obj['documentSymbolProvider'];
        if (documentSymbolProvider != null &&
            documentSymbolProvider is! bool &&
            !DocumentSymbolOptions.canParse(documentSymbolProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentSymbolOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executeCommandProvider');
      try {
        final executeCommandProvider = obj['executeCommandProvider'];
        if (executeCommandProvider != null &&
            !ExecuteCommandOptions.canParse(executeCommandProvider, reporter)) {
          reporter.reportError('must be of type ExecuteCommandOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRangeProvider');
      try {
        final foldingRangeProvider = obj['foldingRangeProvider'];
        if (foldingRangeProvider != null &&
            foldingRangeProvider is! bool &&
            !FoldingRangeOptions.canParse(foldingRangeProvider, reporter) &&
            !FoldingRangeRegistrationOptions.canParse(
                foldingRangeProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('hoverProvider');
      try {
        final hoverProvider = obj['hoverProvider'];
        if (hoverProvider != null &&
            hoverProvider is! bool &&
            !HoverOptions.canParse(hoverProvider, reporter)) {
          reporter.reportError('must be of type Either2<bool, HoverOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('implementationProvider');
      try {
        final implementationProvider = obj['implementationProvider'];
        if (implementationProvider != null &&
            implementationProvider is! bool &&
            !ImplementationOptions.canParse(implementationProvider, reporter) &&
            !ImplementationRegistrationOptions.canParse(
                implementationProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlayHintProvider');
      try {
        final inlayHintProvider = obj['inlayHintProvider'];
        if (inlayHintProvider != null &&
            inlayHintProvider is! bool &&
            !InlayHintOptions.canParse(inlayHintProvider, reporter) &&
            !InlayHintRegistrationOptions.canParse(
                inlayHintProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlineValueProvider');
      try {
        final inlineValueProvider = obj['inlineValueProvider'];
        if (inlineValueProvider != null &&
            inlineValueProvider is! bool &&
            !InlineValueOptions.canParse(inlineValueProvider, reporter) &&
            !InlineValueRegistrationOptions.canParse(
                inlineValueProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkedEditingRangeProvider');
      try {
        final linkedEditingRangeProvider = obj['linkedEditingRangeProvider'];
        if (linkedEditingRangeProvider != null &&
            linkedEditingRangeProvider is! bool &&
            !LinkedEditingRangeOptions.canParse(
                linkedEditingRangeProvider, reporter) &&
            !LinkedEditingRangeRegistrationOptions.canParse(
                linkedEditingRangeProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('monikerProvider');
      try {
        final monikerProvider = obj['monikerProvider'];
        if (monikerProvider != null &&
            monikerProvider is! bool &&
            !MonikerOptions.canParse(monikerProvider, reporter) &&
            !MonikerRegistrationOptions.canParse(monikerProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, MonikerOptions, MonikerRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('notebookDocumentSync');
      try {
        final notebookDocumentSync = obj['notebookDocumentSync'];
        if (notebookDocumentSync != null &&
            !NotebookDocumentSyncOptions.canParse(
                notebookDocumentSync, reporter) &&
            !NotebookDocumentSyncRegistrationOptions.canParse(
                notebookDocumentSync, reporter)) {
          reporter.reportError(
              'must be of type Either2<NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('positionEncoding');
      try {
        final positionEncoding = obj['positionEncoding'];
        if (positionEncoding != null &&
            !PositionEncodingKind.canParse(positionEncoding, reporter)) {
          reporter.reportError('must be of type PositionEncodingKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('referencesProvider');
      try {
        final referencesProvider = obj['referencesProvider'];
        if (referencesProvider != null &&
            referencesProvider is! bool &&
            !ReferenceOptions.canParse(referencesProvider, reporter)) {
          reporter
              .reportError('must be of type Either2<bool, ReferenceOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('renameProvider');
      try {
        final renameProvider = obj['renameProvider'];
        if (renameProvider != null &&
            renameProvider is! bool &&
            !RenameOptions.canParse(renameProvider, reporter)) {
          reporter.reportError('must be of type Either2<bool, RenameOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRangeProvider');
      try {
        final selectionRangeProvider = obj['selectionRangeProvider'];
        if (selectionRangeProvider != null &&
            selectionRangeProvider is! bool &&
            !SelectionRangeOptions.canParse(selectionRangeProvider, reporter) &&
            !SelectionRangeRegistrationOptions.canParse(
                selectionRangeProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('semanticTokensProvider');
      try {
        final semanticTokensProvider = obj['semanticTokensProvider'];
        if (semanticTokensProvider != null &&
            !SemanticTokensOptions.canParse(semanticTokensProvider, reporter) &&
            !SemanticTokensRegistrationOptions.canParse(
                semanticTokensProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatureHelpProvider');
      try {
        final signatureHelpProvider = obj['signatureHelpProvider'];
        if (signatureHelpProvider != null &&
            !SignatureHelpOptions.canParse(signatureHelpProvider, reporter)) {
          reporter.reportError('must be of type SignatureHelpOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocumentSync');
      try {
        final textDocumentSync = obj['textDocumentSync'];
        if (textDocumentSync != null &&
            !TextDocumentSyncKind.canParse(textDocumentSync, reporter) &&
            !TextDocumentSyncOptions.canParse(textDocumentSync, reporter)) {
          reporter.reportError(
              'must be of type Either2<TextDocumentSyncKind, TextDocumentSyncOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeDefinitionProvider');
      try {
        final typeDefinitionProvider = obj['typeDefinitionProvider'];
        if (typeDefinitionProvider != null &&
            typeDefinitionProvider is! bool &&
            !TypeDefinitionOptions.canParse(typeDefinitionProvider, reporter) &&
            !TypeDefinitionRegistrationOptions.canParse(
                typeDefinitionProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeHierarchyProvider');
      try {
        final typeHierarchyProvider = obj['typeHierarchyProvider'];
        if (typeHierarchyProvider != null &&
            typeHierarchyProvider is! bool &&
            !TypeHierarchyOptions.canParse(typeHierarchyProvider, reporter) &&
            !TypeHierarchyRegistrationOptions.canParse(
                typeHierarchyProvider, reporter)) {
          reporter.reportError(
              'must be of type Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspace');
      try {
        final workspace = obj['workspace'];
        if (workspace != null &&
            !ServerCapabilitiesWorkspace.canParse(workspace, reporter)) {
          reporter.reportError('must be of type ServerCapabilitiesWorkspace');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceSymbolProvider');
      try {
        final workspaceSymbolProvider = obj['workspaceSymbolProvider'];
        if (workspaceSymbolProvider != null &&
            workspaceSymbolProvider is! bool &&
            !WorkspaceSymbolOptions.canParse(
                workspaceSymbolProvider, reporter)) {
          reporter.reportError(
              'must be of type Either2<bool, WorkspaceSymbolOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ServerCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ServerCapabilities &&
        other.runtimeType == ServerCapabilities) {
      return callHierarchyProvider == other.callHierarchyProvider &&
          codeActionProvider == other.codeActionProvider &&
          codeLensProvider == other.codeLensProvider &&
          colorProvider == other.colorProvider &&
          completionProvider == other.completionProvider &&
          declarationProvider == other.declarationProvider &&
          definitionProvider == other.definitionProvider &&
          diagnosticProvider == other.diagnosticProvider &&
          documentFormattingProvider == other.documentFormattingProvider &&
          documentHighlightProvider == other.documentHighlightProvider &&
          documentLinkProvider == other.documentLinkProvider &&
          documentOnTypeFormattingProvider ==
              other.documentOnTypeFormattingProvider &&
          documentRangeFormattingProvider ==
              other.documentRangeFormattingProvider &&
          documentSymbolProvider == other.documentSymbolProvider &&
          executeCommandProvider == other.executeCommandProvider &&
          experimental == other.experimental &&
          foldingRangeProvider == other.foldingRangeProvider &&
          hoverProvider == other.hoverProvider &&
          implementationProvider == other.implementationProvider &&
          inlayHintProvider == other.inlayHintProvider &&
          inlineValueProvider == other.inlineValueProvider &&
          linkedEditingRangeProvider == other.linkedEditingRangeProvider &&
          monikerProvider == other.monikerProvider &&
          notebookDocumentSync == other.notebookDocumentSync &&
          positionEncoding == other.positionEncoding &&
          referencesProvider == other.referencesProvider &&
          renameProvider == other.renameProvider &&
          selectionRangeProvider == other.selectionRangeProvider &&
          semanticTokensProvider == other.semanticTokensProvider &&
          signatureHelpProvider == other.signatureHelpProvider &&
          textDocumentSync == other.textDocumentSync &&
          typeDefinitionProvider == other.typeDefinitionProvider &&
          typeHierarchyProvider == other.typeHierarchyProvider &&
          workspace == other.workspace &&
          workspaceSymbolProvider == other.workspaceSymbolProvider &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll([
        callHierarchyProvider,
        codeActionProvider,
        codeLensProvider,
        colorProvider,
        completionProvider,
        declarationProvider,
        definitionProvider,
        diagnosticProvider,
        documentFormattingProvider,
        documentHighlightProvider,
        documentLinkProvider,
        documentOnTypeFormattingProvider,
        documentRangeFormattingProvider,
        documentSymbolProvider,
        executeCommandProvider,
        experimental,
        foldingRangeProvider,
        hoverProvider,
        implementationProvider,
        inlayHintProvider,
        inlineValueProvider,
        linkedEditingRangeProvider,
        monikerProvider,
        notebookDocumentSync,
        positionEncoding,
        referencesProvider,
        renameProvider,
        selectionRangeProvider,
        semanticTokensProvider,
        signatureHelpProvider,
        textDocumentSync,
        typeDefinitionProvider,
        typeHierarchyProvider,
        workspace,
        workspaceSymbolProvider,
      ]);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ServerCapabilitiesWorkspace implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ServerCapabilitiesWorkspace.canParse,
    ServerCapabilitiesWorkspace.fromJson,
  );

  ServerCapabilitiesWorkspace({
    this.fileOperations,
    this.workspaceFolders,
  });
  static ServerCapabilitiesWorkspace fromJson(Map<String, Object?> json) {
    final fileOperationsJson = json['fileOperations'];
    final fileOperations = fileOperationsJson != null
        ? FileOperationOptions.fromJson(
            fileOperationsJson as Map<String, Object?>)
        : null;
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = workspaceFoldersJson != null
        ? WorkspaceFoldersServerCapabilities.fromJson(
            workspaceFoldersJson as Map<String, Object?>)
        : null;
    return ServerCapabilitiesWorkspace(
      fileOperations: fileOperations,
      workspaceFolders: workspaceFolders,
    );
  }

  /// The server is interested in file notifications/requests.
  ///  @since 3.16.0
  final FileOperationOptions? fileOperations;

  /// The server supports workspace folder.
  ///  @since 3.6.0
  final WorkspaceFoldersServerCapabilities? workspaceFolders;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (fileOperations != null) {
      result['fileOperations'] = fileOperations?.toJson();
    }
    if (workspaceFolders != null) {
      result['workspaceFolders'] = workspaceFolders?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('fileOperations');
      try {
        final fileOperations = obj['fileOperations'];
        if (fileOperations != null &&
            !FileOperationOptions.canParse(fileOperations, reporter)) {
          reporter.reportError('must be of type FileOperationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceFolders');
      try {
        final workspaceFolders = obj['workspaceFolders'];
        if (workspaceFolders != null &&
            !WorkspaceFoldersServerCapabilities.canParse(
                workspaceFolders, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceFoldersServerCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ServerCapabilitiesWorkspace');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ServerCapabilitiesWorkspace &&
        other.runtimeType == ServerCapabilitiesWorkspace) {
      return fileOperations == other.fileOperations &&
          workspaceFolders == other.workspaceFolders &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        fileOperations,
        workspaceFolders,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SetTraceParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SetTraceParams.canParse,
    SetTraceParams.fromJson,
  );

  SetTraceParams({
    required this.value,
  });
  static SetTraceParams fromJson(Map<String, Object?> json) {
    final valueJson = json['value'];
    final value = const {'off', 'messages', 'verbose'}.contains(valueJson)
        ? valueJson as String
        : throw '''$valueJson was not one of ('off', 'messages', 'verbose')''';
    return SetTraceParams(
      value: value,
    );
  }

  /// The new value that should be assigned to the trace setting.
  final String value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final value = obj['value'];
        if (value == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (value != 'off' && value != 'messages' && value != 'verbose') {
          reporter.reportError(
              'must be one of the literals \'off\', \'messages\', \'verbose\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SetTraceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SetTraceParams && other.runtimeType == SetTraceParams) {
      return value == other.value && true;
    }
    return false;
  }

  @override
  int get hashCode => value.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities for the show document request.
///  @since 3.16.0
class ShowDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowDocumentClientCapabilities.canParse,
    ShowDocumentClientCapabilities.fromJson,
  );

  ShowDocumentClientCapabilities({
    required this.support,
  });
  static ShowDocumentClientCapabilities fromJson(Map<String, Object?> json) {
    final supportJson = json['support'];
    final support = supportJson as bool;
    return ShowDocumentClientCapabilities(
      support: support,
    );
  }

  /// The client has support for the show document request.
  final bool support;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['support'] = support;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('support');
      try {
        if (!obj.containsKey('support')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final support = obj['support'];
        if (support == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (support is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ShowDocumentClientCapabilities &&
        other.runtimeType == ShowDocumentClientCapabilities) {
      return support == other.support && true;
    }
    return false;
  }

  @override
  int get hashCode => support.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Params to show a document.
///  @since 3.16.0
class ShowDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowDocumentParams.canParse,
    ShowDocumentParams.fromJson,
  );

  ShowDocumentParams({
    this.external,
    this.selection,
    this.takeFocus,
    required this.uri,
  });
  static ShowDocumentParams fromJson(Map<String, Object?> json) {
    final externalJson = json['external'];
    final external = externalJson as bool?;
    final selectionJson = json['selection'];
    final selection = selectionJson != null
        ? Range.fromJson(selectionJson as Map<String, Object?>)
        : null;
    final takeFocusJson = json['takeFocus'];
    final takeFocus = takeFocusJson as bool?;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return ShowDocumentParams(
      external: external,
      selection: selection,
      takeFocus: takeFocus,
      uri: uri,
    );
  }

  /// Indicates to show the resource in an external program. To show for example
  /// `https://code.visualstudio.com/` in the default WEB browser set `external`
  /// to `true`.
  final bool? external;

  /// An optional selection range if the document is a text document. Clients
  /// might ignore the property if an external program is started or the file is
  /// not a text file.
  final Range? selection;

  /// An optional property to indicate whether the editor showing the document
  /// should take focus or not. Clients might ignore this property if an
  /// external program is started.
  final bool? takeFocus;

  /// The document uri to show.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (external != null) {
      result['external'] = external;
    }
    if (selection != null) {
      result['selection'] = selection?.toJson();
    }
    if (takeFocus != null) {
      result['takeFocus'] = takeFocus;
    }
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('external');
      try {
        final external = obj['external'];
        if (external != null && external is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selection');
      try {
        final selection = obj['selection'];
        if (selection != null && !Range.canParse(selection, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('takeFocus');
      try {
        final takeFocus = obj['takeFocus'];
        if (takeFocus != null && takeFocus is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ShowDocumentParams &&
        other.runtimeType == ShowDocumentParams) {
      return external == other.external &&
          selection == other.selection &&
          takeFocus == other.takeFocus &&
          uri == other.uri &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        external,
        selection,
        takeFocus,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result of an show document request.
///  @since 3.16.0
class ShowDocumentResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowDocumentResult.canParse,
    ShowDocumentResult.fromJson,
  );

  ShowDocumentResult({
    required this.success,
  });
  static ShowDocumentResult fromJson(Map<String, Object?> json) {
    final successJson = json['success'];
    final success = successJson as bool;
    return ShowDocumentResult(
      success: success,
    );
  }

  /// A boolean indicating if the show was successful.
  final bool success;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['success'] = success;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('success');
      try {
        if (!obj.containsKey('success')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final success = obj['success'];
        if (success == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (success is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowDocumentResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ShowDocumentResult &&
        other.runtimeType == ShowDocumentResult) {
      return success == other.success && true;
    }
    return false;
  }

  @override
  int get hashCode => success.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ShowMessageParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageParams.canParse,
    ShowMessageParams.fromJson,
  );

  ShowMessageParams({
    required this.message,
    required this.type,
  });
  static ShowMessageParams fromJson(Map<String, Object?> json) {
    final messageJson = json['message'];
    final message = messageJson as String;
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    return ShowMessageParams(
      message: message,
      type: type,
    );
  }

  /// The actual message.
  final String message;

  /// The message type.
  final MessageType type;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['message'] = message;
    result['type'] = type.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final type = obj['type'];
        if (type == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MessageType.canParse(type, reporter)) {
          reporter.reportError('must be of type MessageType');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowMessageParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ShowMessageParams && other.runtimeType == ShowMessageParams) {
      return message == other.message && type == other.type && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        message,
        type,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Show message request client capabilities
class ShowMessageRequestClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageRequestClientCapabilities.canParse,
    ShowMessageRequestClientCapabilities.fromJson,
  );

  ShowMessageRequestClientCapabilities({
    this.messageActionItem,
  });
  static ShowMessageRequestClientCapabilities fromJson(
      Map<String, Object?> json) {
    final messageActionItemJson = json['messageActionItem'];
    final messageActionItem = messageActionItemJson != null
        ? ShowMessageRequestClientCapabilitiesMessageActionItem.fromJson(
            messageActionItemJson as Map<String, Object?>)
        : null;
    return ShowMessageRequestClientCapabilities(
      messageActionItem: messageActionItem,
    );
  }

  /// Capabilities specific to the `MessageActionItem` type.
  final ShowMessageRequestClientCapabilitiesMessageActionItem?
      messageActionItem;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (messageActionItem != null) {
      result['messageActionItem'] = messageActionItem?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('messageActionItem');
      try {
        final messageActionItem = obj['messageActionItem'];
        if (messageActionItem != null &&
            !ShowMessageRequestClientCapabilitiesMessageActionItem.canParse(
                messageActionItem, reporter)) {
          reporter.reportError(
              'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type ShowMessageRequestClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (additionalPropertiesSupport != null) {
      result['additionalPropertiesSupport'] = additionalPropertiesSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('additionalPropertiesSupport');
      try {
        final additionalPropertiesSupport = obj['additionalPropertiesSupport'];
        if (additionalPropertiesSupport != null &&
            additionalPropertiesSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ShowMessageRequestClientCapabilitiesMessageActionItem &&
        other.runtimeType ==
            ShowMessageRequestClientCapabilitiesMessageActionItem) {
      return additionalPropertiesSupport == other.additionalPropertiesSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => additionalPropertiesSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ShowMessageRequestParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageRequestParams.canParse,
    ShowMessageRequestParams.fromJson,
  );

  ShowMessageRequestParams({
    this.actions,
    required this.message,
    required this.type,
  });
  static ShowMessageRequestParams fromJson(Map<String, Object?> json) {
    final actionsJson = json['actions'];
    final actions = (actionsJson as List<Object?>?)
        ?.map(
            (item) => MessageActionItem.fromJson(item as Map<String, Object?>))
        .toList();
    final messageJson = json['message'];
    final message = messageJson as String;
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    return ShowMessageRequestParams(
      actions: actions,
      message: message,
      type: type,
    );
  }

  /// The message action items to present.
  final List<MessageActionItem>? actions;

  /// The actual message
  final String message;

  /// The message type.
  final MessageType type;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (actions != null) {
      result['actions'] = actions?.map((item) => item.toJson()).toList();
    }
    result['message'] = message;
    result['type'] = type.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('actions');
      try {
        final actions = obj['actions'];
        if (actions != null &&
            (actions is! List<Object?> ||
                actions.any(
                    (item) => !MessageActionItem.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<MessageActionItem>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final message = obj['message'];
        if (message == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final type = obj['type'];
        if (type == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!MessageType.canParse(type, reporter)) {
          reporter.reportError('must be of type MessageType');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowMessageRequestParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ShowMessageRequestParams &&
        other.runtimeType == ShowMessageRequestParams) {
      return listEqual(actions, other.actions,
              (MessageActionItem a, MessageActionItem b) => a == b) &&
          message == other.message &&
          type == other.type &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(actions),
        message,
        type,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Signature help represents the signature of something callable. There can be
/// multiple signature but only one active and only one active parameter.
class SignatureHelp implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelp.canParse,
    SignatureHelp.fromJson,
  );

  SignatureHelp({
    this.activeParameter,
    this.activeSignature,
    required this.signatures,
  });
  static SignatureHelp fromJson(Map<String, Object?> json) {
    final activeParameterJson = json['activeParameter'];
    final activeParameter = activeParameterJson as int?;
    final activeSignatureJson = json['activeSignature'];
    final activeSignature = activeSignatureJson as int?;
    final signaturesJson = json['signatures'];
    final signatures = (signaturesJson as List<Object?>)
        .map((item) =>
            SignatureInformation.fromJson(item as Map<String, Object?>))
        .toList();
    return SignatureHelp(
      activeParameter: activeParameter,
      activeSignature: activeSignature,
      signatures: signatures,
    );
  }

  /// The active parameter of the active signature. If omitted or the value lies
  /// outside the range of `signatures[activeSignature].parameters` defaults to
  /// 0 if the active signature has parameters. If the active signature has no
  /// parameters it is ignored. In future version of the protocol this property
  /// might become mandatory to better express the active parameter if the
  /// active signature does have any.
  final int? activeParameter;

  /// The active signature. If omitted or the value lies outside the range of
  /// `signatures` the value defaults to zero or is ignore if the
  /// `SignatureHelp` as no signatures.
  ///
  /// Whenever possible implementors should make an active decision about the
  /// active signature and shouldn't rely on a default value.
  ///
  /// In future version of the protocol this property might become mandatory to
  /// better express this.
  final int? activeSignature;

  /// One or more signatures. If no signatures are available the signature help
  /// request should return `null`.
  final List<SignatureInformation> signatures;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeParameter != null) {
      result['activeParameter'] = activeParameter;
    }
    if (activeSignature != null) {
      result['activeSignature'] = activeSignature;
    }
    result['signatures'] = signatures.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('activeParameter');
      try {
        final activeParameter = obj['activeParameter'];
        if (activeParameter != null && activeParameter is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('activeSignature');
      try {
        final activeSignature = obj['activeSignature'];
        if (activeSignature != null && activeSignature is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatures');
      try {
        if (!obj.containsKey('signatures')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final signatures = obj['signatures'];
        if (signatures == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (signatures is! List<Object?> ||
            signatures.any(
                (item) => !SignatureInformation.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SignatureInformation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelp');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelp && other.runtimeType == SignatureHelp) {
      return activeParameter == other.activeParameter &&
          activeSignature == other.activeSignature &&
          listEqual(signatures, other.signatures,
              (SignatureInformation a, SignatureInformation b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        activeParameter,
        activeSignature,
        lspHashCode(signatures),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpClientCapabilities.canParse,
    SignatureHelpClientCapabilities.fromJson,
  );

  SignatureHelpClientCapabilities({
    this.contextSupport,
    this.dynamicRegistration,
    this.signatureInformation,
  });
  static SignatureHelpClientCapabilities fromJson(Map<String, Object?> json) {
    final contextSupportJson = json['contextSupport'];
    final contextSupport = contextSupportJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final signatureInformationJson = json['signatureInformation'];
    final signatureInformation = signatureInformationJson != null
        ? SignatureHelpClientCapabilitiesSignatureInformation.fromJson(
            signatureInformationJson as Map<String, Object?>)
        : null;
    return SignatureHelpClientCapabilities(
      contextSupport: contextSupport,
      dynamicRegistration: dynamicRegistration,
      signatureInformation: signatureInformation,
    );
  }

  /// The client supports to send additional context information for a
  /// `textDocument/signatureHelp` request. A client that opts into
  /// contextSupport will also support the `retriggerCharacters` on
  /// `SignatureHelpOptions`.
  ///  @since 3.15.0
  final bool? contextSupport;

  /// Whether signature help supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports the following `SignatureInformation` specific
  /// properties.
  final SignatureHelpClientCapabilitiesSignatureInformation?
      signatureInformation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (contextSupport != null) {
      result['contextSupport'] = contextSupport;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (signatureInformation != null) {
      result['signatureInformation'] = signatureInformation?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('contextSupport');
      try {
        final contextSupport = obj['contextSupport'];
        if (contextSupport != null && contextSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatureInformation');
      try {
        final signatureInformation = obj['signatureInformation'];
        if (signatureInformation != null &&
            !SignatureHelpClientCapabilitiesSignatureInformation.canParse(
                signatureInformation, reporter)) {
          reporter.reportError(
              'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpClientCapabilities &&
        other.runtimeType == SignatureHelpClientCapabilities) {
      return contextSupport == other.contextSupport &&
          dynamicRegistration == other.dynamicRegistration &&
          signatureInformation == other.signatureInformation &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        contextSupport,
        dynamicRegistration,
        signatureInformation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpClientCapabilitiesSignatureInformation
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpClientCapabilitiesSignatureInformation.canParse,
    SignatureHelpClientCapabilitiesSignatureInformation.fromJson,
  );

  SignatureHelpClientCapabilitiesSignatureInformation({
    this.activeParameterSupport,
    this.documentationFormat,
    this.parameterInformation,
  });
  static SignatureHelpClientCapabilitiesSignatureInformation fromJson(
      Map<String, Object?> json) {
    final activeParameterSupportJson = json['activeParameterSupport'];
    final activeParameterSupport = activeParameterSupportJson as bool?;
    final documentationFormatJson = json['documentationFormat'];
    final documentationFormat = (documentationFormatJson as List<Object?>?)
        ?.map((item) => MarkupKind.fromJson(item as String))
        .toList();
    final parameterInformationJson = json['parameterInformation'];
    final parameterInformation = parameterInformationJson != null
        ? SignatureInformationParameterInformation.fromJson(
            parameterInformationJson as Map<String, Object?>)
        : null;
    return SignatureHelpClientCapabilitiesSignatureInformation(
      activeParameterSupport: activeParameterSupport,
      documentationFormat: documentationFormat,
      parameterInformation: parameterInformation,
    );
  }

  /// The client supports the `activeParameter` property on
  /// `SignatureInformation` literal.
  ///  @since 3.16.0
  final bool? activeParameterSupport;

  /// Client supports the 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 SignatureInformationParameterInformation? parameterInformation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeParameterSupport != null) {
      result['activeParameterSupport'] = activeParameterSupport;
    }
    if (documentationFormat != null) {
      result['documentationFormat'] =
          documentationFormat?.map((item) => item.toJson()).toList();
    }
    if (parameterInformation != null) {
      result['parameterInformation'] = parameterInformation?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('activeParameterSupport');
      try {
        final activeParameterSupport = obj['activeParameterSupport'];
        if (activeParameterSupport != null && activeParameterSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentationFormat');
      try {
        final documentationFormat = obj['documentationFormat'];
        if (documentationFormat != null &&
            (documentationFormat is! List<Object?> ||
                documentationFormat
                    .any((item) => !MarkupKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<MarkupKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('parameterInformation');
      try {
        final parameterInformation = obj['parameterInformation'];
        if (parameterInformation != null &&
            !SignatureInformationParameterInformation.canParse(
                parameterInformation, reporter)) {
          reporter.reportError(
              'must be of type SignatureInformationParameterInformation');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpClientCapabilitiesSignatureInformation &&
        other.runtimeType ==
            SignatureHelpClientCapabilitiesSignatureInformation) {
      return activeParameterSupport == other.activeParameterSupport &&
          listEqual(documentationFormat, other.documentationFormat,
              (MarkupKind a, MarkupKind b) => a == b) &&
          parameterInformation == other.parameterInformation &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        activeParameterSupport,
        lspHashCode(documentationFormat),
        parameterInformation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Additional information about the context in which a signature help request
/// was triggered.
///  @since 3.15.0
class SignatureHelpContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpContext.canParse,
    SignatureHelpContext.fromJson,
  );

  SignatureHelpContext({
    this.activeSignatureHelp,
    required this.isRetrigger,
    this.triggerCharacter,
    required this.triggerKind,
  });
  static SignatureHelpContext fromJson(Map<String, Object?> json) {
    final activeSignatureHelpJson = json['activeSignatureHelp'];
    final activeSignatureHelp = activeSignatureHelpJson != null
        ? SignatureHelp.fromJson(
            activeSignatureHelpJson as Map<String, Object?>)
        : null;
    final isRetriggerJson = json['isRetrigger'];
    final isRetrigger = isRetriggerJson as bool;
    final triggerCharacterJson = json['triggerCharacter'];
    final triggerCharacter = triggerCharacterJson as String?;
    final triggerKindJson = json['triggerKind'];
    final triggerKind =
        SignatureHelpTriggerKind.fromJson(triggerKindJson as int);
    return SignatureHelpContext(
      activeSignatureHelp: activeSignatureHelp,
      isRetrigger: isRetrigger,
      triggerCharacter: triggerCharacter,
      triggerKind: triggerKind,
    );
  }

  /// The currently active `SignatureHelp`.
  ///
  /// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field
  /// updated based on the user navigating through available signatures.
  final SignatureHelp? activeSignatureHelp;

  /// `true` if signature help was already showing when it was triggered.
  ///
  /// Retriggers occur when the signature help is already active and can be
  /// caused by actions such as typing a trigger character, a cursor move, or
  /// document content changes.
  final bool isRetrigger;

  /// Character that caused signature help to be triggered.
  ///
  /// This is undefined when triggerKind !==
  /// SignatureHelpTriggerKind.TriggerCharacter
  final String? triggerCharacter;

  /// Action that caused signature help to be triggered.
  final SignatureHelpTriggerKind triggerKind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeSignatureHelp != null) {
      result['activeSignatureHelp'] = activeSignatureHelp?.toJson();
    }
    result['isRetrigger'] = isRetrigger;
    if (triggerCharacter != null) {
      result['triggerCharacter'] = triggerCharacter;
    }
    result['triggerKind'] = triggerKind.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('activeSignatureHelp');
      try {
        final activeSignatureHelp = obj['activeSignatureHelp'];
        if (activeSignatureHelp != null &&
            !SignatureHelp.canParse(activeSignatureHelp, reporter)) {
          reporter.reportError('must be of type SignatureHelp');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('isRetrigger');
      try {
        if (!obj.containsKey('isRetrigger')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final isRetrigger = obj['isRetrigger'];
        if (isRetrigger == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (isRetrigger is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacter');
      try {
        final triggerCharacter = obj['triggerCharacter'];
        if (triggerCharacter != null && triggerCharacter is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerKind');
      try {
        if (!obj.containsKey('triggerKind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final triggerKind = obj['triggerKind'];
        if (triggerKind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SignatureHelpTriggerKind.canParse(triggerKind, reporter)) {
          reporter.reportError('must be of type SignatureHelpTriggerKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpContext &&
        other.runtimeType == SignatureHelpContext) {
      return activeSignatureHelp == other.activeSignatureHelp &&
          isRetrigger == other.isRetrigger &&
          triggerCharacter == other.triggerCharacter &&
          triggerKind == other.triggerKind &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        activeSignatureHelp,
        isRetrigger,
        triggerCharacter,
        triggerKind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpOptions.canParse,
    SignatureHelpOptions.fromJson,
  );

  SignatureHelpOptions({
    this.retriggerCharacters,
    this.triggerCharacters,
    this.workDoneProgress,
  });
  static SignatureHelpOptions fromJson(Map<String, Object?> json) {
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    final retriggerCharactersJson = json['retriggerCharacters'];
    final retriggerCharacters = (retriggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SignatureHelpOptions(
      retriggerCharacters: retriggerCharacters,
      triggerCharacters: triggerCharacters,
      workDoneProgress: workDoneProgress,
    );
  }

  /// List of characters that re-trigger signature help.
  ///
  /// These trigger characters are only active when signature help is already
  /// showing. All trigger characters are also counted as re-trigger characters.
  ///  @since 3.15.0
  final List<String>? retriggerCharacters;

  /// The characters that trigger signature help automatically.
  final List<String>? triggerCharacters;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (retriggerCharacters != null) {
      result['retriggerCharacters'] = retriggerCharacters;
    }
    if (triggerCharacters != null) {
      result['triggerCharacters'] = triggerCharacters;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('retriggerCharacters');
      try {
        final retriggerCharacters = obj['retriggerCharacters'];
        if (retriggerCharacters != null &&
            (retriggerCharacters is! List<Object?> ||
                retriggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacters');
      try {
        final triggerCharacters = obj['triggerCharacters'];
        if (triggerCharacters != null &&
            (triggerCharacters is! List<Object?> ||
                triggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpOptions &&
        other.runtimeType == SignatureHelpOptions) {
      return listEqual(retriggerCharacters, other.retriggerCharacters,
              (String a, String b) => a == b) &&
          listEqual(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(retriggerCharacters),
        lspHashCode(triggerCharacters),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpParams.canParse,
    SignatureHelpParams.fromJson,
  );

  SignatureHelpParams({
    this.context,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static SignatureHelpParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context = contextJson != null
        ? SignatureHelpContext.fromJson(contextJson as Map<String, Object?>)
        : null;
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return SignatureHelpParams(
      context: context,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The signature help context. This is only available if the client specifies
  /// to send this using the client capability
  /// `textDocument.signatureHelp.contextSupport === true`
  ///  @since 3.15.0
  final SignatureHelpContext? context;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (context != null) {
      result['context'] = context?.toJson();
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('context');
      try {
        final context = obj['context'];
        if (context != null &&
            !SignatureHelpContext.canParse(context, reporter)) {
          reporter.reportError('must be of type SignatureHelpContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpParams &&
        other.runtimeType == SignatureHelpParams) {
      return context == other.context &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        context,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpRegistrationOptions
    implements
        SignatureHelpOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpRegistrationOptions.canParse,
    SignatureHelpRegistrationOptions.fromJson,
  );

  SignatureHelpRegistrationOptions({
    this.documentSelector,
    this.retriggerCharacters,
    this.triggerCharacters,
    this.workDoneProgress,
  });
  static SignatureHelpRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final retriggerCharactersJson = json['retriggerCharacters'];
    final retriggerCharacters = (retriggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SignatureHelpRegistrationOptions(
      documentSelector: documentSelector,
      retriggerCharacters: retriggerCharacters,
      triggerCharacters: triggerCharacters,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// List of characters that re-trigger signature help.
  ///
  /// These trigger characters are only active when signature help is already
  /// showing. All trigger characters are also counted as re-trigger characters.
  ///  @since 3.15.0
  @override
  final List<String>? retriggerCharacters;

  /// The characters that trigger signature help automatically.
  @override
  final List<String>? triggerCharacters;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (retriggerCharacters != null) {
      result['retriggerCharacters'] = retriggerCharacters;
    }
    if (triggerCharacters != null) {
      result['triggerCharacters'] = triggerCharacters;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('retriggerCharacters');
      try {
        final retriggerCharacters = obj['retriggerCharacters'];
        if (retriggerCharacters != null &&
            (retriggerCharacters is! List<Object?> ||
                retriggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacters');
      try {
        final triggerCharacters = obj['triggerCharacters'];
        if (triggerCharacters != null &&
            (triggerCharacters is! List<Object?> ||
                triggerCharacters.any((item) => item is! String))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpRegistrationOptions &&
        other.runtimeType == SignatureHelpRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          listEqual(retriggerCharacters, other.retriggerCharacters,
              (String a, String b) => a == b) &&
          listEqual(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        lspHashCode(retriggerCharacters),
        lspHashCode(triggerCharacters),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// How a signature help was triggered.
///  @since 3.15.0
class SignatureHelpTriggerKind implements ToJsonable {
  const SignatureHelpTriggerKind(this._value);
  const SignatureHelpTriggerKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Signature help was triggered by the cursor moving or by the document
  /// content changing.
  static const ContentChange = SignatureHelpTriggerKind(3);

  /// Signature help was invoked manually by the user or by a command.
  static const Invoked = SignatureHelpTriggerKind(1);

  /// Signature help was triggered by a trigger character.
  static const TriggerCharacter = SignatureHelpTriggerKind(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SignatureHelpTriggerKind && other._value == _value;
}

/// Represents the signature of something callable. A signature can have a
/// label, like a function-name, a doc-comment, and a set of parameters.
class SignatureInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureInformation.canParse,
    SignatureInformation.fromJson,
  );

  SignatureInformation({
    this.activeParameter,
    this.documentation,
    required this.label,
    this.parameters,
  });
  static SignatureInformation fromJson(Map<String, Object?> json) {
    final activeParameterJson = json['activeParameter'];
    final activeParameter = activeParameterJson as int?;
    final documentationJson = json['documentation'];
    final documentation = documentationJson == null
        ? null
        : (MarkupContent.canParse(documentationJson, nullLspJsonReporter)
            ? Either2<MarkupContent, String>.t1(MarkupContent.fromJson(
                documentationJson as Map<String, Object?>))
            : (documentationJson is String
                ? Either2<MarkupContent, String>.t2(documentationJson)
                : (throw '''$documentationJson was not one of (MarkupContent, String)''')));
    final labelJson = json['label'];
    final label = labelJson as String;
    final parametersJson = json['parameters'];
    final parameters = (parametersJson as List<Object?>?)
        ?.map((item) =>
            ParameterInformation.fromJson(item as Map<String, Object?>))
        .toList();
    return SignatureInformation(
      activeParameter: activeParameter,
      documentation: documentation,
      label: label,
      parameters: parameters,
    );
  }

  /// The index of the active parameter.
  ///
  /// If provided, this is used in place of `SignatureHelp.activeParameter`.
  ///  @since 3.16.0
  final int? activeParameter;

  /// The human-readable doc-comment of this signature. Will be shown in the UI
  /// but can be omitted.
  final Either2<MarkupContent, String>? documentation;

  /// The label of this signature. Will be shown in the UI.
  final String label;

  /// The parameters of this signature.
  final List<ParameterInformation>? parameters;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeParameter != null) {
      result['activeParameter'] = activeParameter;
    }
    if (documentation != null) {
      result['documentation'] = documentation;
    }
    result['label'] = label;
    if (parameters != null) {
      result['parameters'] = parameters?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('activeParameter');
      try {
        final activeParameter = obj['activeParameter'];
        if (activeParameter != null && activeParameter is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentation');
      try {
        final documentation = obj['documentation'];
        if (documentation != null &&
            !MarkupContent.canParse(documentation, reporter) &&
            documentation is! String) {
          reporter
              .reportError('must be of type Either2<MarkupContent, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final label = obj['label'];
        if (label == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (label is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('parameters');
      try {
        final parameters = obj['parameters'];
        if (parameters != null &&
            (parameters is! List<Object?> ||
                parameters.any((item) =>
                    !ParameterInformation.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<ParameterInformation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureInformation &&
        other.runtimeType == SignatureInformation) {
      return activeParameter == other.activeParameter &&
          documentation == other.documentation &&
          label == other.label &&
          listEqual(parameters, other.parameters,
              (ParameterInformation a, ParameterInformation b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        activeParameter,
        documentation,
        label,
        lspHashCode(parameters),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureInformationParameterInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureInformationParameterInformation.canParse,
    SignatureInformationParameterInformation.fromJson,
  );

  SignatureInformationParameterInformation({
    this.labelOffsetSupport,
  });
  static SignatureInformationParameterInformation fromJson(
      Map<String, Object?> json) {
    final labelOffsetSupportJson = json['labelOffsetSupport'];
    final labelOffsetSupport = labelOffsetSupportJson as bool?;
    return SignatureInformationParameterInformation(
      labelOffsetSupport: labelOffsetSupport,
    );
  }

  /// The client supports processing label offsets instead of a simple label
  /// string.
  ///  @since 3.14.0
  final bool? labelOffsetSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (labelOffsetSupport != null) {
      result['labelOffsetSupport'] = labelOffsetSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('labelOffsetSupport');
      try {
        final labelOffsetSupport = obj['labelOffsetSupport'];
        if (labelOffsetSupport != null && labelOffsetSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SignatureInformationParameterInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureInformationParameterInformation &&
        other.runtimeType == SignatureInformationParameterInformation) {
      return labelOffsetSupport == other.labelOffsetSupport && true;
    }
    return false;
  }

  @override
  int get hashCode => labelOffsetSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Static registration options to be returned in the initialize request.
class StaticRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    StaticRegistrationOptions.canParse,
    StaticRegistrationOptions.fromJson,
  );

  StaticRegistrationOptions({
    this.id,
  });
  static StaticRegistrationOptions fromJson(Map<String, Object?> json) {
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (DiagnosticRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    if (NotebookDocumentSyncRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return NotebookDocumentSyncRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    final idJson = json['id'];
    final id = idJson as String?;
    return StaticRegistrationOptions(
      id: id,
    );
  }

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  final String? id;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (id != null) {
      result['id'] = id;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type StaticRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is StaticRegistrationOptions &&
        other.runtimeType == StaticRegistrationOptions) {
      return id == other.id && true;
    }
    return false;
  }

  @override
  int get hashCode => id.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents information about programming constructs like variables, classes,
/// interfaces etc.
///  @deprecated use DocumentSymbol or WorkspaceSymbol instead.
class SymbolInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SymbolInformation.canParse,
    SymbolInformation.fromJson,
  );

  SymbolInformation({
    this.containerName,
    this.deprecated,
    required this.kind,
    required this.location,
    required this.name,
    this.tags,
  });
  static SymbolInformation fromJson(Map<String, Object?> json) {
    final containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    final deprecatedJson = json['deprecated'];
    final deprecated = deprecatedJson as bool?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final locationJson = json['location'];
    final location = Location.fromJson(locationJson as Map<String, Object?>);
    final nameJson = json['name'];
    final name = nameJson as String;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return SymbolInformation(
      containerName: containerName,
      deprecated: deprecated,
      kind: kind,
      location: location,
      name: name,
      tags: tags,
    );
  }

  /// The name of the symbol containing this symbol. This information is for
  /// user interface purposes (e.g. to render a qualifier in the user interface
  /// if necessary). It can't be used to re-infer a hierarchy for the document
  /// symbols.
  final String? containerName;

  /// Indicates if this symbol is deprecated.
  ///  @deprecated Use tags instead
  final bool? deprecated;

  /// The kind of this symbol.
  final SymbolKind kind;

  /// The location of this symbol. The location's range is used by a tool to
  /// reveal the location in the editor. If the symbol is selected in the tool
  /// the range's start information is used to position the cursor. So the range
  /// usually spans more then the actual symbol's name and does normally include
  /// things like visibility modifiers.
  ///
  /// The range doesn't have to denote a node range in the sense of a abstract
  /// syntax tree. It can therefore not be used to re-construct a hierarchy of
  /// the symbols.
  final Location location;

  /// The name of this symbol.
  final String name;

  /// Tags for this symbol.
  ///  @since 3.16.0
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (containerName != null) {
      result['containerName'] = containerName;
    }
    if (deprecated != null) {
      result['deprecated'] = deprecated;
    }
    result['kind'] = kind.toJson();
    result['location'] = location.toJson();
    result['name'] = name;
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('containerName');
      try {
        final containerName = obj['containerName'];
        if (containerName != null && containerName is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deprecated');
      try {
        final deprecated = obj['deprecated'];
        if (deprecated != null && deprecated is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('location');
      try {
        if (!obj.containsKey('location')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final location = obj['location'];
        if (location == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Location.canParse(location, reporter)) {
          reporter.reportError('must be of type Location');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SymbolInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SymbolInformation && other.runtimeType == SymbolInformation) {
      return containerName == other.containerName &&
          deprecated == other.deprecated &&
          kind == other.kind &&
          location == other.location &&
          name == other.name &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        containerName,
        deprecated,
        kind,
        location,
        name,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A symbol kind.
class SymbolKind implements ToJsonable {
  const SymbolKind(this._value);
  const SymbolKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  static const Array = SymbolKind(18);
  static const Boolean = SymbolKind(17);
  static const Class = SymbolKind(5);
  static const Constant = SymbolKind(14);
  static const Constructor = SymbolKind(9);
  static const Enum = SymbolKind(10);
  static const EnumMember = SymbolKind(22);
  static const Event = SymbolKind(24);
  static const Field = SymbolKind(8);
  static const File = SymbolKind(1);
  static const Function = SymbolKind(12);
  static const Interface = SymbolKind(11);
  static const Key = SymbolKind(20);
  static const Method = SymbolKind(6);
  static const Module = SymbolKind(2);
  static const Namespace = SymbolKind(3);
  static const Null = SymbolKind(21);
  static const Number = SymbolKind(16);
  static const Obj = SymbolKind(19);
  static const Operator = SymbolKind(25);
  static const Package = SymbolKind(4);
  static const Property = SymbolKind(7);
  static const Str = SymbolKind(15);
  static const Struct = SymbolKind(23);
  static const TypeParameter = SymbolKind(26);
  static const Variable = SymbolKind(13);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SymbolKind && other._value == _value;
}

/// Symbol tags are extra annotations that tweak the rendering of a symbol.
///  @since 3.16
class SymbolTag implements ToJsonable {
  const SymbolTag(this._value);
  const SymbolTag.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Render a symbol as obsolete, usually using a strike-out.
  static const Deprecated = SymbolTag(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SymbolTag && other._value == _value;
}

/// Describe options to be used when registering for text document change
/// events.
class TextDocumentChangeRegistrationOptions
    implements TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentChangeRegistrationOptions.canParse,
    TextDocumentChangeRegistrationOptions.fromJson,
  );

  TextDocumentChangeRegistrationOptions({
    this.documentSelector,
    required this.syncKind,
  });
  static TextDocumentChangeRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final syncKindJson = json['syncKind'];
    final syncKind = TextDocumentSyncKind.fromJson(syncKindJson as int);
    return TextDocumentChangeRegistrationOptions(
      documentSelector: documentSelector,
      syncKind: syncKind,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// How documents are synced to the server. See TextDocumentSyncKind.Full and
  /// TextDocumentSyncKind.Incremental.
  final TextDocumentSyncKind syncKind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    result['syncKind'] = syncKind.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('syncKind');
      try {
        if (!obj.containsKey('syncKind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final syncKind = obj['syncKind'];
        if (syncKind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentSyncKind.canParse(syncKind, reporter)) {
          reporter.reportError('must be of type TextDocumentSyncKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type TextDocumentChangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentChangeRegistrationOptions &&
        other.runtimeType == TextDocumentChangeRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          syncKind == other.syncKind &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        syncKind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Text document specific client capabilities.
class TextDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentClientCapabilities.canParse,
    TextDocumentClientCapabilities.fromJson,
  );

  TextDocumentClientCapabilities({
    this.callHierarchy,
    this.codeAction,
    this.codeLens,
    this.colorProvider,
    this.completion,
    this.declaration,
    this.definition,
    this.diagnostic,
    this.documentHighlight,
    this.documentLink,
    this.documentSymbol,
    this.foldingRange,
    this.formatting,
    this.hover,
    this.implementation,
    this.inlayHint,
    this.inlineValue,
    this.linkedEditingRange,
    this.moniker,
    this.onTypeFormatting,
    this.publishDiagnostics,
    this.rangeFormatting,
    this.references,
    this.rename,
    this.selectionRange,
    this.semanticTokens,
    this.signatureHelp,
    this.synchronization,
    this.typeDefinition,
    this.typeHierarchy,
  });
  static TextDocumentClientCapabilities fromJson(Map<String, Object?> json) {
    final callHierarchyJson = json['callHierarchy'];
    final callHierarchy = callHierarchyJson != null
        ? CallHierarchyClientCapabilities.fromJson(
            callHierarchyJson as Map<String, Object?>)
        : null;
    final codeActionJson = json['codeAction'];
    final codeAction = codeActionJson != null
        ? CodeActionClientCapabilities.fromJson(
            codeActionJson as Map<String, Object?>)
        : null;
    final codeLensJson = json['codeLens'];
    final codeLens = codeLensJson != null
        ? CodeLensClientCapabilities.fromJson(
            codeLensJson as Map<String, Object?>)
        : null;
    final colorProviderJson = json['colorProvider'];
    final colorProvider = colorProviderJson != null
        ? DocumentColorClientCapabilities.fromJson(
            colorProviderJson as Map<String, Object?>)
        : null;
    final completionJson = json['completion'];
    final completion = completionJson != null
        ? CompletionClientCapabilities.fromJson(
            completionJson as Map<String, Object?>)
        : null;
    final declarationJson = json['declaration'];
    final declaration = declarationJson != null
        ? DeclarationClientCapabilities.fromJson(
            declarationJson as Map<String, Object?>)
        : null;
    final definitionJson = json['definition'];
    final definition = definitionJson != null
        ? DefinitionClientCapabilities.fromJson(
            definitionJson as Map<String, Object?>)
        : null;
    final diagnosticJson = json['diagnostic'];
    final diagnostic = diagnosticJson != null
        ? DiagnosticClientCapabilities.fromJson(
            diagnosticJson as Map<String, Object?>)
        : null;
    final documentHighlightJson = json['documentHighlight'];
    final documentHighlight = documentHighlightJson != null
        ? DocumentHighlightClientCapabilities.fromJson(
            documentHighlightJson as Map<String, Object?>)
        : null;
    final documentLinkJson = json['documentLink'];
    final documentLink = documentLinkJson != null
        ? DocumentLinkClientCapabilities.fromJson(
            documentLinkJson as Map<String, Object?>)
        : null;
    final documentSymbolJson = json['documentSymbol'];
    final documentSymbol = documentSymbolJson != null
        ? DocumentSymbolClientCapabilities.fromJson(
            documentSymbolJson as Map<String, Object?>)
        : null;
    final foldingRangeJson = json['foldingRange'];
    final foldingRange = foldingRangeJson != null
        ? FoldingRangeClientCapabilities.fromJson(
            foldingRangeJson as Map<String, Object?>)
        : null;
    final formattingJson = json['formatting'];
    final formatting = formattingJson != null
        ? DocumentFormattingClientCapabilities.fromJson(
            formattingJson as Map<String, Object?>)
        : null;
    final hoverJson = json['hover'];
    final hover = hoverJson != null
        ? HoverClientCapabilities.fromJson(hoverJson as Map<String, Object?>)
        : null;
    final implementationJson = json['implementation'];
    final implementation = implementationJson != null
        ? ImplementationClientCapabilities.fromJson(
            implementationJson as Map<String, Object?>)
        : null;
    final inlayHintJson = json['inlayHint'];
    final inlayHint = inlayHintJson != null
        ? InlayHintClientCapabilities.fromJson(
            inlayHintJson as Map<String, Object?>)
        : null;
    final inlineValueJson = json['inlineValue'];
    final inlineValue = inlineValueJson != null
        ? InlineValueClientCapabilities.fromJson(
            inlineValueJson as Map<String, Object?>)
        : null;
    final linkedEditingRangeJson = json['linkedEditingRange'];
    final linkedEditingRange = linkedEditingRangeJson != null
        ? LinkedEditingRangeClientCapabilities.fromJson(
            linkedEditingRangeJson as Map<String, Object?>)
        : null;
    final monikerJson = json['moniker'];
    final moniker = monikerJson != null
        ? MonikerClientCapabilities.fromJson(
            monikerJson as Map<String, Object?>)
        : null;
    final onTypeFormattingJson = json['onTypeFormatting'];
    final onTypeFormatting = onTypeFormattingJson != null
        ? DocumentOnTypeFormattingClientCapabilities.fromJson(
            onTypeFormattingJson as Map<String, Object?>)
        : null;
    final publishDiagnosticsJson = json['publishDiagnostics'];
    final publishDiagnostics = publishDiagnosticsJson != null
        ? PublishDiagnosticsClientCapabilities.fromJson(
            publishDiagnosticsJson as Map<String, Object?>)
        : null;
    final rangeFormattingJson = json['rangeFormatting'];
    final rangeFormatting = rangeFormattingJson != null
        ? DocumentRangeFormattingClientCapabilities.fromJson(
            rangeFormattingJson as Map<String, Object?>)
        : null;
    final referencesJson = json['references'];
    final references = referencesJson != null
        ? ReferenceClientCapabilities.fromJson(
            referencesJson as Map<String, Object?>)
        : null;
    final renameJson = json['rename'];
    final rename = renameJson != null
        ? RenameClientCapabilities.fromJson(renameJson as Map<String, Object?>)
        : null;
    final selectionRangeJson = json['selectionRange'];
    final selectionRange = selectionRangeJson != null
        ? SelectionRangeClientCapabilities.fromJson(
            selectionRangeJson as Map<String, Object?>)
        : null;
    final semanticTokensJson = json['semanticTokens'];
    final semanticTokens = semanticTokensJson != null
        ? SemanticTokensClientCapabilities.fromJson(
            semanticTokensJson as Map<String, Object?>)
        : null;
    final signatureHelpJson = json['signatureHelp'];
    final signatureHelp = signatureHelpJson != null
        ? SignatureHelpClientCapabilities.fromJson(
            signatureHelpJson as Map<String, Object?>)
        : null;
    final synchronizationJson = json['synchronization'];
    final synchronization = synchronizationJson != null
        ? TextDocumentSyncClientCapabilities.fromJson(
            synchronizationJson as Map<String, Object?>)
        : null;
    final typeDefinitionJson = json['typeDefinition'];
    final typeDefinition = typeDefinitionJson != null
        ? TypeDefinitionClientCapabilities.fromJson(
            typeDefinitionJson as Map<String, Object?>)
        : null;
    final typeHierarchyJson = json['typeHierarchy'];
    final typeHierarchy = typeHierarchyJson != null
        ? TypeHierarchyClientCapabilities.fromJson(
            typeHierarchyJson as Map<String, Object?>)
        : null;
    return TextDocumentClientCapabilities(
      callHierarchy: callHierarchy,
      codeAction: codeAction,
      codeLens: codeLens,
      colorProvider: colorProvider,
      completion: completion,
      declaration: declaration,
      definition: definition,
      diagnostic: diagnostic,
      documentHighlight: documentHighlight,
      documentLink: documentLink,
      documentSymbol: documentSymbol,
      foldingRange: foldingRange,
      formatting: formatting,
      hover: hover,
      implementation: implementation,
      inlayHint: inlayHint,
      inlineValue: inlineValue,
      linkedEditingRange: linkedEditingRange,
      moniker: moniker,
      onTypeFormatting: onTypeFormatting,
      publishDiagnostics: publishDiagnostics,
      rangeFormatting: rangeFormatting,
      references: references,
      rename: rename,
      selectionRange: selectionRange,
      semanticTokens: semanticTokens,
      signatureHelp: signatureHelp,
      synchronization: synchronization,
      typeDefinition: typeDefinition,
      typeHierarchy: typeHierarchy,
    );
  }

  /// Capabilities specific to the various call hierarchy requests.
  ///  @since 3.16.0
  final CallHierarchyClientCapabilities? callHierarchy;

  /// Capabilities specific to the `textDocument/codeAction` request.
  final CodeActionClientCapabilities? codeAction;

  /// Capabilities specific to the `textDocument/codeLens` request.
  final CodeLensClientCapabilities? codeLens;

  /// Capabilities specific to the `textDocument/documentColor` and the
  /// `textDocument/colorPresentation` request.
  ///  @since 3.6.0
  final DocumentColorClientCapabilities? colorProvider;

  /// Capabilities specific to the `textDocument/completion` request.
  final CompletionClientCapabilities? completion;

  /// Capabilities specific to the `textDocument/declaration` request.
  ///  @since 3.14.0
  final DeclarationClientCapabilities? declaration;

  /// Capabilities specific to the `textDocument/definition` request.
  final DefinitionClientCapabilities? definition;

  /// Capabilities specific to the diagnostic pull model.
  ///  @since 3.17.0
  final DiagnosticClientCapabilities? diagnostic;

  /// Capabilities specific to the `textDocument/documentHighlight` request.
  final DocumentHighlightClientCapabilities? documentHighlight;

  /// Capabilities specific to the `textDocument/documentLink` request.
  final DocumentLinkClientCapabilities? documentLink;

  /// Capabilities specific to the `textDocument/documentSymbol` request.
  final DocumentSymbolClientCapabilities? documentSymbol;

  /// Capabilities specific to the `textDocument/foldingRange` request.
  ///  @since 3.10.0
  final FoldingRangeClientCapabilities? foldingRange;

  /// Capabilities specific to the `textDocument/formatting` request.
  final DocumentFormattingClientCapabilities? formatting;

  /// Capabilities specific to the `textDocument/hover` request.
  final HoverClientCapabilities? hover;

  /// Capabilities specific to the `textDocument/implementation` request.
  ///  @since 3.6.0
  final ImplementationClientCapabilities? implementation;

  /// Capabilities specific to the `textDocument/inlayHint` request.
  ///  @since 3.17.0
  final InlayHintClientCapabilities? inlayHint;

  /// Capabilities specific to the `textDocument/inlineValue` request.
  ///  @since 3.17.0
  final InlineValueClientCapabilities? inlineValue;

  /// Capabilities specific to the `textDocument/linkedEditingRange` request.
  ///  @since 3.16.0
  final LinkedEditingRangeClientCapabilities? linkedEditingRange;

  /// Capabilities specific to the `textDocument/moniker` request.
  ///  @since 3.16.0
  final MonikerClientCapabilities? moniker;

  /// request. Capabilities specific to the `textDocument/onTypeFormatting`
  /// request.
  final DocumentOnTypeFormattingClientCapabilities? onTypeFormatting;

  /// Capabilities specific to the `textDocument/publishDiagnostics`
  /// notification.
  final PublishDiagnosticsClientCapabilities? publishDiagnostics;

  /// Capabilities specific to the `textDocument/rangeFormatting` request.
  final DocumentRangeFormattingClientCapabilities? rangeFormatting;

  /// Capabilities specific to the `textDocument/references` request.
  final ReferenceClientCapabilities? references;

  /// Capabilities specific to the `textDocument/rename` request.
  final RenameClientCapabilities? rename;

  /// Capabilities specific to the `textDocument/selectionRange` request.
  ///  @since 3.15.0
  final SelectionRangeClientCapabilities? selectionRange;

  /// Capabilities specific to the various semantic token requests.
  ///  @since 3.16.0
  final SemanticTokensClientCapabilities? semanticTokens;

  /// Capabilities specific to the `textDocument/signatureHelp` request.
  final SignatureHelpClientCapabilities? signatureHelp;
  final TextDocumentSyncClientCapabilities? synchronization;

  /// Capabilities specific to the `textDocument/typeDefinition` request.
  ///  @since 3.6.0
  final TypeDefinitionClientCapabilities? typeDefinition;

  /// Capabilities specific to the various type hierarchy requests.
  ///  @since 3.17.0
  final TypeHierarchyClientCapabilities? typeHierarchy;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (callHierarchy != null) {
      result['callHierarchy'] = callHierarchy?.toJson();
    }
    if (codeAction != null) {
      result['codeAction'] = codeAction?.toJson();
    }
    if (codeLens != null) {
      result['codeLens'] = codeLens?.toJson();
    }
    if (colorProvider != null) {
      result['colorProvider'] = colorProvider?.toJson();
    }
    if (completion != null) {
      result['completion'] = completion?.toJson();
    }
    if (declaration != null) {
      result['declaration'] = declaration?.toJson();
    }
    if (definition != null) {
      result['definition'] = definition?.toJson();
    }
    if (diagnostic != null) {
      result['diagnostic'] = diagnostic?.toJson();
    }
    if (documentHighlight != null) {
      result['documentHighlight'] = documentHighlight?.toJson();
    }
    if (documentLink != null) {
      result['documentLink'] = documentLink?.toJson();
    }
    if (documentSymbol != null) {
      result['documentSymbol'] = documentSymbol?.toJson();
    }
    if (foldingRange != null) {
      result['foldingRange'] = foldingRange?.toJson();
    }
    if (formatting != null) {
      result['formatting'] = formatting?.toJson();
    }
    if (hover != null) {
      result['hover'] = hover?.toJson();
    }
    if (implementation != null) {
      result['implementation'] = implementation?.toJson();
    }
    if (inlayHint != null) {
      result['inlayHint'] = inlayHint?.toJson();
    }
    if (inlineValue != null) {
      result['inlineValue'] = inlineValue?.toJson();
    }
    if (linkedEditingRange != null) {
      result['linkedEditingRange'] = linkedEditingRange?.toJson();
    }
    if (moniker != null) {
      result['moniker'] = moniker?.toJson();
    }
    if (onTypeFormatting != null) {
      result['onTypeFormatting'] = onTypeFormatting?.toJson();
    }
    if (publishDiagnostics != null) {
      result['publishDiagnostics'] = publishDiagnostics?.toJson();
    }
    if (rangeFormatting != null) {
      result['rangeFormatting'] = rangeFormatting?.toJson();
    }
    if (references != null) {
      result['references'] = references?.toJson();
    }
    if (rename != null) {
      result['rename'] = rename?.toJson();
    }
    if (selectionRange != null) {
      result['selectionRange'] = selectionRange?.toJson();
    }
    if (semanticTokens != null) {
      result['semanticTokens'] = semanticTokens?.toJson();
    }
    if (signatureHelp != null) {
      result['signatureHelp'] = signatureHelp?.toJson();
    }
    if (synchronization != null) {
      result['synchronization'] = synchronization?.toJson();
    }
    if (typeDefinition != null) {
      result['typeDefinition'] = typeDefinition?.toJson();
    }
    if (typeHierarchy != null) {
      result['typeHierarchy'] = typeHierarchy?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('callHierarchy');
      try {
        final callHierarchy = obj['callHierarchy'];
        if (callHierarchy != null &&
            !CallHierarchyClientCapabilities.canParse(
                callHierarchy, reporter)) {
          reporter
              .reportError('must be of type CallHierarchyClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeAction');
      try {
        final codeAction = obj['codeAction'];
        if (codeAction != null &&
            !CodeActionClientCapabilities.canParse(codeAction, reporter)) {
          reporter.reportError('must be of type CodeActionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeLens');
      try {
        final codeLens = obj['codeLens'];
        if (codeLens != null &&
            !CodeLensClientCapabilities.canParse(codeLens, reporter)) {
          reporter.reportError('must be of type CodeLensClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('colorProvider');
      try {
        final colorProvider = obj['colorProvider'];
        if (colorProvider != null &&
            !DocumentColorClientCapabilities.canParse(
                colorProvider, reporter)) {
          reporter
              .reportError('must be of type DocumentColorClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completion');
      try {
        final completion = obj['completion'];
        if (completion != null &&
            !CompletionClientCapabilities.canParse(completion, reporter)) {
          reporter.reportError('must be of type CompletionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('declaration');
      try {
        final declaration = obj['declaration'];
        if (declaration != null &&
            !DeclarationClientCapabilities.canParse(declaration, reporter)) {
          reporter.reportError('must be of type DeclarationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('definition');
      try {
        final definition = obj['definition'];
        if (definition != null &&
            !DefinitionClientCapabilities.canParse(definition, reporter)) {
          reporter.reportError('must be of type DefinitionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('diagnostic');
      try {
        final diagnostic = obj['diagnostic'];
        if (diagnostic != null &&
            !DiagnosticClientCapabilities.canParse(diagnostic, reporter)) {
          reporter.reportError('must be of type DiagnosticClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentHighlight');
      try {
        final documentHighlight = obj['documentHighlight'];
        if (documentHighlight != null &&
            !DocumentHighlightClientCapabilities.canParse(
                documentHighlight, reporter)) {
          reporter.reportError(
              'must be of type DocumentHighlightClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentLink');
      try {
        final documentLink = obj['documentLink'];
        if (documentLink != null &&
            !DocumentLinkClientCapabilities.canParse(documentLink, reporter)) {
          reporter
              .reportError('must be of type DocumentLinkClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSymbol');
      try {
        final documentSymbol = obj['documentSymbol'];
        if (documentSymbol != null &&
            !DocumentSymbolClientCapabilities.canParse(
                documentSymbol, reporter)) {
          reporter
              .reportError('must be of type DocumentSymbolClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRange');
      try {
        final foldingRange = obj['foldingRange'];
        if (foldingRange != null &&
            !FoldingRangeClientCapabilities.canParse(foldingRange, reporter)) {
          reporter
              .reportError('must be of type FoldingRangeClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('formatting');
      try {
        final formatting = obj['formatting'];
        if (formatting != null &&
            !DocumentFormattingClientCapabilities.canParse(
                formatting, reporter)) {
          reporter.reportError(
              'must be of type DocumentFormattingClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('hover');
      try {
        final hover = obj['hover'];
        if (hover != null &&
            !HoverClientCapabilities.canParse(hover, reporter)) {
          reporter.reportError('must be of type HoverClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('implementation');
      try {
        final implementation = obj['implementation'];
        if (implementation != null &&
            !ImplementationClientCapabilities.canParse(
                implementation, reporter)) {
          reporter
              .reportError('must be of type ImplementationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlayHint');
      try {
        final inlayHint = obj['inlayHint'];
        if (inlayHint != null &&
            !InlayHintClientCapabilities.canParse(inlayHint, reporter)) {
          reporter.reportError('must be of type InlayHintClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlineValue');
      try {
        final inlineValue = obj['inlineValue'];
        if (inlineValue != null &&
            !InlineValueClientCapabilities.canParse(inlineValue, reporter)) {
          reporter.reportError('must be of type InlineValueClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkedEditingRange');
      try {
        final linkedEditingRange = obj['linkedEditingRange'];
        if (linkedEditingRange != null &&
            !LinkedEditingRangeClientCapabilities.canParse(
                linkedEditingRange, reporter)) {
          reporter.reportError(
              'must be of type LinkedEditingRangeClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('moniker');
      try {
        final moniker = obj['moniker'];
        if (moniker != null &&
            !MonikerClientCapabilities.canParse(moniker, reporter)) {
          reporter.reportError('must be of type MonikerClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('onTypeFormatting');
      try {
        final onTypeFormatting = obj['onTypeFormatting'];
        if (onTypeFormatting != null &&
            !DocumentOnTypeFormattingClientCapabilities.canParse(
                onTypeFormatting, reporter)) {
          reporter.reportError(
              'must be of type DocumentOnTypeFormattingClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('publishDiagnostics');
      try {
        final publishDiagnostics = obj['publishDiagnostics'];
        if (publishDiagnostics != null &&
            !PublishDiagnosticsClientCapabilities.canParse(
                publishDiagnostics, reporter)) {
          reporter.reportError(
              'must be of type PublishDiagnosticsClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rangeFormatting');
      try {
        final rangeFormatting = obj['rangeFormatting'];
        if (rangeFormatting != null &&
            !DocumentRangeFormattingClientCapabilities.canParse(
                rangeFormatting, reporter)) {
          reporter.reportError(
              'must be of type DocumentRangeFormattingClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('references');
      try {
        final references = obj['references'];
        if (references != null &&
            !ReferenceClientCapabilities.canParse(references, reporter)) {
          reporter.reportError('must be of type ReferenceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rename');
      try {
        final rename = obj['rename'];
        if (rename != null &&
            !RenameClientCapabilities.canParse(rename, reporter)) {
          reporter.reportError('must be of type RenameClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRange');
      try {
        final selectionRange = obj['selectionRange'];
        if (selectionRange != null &&
            !SelectionRangeClientCapabilities.canParse(
                selectionRange, reporter)) {
          reporter
              .reportError('must be of type SelectionRangeClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('semanticTokens');
      try {
        final semanticTokens = obj['semanticTokens'];
        if (semanticTokens != null &&
            !SemanticTokensClientCapabilities.canParse(
                semanticTokens, reporter)) {
          reporter
              .reportError('must be of type SemanticTokensClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatureHelp');
      try {
        final signatureHelp = obj['signatureHelp'];
        if (signatureHelp != null &&
            !SignatureHelpClientCapabilities.canParse(
                signatureHelp, reporter)) {
          reporter
              .reportError('must be of type SignatureHelpClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('synchronization');
      try {
        final synchronization = obj['synchronization'];
        if (synchronization != null &&
            !TextDocumentSyncClientCapabilities.canParse(
                synchronization, reporter)) {
          reporter.reportError(
              'must be of type TextDocumentSyncClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeDefinition');
      try {
        final typeDefinition = obj['typeDefinition'];
        if (typeDefinition != null &&
            !TypeDefinitionClientCapabilities.canParse(
                typeDefinition, reporter)) {
          reporter
              .reportError('must be of type TypeDefinitionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeHierarchy');
      try {
        final typeHierarchy = obj['typeHierarchy'];
        if (typeHierarchy != null &&
            !TypeHierarchyClientCapabilities.canParse(
                typeHierarchy, reporter)) {
          reporter
              .reportError('must be of type TypeHierarchyClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentClientCapabilities &&
        other.runtimeType == TextDocumentClientCapabilities) {
      return callHierarchy == other.callHierarchy &&
          codeAction == other.codeAction &&
          codeLens == other.codeLens &&
          colorProvider == other.colorProvider &&
          completion == other.completion &&
          declaration == other.declaration &&
          definition == other.definition &&
          diagnostic == other.diagnostic &&
          documentHighlight == other.documentHighlight &&
          documentLink == other.documentLink &&
          documentSymbol == other.documentSymbol &&
          foldingRange == other.foldingRange &&
          formatting == other.formatting &&
          hover == other.hover &&
          implementation == other.implementation &&
          inlayHint == other.inlayHint &&
          inlineValue == other.inlineValue &&
          linkedEditingRange == other.linkedEditingRange &&
          moniker == other.moniker &&
          onTypeFormatting == other.onTypeFormatting &&
          publishDiagnostics == other.publishDiagnostics &&
          rangeFormatting == other.rangeFormatting &&
          references == other.references &&
          rename == other.rename &&
          selectionRange == other.selectionRange &&
          semanticTokens == other.semanticTokens &&
          signatureHelp == other.signatureHelp &&
          synchronization == other.synchronization &&
          typeDefinition == other.typeDefinition &&
          typeHierarchy == other.typeHierarchy &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hashAll([
        callHierarchy,
        codeAction,
        codeLens,
        colorProvider,
        completion,
        declaration,
        definition,
        diagnostic,
        documentHighlight,
        documentLink,
        documentSymbol,
        foldingRange,
        formatting,
        hover,
        implementation,
        inlayHint,
        inlineValue,
        linkedEditingRange,
        moniker,
        onTypeFormatting,
        publishDiagnostics,
        rangeFormatting,
        references,
        rename,
        selectionRange,
        semanticTokens,
        signatureHelp,
        synchronization,
        typeDefinition,
        typeHierarchy,
      ]);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentContentChangeEvent1 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentContentChangeEvent1.canParse,
    TextDocumentContentChangeEvent1.fromJson,
  );

  TextDocumentContentChangeEvent1({
    required this.range,
    this.rangeLength,
    required this.text,
  });
  static TextDocumentContentChangeEvent1 fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final rangeLengthJson = json['rangeLength'];
    final rangeLength = rangeLengthJson as int?;
    final textJson = json['text'];
    final text = textJson as String;
    return TextDocumentContentChangeEvent1(
      range: range,
      rangeLength: rangeLength,
      text: text,
    );
  }

  /// The range of the document that changed.
  final Range range;

  /// The optional length of the range that got replaced.
  ///  @deprecated use range instead.
  final int? rangeLength;

  /// The new text for the provided range.
  final String text;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    if (rangeLength != null) {
      result['rangeLength'] = rangeLength;
    }
    result['text'] = text;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rangeLength');
      try {
        final rangeLength = obj['rangeLength'];
        if (rangeLength != null && rangeLength is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final text = obj['text'];
        if (text == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (text is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentContentChangeEvent1');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['text'] = text;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final text = obj['text'];
        if (text == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (text is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentContentChangeEvent2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentContentChangeEvent2 &&
        other.runtimeType == TextDocumentContentChangeEvent2) {
      return text == other.text && true;
    }
    return false;
  }

  @override
  int get hashCode => text.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentEdit.canParse,
    TextDocumentEdit.fromJson,
  );

  TextDocumentEdit({
    required this.edits,
    required this.textDocument,
  });
  static TextDocumentEdit fromJson(Map<String, Object?> json) {
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map((item) => AnnotatedTextEdit.canParse(item, nullLspJsonReporter)
            ? Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>.t1(
                AnnotatedTextEdit.fromJson(item as Map<String, Object?>))
            : (SnippetTextEdit.canParse(item, nullLspJsonReporter)
                ? Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>.t2(
                    SnippetTextEdit.fromJson(item as Map<String, Object?>))
                : (TextEdit.canParse(item, nullLspJsonReporter)
                    ? Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>.t3(
                        TextEdit.fromJson(item as Map<String, Object?>))
                    : (throw '''$item was not one of (AnnotatedTextEdit, SnippetTextEdit, TextEdit)'''))))
        .toList();
    final textDocumentJson = json['textDocument'];
    final textDocument = OptionalVersionedTextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return TextDocumentEdit(
      edits: edits,
      textDocument: textDocument,
    );
  }

  /// The edits to be applied.
  ///  @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
  /// client capability `workspace.workspaceEdit.changeAnnotationSupport`
  final List<Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>> edits;

  /// The text document to change.
  final OptionalVersionedTextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['edits'] = edits;
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('edits');
      try {
        if (!obj.containsKey('edits')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final edits = obj['edits'];
        if (edits == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (edits is! List<Object?> ||
            edits.any((item) =>
                !AnnotatedTextEdit.canParse(item, reporter) &&
                !SnippetTextEdit.canParse(item, reporter) &&
                !TextEdit.canParse(item, reporter))) {
          reporter.reportError(
              'must be of type List<Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!OptionalVersionedTextDocumentIdentifier.canParse(
            textDocument, reporter)) {
          reporter.reportError(
              'must be of type OptionalVersionedTextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentEdit && other.runtimeType == TextDocumentEdit) {
      return listEqual(
              edits,
              other.edits,
              (Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit> a,
                      Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>
                          b) =>
                  a == b) &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(edits),
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentFilterWithScheme implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentFilterWithScheme.canParse,
    TextDocumentFilterWithScheme.fromJson,
  );

  TextDocumentFilterWithScheme({
    this.language,
    this.pattern,
    this.scheme,
  });
  static TextDocumentFilterWithScheme fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return TextDocumentFilterWithScheme(
      language: language,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// A language id, like `typescript`.
  final String? language;

  /// A glob pattern, like `*.{ts,js}`.
  ///
  /// Glob patterns can have the following syntax:
  /// - `*` to match one or more characters in a path segment
  /// - `?` to match on one character in a path segment
  /// - `**` to match any number of path segments, including none
  /// - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}`
  ///   matches all TypeScript and JavaScript files)
  /// - `[]` to declare a range of characters to match in a path segment
  ///   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
  /// - `[!...]` to negate a range of characters to match in a path segment
  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
  ///   not `example.0`)
  final String? pattern;

  /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (language != null) {
      result['language'] = language;
    }
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('language');
      try {
        final language = obj['language'];
        if (language != null && language is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('pattern');
      try {
        final pattern = obj['pattern'];
        if (pattern != null && pattern is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('scheme');
      try {
        final scheme = obj['scheme'];
        if (scheme != null && scheme is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentFilterWithScheme');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentFilterWithScheme &&
        other.runtimeType == TextDocumentFilterWithScheme) {
      return language == other.language &&
          pattern == other.pattern &&
          scheme == other.scheme &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        language,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentIdentifier.canParse,
    TextDocumentIdentifier.fromJson,
  );

  TextDocumentIdentifier({
    required this.uri,
  });
  static TextDocumentIdentifier fromJson(Map<String, Object?> json) {
    if (VersionedTextDocumentIdentifier.canParse(json, nullLspJsonReporter)) {
      return VersionedTextDocumentIdentifier.fromJson(json);
    }
    if (OptionalVersionedTextDocumentIdentifier.canParse(
        json, nullLspJsonReporter)) {
      return OptionalVersionedTextDocumentIdentifier.fromJson(json);
    }
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return TextDocumentIdentifier(
      uri: uri,
    );
  }

  /// The text document's URI.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentIdentifier &&
        other.runtimeType == TextDocumentIdentifier) {
      return uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentItem.canParse,
    TextDocumentItem.fromJson,
  );

  TextDocumentItem({
    required this.languageId,
    required this.text,
    required this.uri,
    required this.version,
  });
  static TextDocumentItem fromJson(Map<String, Object?> json) {
    final languageIdJson = json['languageId'];
    final languageId = languageIdJson as String;
    final textJson = json['text'];
    final text = textJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return TextDocumentItem(
      languageId: languageId,
      text: text,
      uri: uri,
      version: version,
    );
  }

  /// The text document's language identifier.
  final String languageId;

  /// The content of the opened text document.
  final String text;

  /// The text document's URI.
  final String uri;

  /// The version number of this document (it will increase after each change,
  /// including undo/redo).
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['languageId'] = languageId;
    result['text'] = text;
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('languageId');
      try {
        if (!obj.containsKey('languageId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final languageId = obj['languageId'];
        if (languageId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (languageId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final text = obj['text'];
        if (text == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (text is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentItem && other.runtimeType == TextDocumentItem) {
      return languageId == other.languageId &&
          text == other.text &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        languageId,
        text,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentPositionParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentPositionParams.canParse,
    TextDocumentPositionParams.fromJson,
  );

  TextDocumentPositionParams({
    required this.position,
    required this.textDocument,
  });
  static TextDocumentPositionParams fromJson(Map<String, Object?> json) {
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (RenameParams.canParse(json, nullLspJsonReporter)) {
      return RenameParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
      return PrepareRenameParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (TypeHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyPrepareParams.fromJson(json);
    }
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return TextDocumentPositionParams(
      position: position,
      textDocument: textDocument,
    );
  }

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentPositionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentPositionParams &&
        other.runtimeType == TextDocumentPositionParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// General text document registration options.
class TextDocumentRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentRegistrationOptions.canParse,
    TextDocumentRegistrationOptions.fromJson,
  );

  TextDocumentRegistrationOptions({
    this.documentSelector,
  });
  static TextDocumentRegistrationOptions fromJson(Map<String, Object?> json) {
    if (TextDocumentChangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentChangeRegistrationOptions.fromJson(json);
    }
    if (TextDocumentSaveRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentSaveRegistrationOptions.fromJson(json);
    }
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (CodeActionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionRegistrationOptions.fromJson(json);
    }
    if (CodeLensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensRegistrationOptions.fromJson(json);
    }
    if (CompletionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionRegistrationOptions.fromJson(json);
    }
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (DefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionRegistrationOptions.fromJson(json);
    }
    if (DiagnosticRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (DocumentFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentHighlightRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentHighlightRegistrationOptions.fromJson(json);
    }
    if (DocumentLinkRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkRegistrationOptions.fromJson(json);
    }
    if (DocumentOnTypeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentRangeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentRangeFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.fromJson(json);
    }
    if (ReferenceRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceRegistrationOptions.fromJson(json);
    }
    if (RenameRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return RenameRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    return TextDocumentRegistrationOptions(
      documentSelector: documentSelector,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<TextDocumentFilterWithScheme>? documentSelector;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentRegistrationOptions &&
        other.runtimeType == TextDocumentRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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 implements ToJsonable {
  const TextDocumentSaveReason(this._value);
  const TextDocumentSaveReason.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Automatic after a delay.
  static const AfterDelay = TextDocumentSaveReason(2);

  /// When the editor lost focus.
  static const FocusOut = TextDocumentSaveReason(3);

  /// Manually triggered, e.g. by the user pressing save, by starting debugging,
  /// or by an API call.
  static const Manual = TextDocumentSaveReason(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TextDocumentSaveReason && other._value == _value;
}

class TextDocumentSaveRegistrationOptions
    implements TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentSaveRegistrationOptions.canParse,
    TextDocumentSaveRegistrationOptions.fromJson,
  );

  TextDocumentSaveRegistrationOptions({
    this.documentSelector,
    this.includeText,
  });
  static TextDocumentSaveRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final includeTextJson = json['includeText'];
    final includeText = includeTextJson as bool?;
    return TextDocumentSaveRegistrationOptions(
      documentSelector: documentSelector,
      includeText: includeText,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The client is supposed to include the content on save.
  final bool? includeText;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (includeText != null) {
      result['includeText'] = includeText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('includeText');
      try {
        final includeText = obj['includeText'];
        if (includeText != null && includeText is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type TextDocumentSaveRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentSaveRegistrationOptions &&
        other.runtimeType == TextDocumentSaveRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          includeText == other.includeText &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        includeText,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentSyncClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentSyncClientCapabilities.canParse,
    TextDocumentSyncClientCapabilities.fromJson,
  );

  TextDocumentSyncClientCapabilities({
    this.didSave,
    this.dynamicRegistration,
    this.willSave,
    this.willSaveWaitUntil,
  });
  static TextDocumentSyncClientCapabilities fromJson(
      Map<String, Object?> json) {
    final didSaveJson = json['didSave'];
    final didSave = didSaveJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final willSaveJson = json['willSave'];
    final willSave = willSaveJson as bool?;
    final willSaveWaitUntilJson = json['willSaveWaitUntil'];
    final willSaveWaitUntil = willSaveWaitUntilJson as bool?;
    return TextDocumentSyncClientCapabilities(
      didSave: didSave,
      dynamicRegistration: dynamicRegistration,
      willSave: willSave,
      willSaveWaitUntil: willSaveWaitUntil,
    );
  }

  /// The client supports did save notifications.
  final bool? didSave;

  /// Whether text document synchronization supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports sending will save notifications.
  final bool? willSave;

  /// The client supports sending a will save request and waits for a response
  /// providing text edits which will be applied to the document before it is
  /// saved.
  final bool? willSaveWaitUntil;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (didSave != null) {
      result['didSave'] = didSave;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (willSave != null) {
      result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('didSave');
      try {
        final didSave = obj['didSave'];
        if (didSave != null && didSave is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSave');
      try {
        final willSave = obj['willSave'];
        if (willSave != null && willSave is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSaveWaitUntil');
      try {
        final willSaveWaitUntil = obj['willSaveWaitUntil'];
        if (willSaveWaitUntil != null && willSaveWaitUntil is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type TextDocumentSyncClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentSyncClientCapabilities &&
        other.runtimeType == TextDocumentSyncClientCapabilities) {
      return didSave == other.didSave &&
          dynamicRegistration == other.dynamicRegistration &&
          willSave == other.willSave &&
          willSaveWaitUntil == other.willSaveWaitUntil &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        didSave,
        dynamicRegistration,
        willSave,
        willSaveWaitUntil,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines how the host (editor) should sync document changes to the language
/// server.
class TextDocumentSyncKind implements ToJsonable {
  const TextDocumentSyncKind(this._value);
  const TextDocumentSyncKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Documents are synced by always sending the full content of the document.
  static const Full = TextDocumentSyncKind(1);

  /// Documents are synced by sending the full content on open. After that only
  /// incremental updates to the document are send.
  static const Incremental = TextDocumentSyncKind(2);

  /// Documents should not be synced at all.
  static const None = TextDocumentSyncKind(0);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TextDocumentSyncKind && other._value == _value;
}

class TextDocumentSyncOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentSyncOptions.canParse,
    TextDocumentSyncOptions.fromJson,
  );

  TextDocumentSyncOptions({
    this.change,
    this.openClose,
    this.save,
    this.willSave,
    this.willSaveWaitUntil,
  });
  static TextDocumentSyncOptions fromJson(Map<String, Object?> json) {
    final changeJson = json['change'];
    final change = changeJson != null
        ? TextDocumentSyncKind.fromJson(changeJson as int)
        : null;
    final openCloseJson = json['openClose'];
    final openClose = openCloseJson as bool?;
    final saveJson = json['save'];
    final save = saveJson == null
        ? null
        : (saveJson is bool
            ? Either2<bool, SaveOptions>.t1(saveJson)
            : (SaveOptions.canParse(saveJson, nullLspJsonReporter)
                ? Either2<bool, SaveOptions>.t2(
                    SaveOptions.fromJson(saveJson as Map<String, Object?>))
                : (throw '''$saveJson was not one of (bool, SaveOptions)''')));
    final willSaveJson = json['willSave'];
    final willSave = willSaveJson as bool?;
    final willSaveWaitUntilJson = json['willSaveWaitUntil'];
    final willSaveWaitUntil = willSaveWaitUntilJson as bool?;
    return TextDocumentSyncOptions(
      change: change,
      openClose: openClose,
      save: save,
      willSave: willSave,
      willSaveWaitUntil: willSaveWaitUntil,
    );
  }

  /// Change notifications are sent to the server. See
  /// TextDocumentSyncKind.None, TextDocumentSyncKind.Full and
  /// TextDocumentSyncKind.Incremental. If omitted it defaults to
  /// TextDocumentSyncKind.None.
  final TextDocumentSyncKind? change;

  /// Open and close notifications are sent to the server. If omitted open close
  /// notification should not be sent.
  final bool? openClose;

  /// If present save notifications are sent to the server. If omitted the
  /// notification should not be sent.
  final Either2<bool, SaveOptions>? save;

  /// If present will save notifications are sent to the server. If omitted the
  /// notification should not be sent.
  final bool? willSave;

  /// If present will save wait until requests are sent to the server. If
  /// omitted the request should not be sent.
  final bool? willSaveWaitUntil;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (change != null) {
      result['change'] = change?.toJson();
    }
    if (openClose != null) {
      result['openClose'] = openClose;
    }
    if (save != null) {
      result['save'] = save;
    }
    if (willSave != null) {
      result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('change');
      try {
        final change = obj['change'];
        if (change != null &&
            !TextDocumentSyncKind.canParse(change, reporter)) {
          reporter.reportError('must be of type TextDocumentSyncKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('openClose');
      try {
        final openClose = obj['openClose'];
        if (openClose != null && openClose is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('save');
      try {
        final save = obj['save'];
        if (save != null &&
            save is! bool &&
            !SaveOptions.canParse(save, reporter)) {
          reporter.reportError('must be of type Either2<bool, SaveOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSave');
      try {
        final willSave = obj['willSave'];
        if (willSave != null && willSave is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSaveWaitUntil');
      try {
        final willSaveWaitUntil = obj['willSaveWaitUntil'];
        if (willSaveWaitUntil != null && willSaveWaitUntil is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentSyncOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentSyncOptions &&
        other.runtimeType == TextDocumentSyncOptions) {
      return change == other.change &&
          openClose == other.openClose &&
          save == other.save &&
          willSave == other.willSave &&
          willSaveWaitUntil == other.willSaveWaitUntil &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        change,
        openClose,
        save,
        willSave,
        willSaveWaitUntil,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextEdit.canParse,
    TextEdit.fromJson,
  );

  TextEdit({
    required this.newText,
    required this.range,
  });
  static TextEdit fromJson(Map<String, Object?> json) {
    if (AnnotatedTextEdit.canParse(json, nullLspJsonReporter)) {
      return AnnotatedTextEdit.fromJson(json);
    }
    if (SnippetTextEdit.canParse(json, nullLspJsonReporter)) {
      return SnippetTextEdit.fromJson(json);
    }
    final newTextJson = json['newText'];
    final newText = newTextJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return TextEdit(
      newText: newText,
      range: range,
    );
  }

  /// The string to be inserted. For delete operations use an empty string.
  final String newText;

  /// The range of the text document to be manipulated. To insert text into a
  /// document create a range where start === end.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['newText'] = newText;
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('newText');
      try {
        if (!obj.containsKey('newText')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final newText = obj['newText'];
        if (newText == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (newText is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextEdit && other.runtimeType == TextEdit) {
      return newText == other.newText && range == other.range && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        newText,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TokenFormat implements ToJsonable {
  const TokenFormat(this._value);
  const TokenFormat.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  static const Relative = TokenFormat('relative');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TokenFormat && other._value == _value;
}

class TypeDefinitionClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionClientCapabilities.canParse,
    TypeDefinitionClientCapabilities.fromJson,
  );

  TypeDefinitionClientCapabilities({
    this.dynamicRegistration,
    this.linkSupport,
  });
  static TypeDefinitionClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final linkSupportJson = json['linkSupport'];
    final linkSupport = linkSupportJson as bool?;
    return TypeDefinitionClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      linkSupport: linkSupport,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `TypeDefinitionRegistrationOptions`
  /// return value for the corresponding server capability as well.
  final bool? dynamicRegistration;

  /// The client supports additional metadata in the form of definition links.
  ///  @since 3.14.0
  final bool? linkSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (linkSupport != null) {
      result['linkSupport'] = linkSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        final linkSupport = obj['linkSupport'];
        if (linkSupport != null && linkSupport is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionParams.canParse,
    TypeDefinitionParams.fromJson,
  );

  TypeDefinitionParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static TypeDefinitionParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return TypeDefinitionParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeDefinitionParams &&
        other.runtimeType == TypeDefinitionParams) {
      return partialResultToken == other.partialResultToken &&
          position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeDefinitionRegistrationOptions
    implements
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        TypeDefinitionOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionRegistrationOptions.canParse,
    TypeDefinitionRegistrationOptions.fromJson,
  );

  TypeDefinitionRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static TypeDefinitionRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeDefinitionRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeDefinitionRegistrationOptions &&
        other.runtimeType == TypeDefinitionRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme 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 TypeHierarchyClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyClientCapabilities.canParse,
    TypeHierarchyClientCapabilities.fromJson,
  );

  TypeHierarchyClientCapabilities({
    this.dynamicRegistration,
  });
  static TypeHierarchyClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return TypeHierarchyClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchyClientCapabilities &&
        other.runtimeType == TypeHierarchyClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration && true;
    }
    return false;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeHierarchyItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyItem.canParse,
    TypeHierarchyItem.fromJson,
  );

  TypeHierarchyItem({
    this.data,
    this.detail,
    required this.kind,
    required this.name,
    required this.range,
    required this.selectionRange,
    this.tags,
    required this.uri,
  });
  static TypeHierarchyItem fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final nameJson = json['name'];
    final name = nameJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final selectionRangeJson = json['selectionRange'];
    final selectionRange =
        Range.fromJson(selectionRangeJson as Map<String, Object?>);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return TypeHierarchyItem(
      data: data,
      detail: detail,
      kind: kind,
      name: name,
      range: range,
      selectionRange: selectionRange,
      tags: tags,
      uri: uri,
    );
  }

  /// A data entry field that is preserved between a type hierarchy prepare and
  /// supertypes or subtypes requests. It could also be used to identify the
  /// type hierarchy in the server, helping improve the performance on resolving
  /// supertypes and subtypes.
  final Object? data;

  /// More detail for this item, e.g. the signature of a function.
  final String? detail;

  /// The kind of this item.
  final SymbolKind kind;

  /// The name of this item.
  final String name;

  /// The range enclosing this symbol not including leading/trailing whitespace
  /// but everything else, e.g. comments and code.
  final Range range;

  /// The range that should be selected and revealed when this symbol is being
  /// picked, e.g. the name of a function. Must be contained by the
  /// [`range`](#TypeHierarchyItem.range).
  final Range selectionRange;

  /// Tags for this item.
  final List<SymbolTag>? tags;

  /// The resource identifier of this item.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    if (detail != null) {
      result['detail'] = detail;
    }
    result['kind'] = kind.toJson();
    result['name'] = name;
    result['range'] = range.toJson();
    result['selectionRange'] = selectionRange.toJson();
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('detail');
      try {
        final detail = obj['detail'];
        if (detail != null && detail is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final range = obj['range'];
        if (range == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(range, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRange');
      try {
        if (!obj.containsKey('selectionRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final selectionRange = obj['selectionRange'];
        if (selectionRange == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Range.canParse(selectionRange, reporter)) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchyItem && other.runtimeType == TypeHierarchyItem) {
      return data == other.data &&
          detail == other.detail &&
          kind == other.kind &&
          name == other.name &&
          range == other.range &&
          selectionRange == other.selectionRange &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          uri == other.uri &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        data,
        detail,
        kind,
        name,
        range,
        selectionRange,
        lspHashCode(tags),
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeHierarchyOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyOptions.canParse,
    TypeHierarchyOptions.fromJson,
  );

  TypeHierarchyOptions({
    this.workDoneProgress,
  });
  static TypeHierarchyOptions fromJson(Map<String, Object?> json) {
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeHierarchyOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchyOptions &&
        other.runtimeType == TypeHierarchyOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeHierarchyPrepareParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyPrepareParams.canParse,
    TypeHierarchyPrepareParams.fromJson,
  );

  TypeHierarchyPrepareParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static TypeHierarchyPrepareParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return TypeHierarchyPrepareParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final position = obj['position'];
        if (position == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Position.canParse(position, reporter)) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyPrepareParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchyPrepareParams &&
        other.runtimeType == TypeHierarchyPrepareParams) {
      return position == other.position &&
          textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeHierarchyRegistrationOptions
    implements
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        TypeHierarchyOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyRegistrationOptions.canParse,
    TypeHierarchyRegistrationOptions.fromJson,
  );

  TypeHierarchyRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static TypeHierarchyRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeHierarchyRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final documentSelector = obj['documentSelector'];
        if (documentSelector != null &&
            (documentSelector is! List<Object?> ||
                documentSelector.any((item) =>
                    !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<TextDocumentFilterWithScheme>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        final id = obj['id'];
        if (id != null && id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchyRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchyRegistrationOptions &&
        other.runtimeType == TypeHierarchyRegistrationOptions) {
      return listEqual(
              documentSelector,
              other.documentSelector,
              (TextDocumentFilterWithScheme a,
                      TextDocumentFilterWithScheme b) =>
                  a == b) &&
          id == other.id &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeHierarchySubtypesParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchySubtypesParams.canParse,
    TypeHierarchySubtypesParams.fromJson,
  );

  TypeHierarchySubtypesParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static TypeHierarchySubtypesParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = TypeHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return TypeHierarchySubtypesParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final TypeHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['item'] = item.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('item');
      try {
        if (!obj.containsKey('item')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final item = obj['item'];
        if (item == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TypeHierarchyItem.canParse(item, reporter)) {
          reporter.reportError('must be of type TypeHierarchyItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchySubtypesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchySubtypesParams &&
        other.runtimeType == TypeHierarchySubtypesParams) {
      return item == other.item &&
          partialResultToken == other.partialResultToken &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        item,
        partialResultToken,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeHierarchySupertypesParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchySupertypesParams.canParse,
    TypeHierarchySupertypesParams.fromJson,
  );

  TypeHierarchySupertypesParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static TypeHierarchySupertypesParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = TypeHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return TypeHierarchySupertypesParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final TypeHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['item'] = item.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('item');
      try {
        if (!obj.containsKey('item')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final item = obj['item'];
        if (item == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TypeHierarchyItem.canParse(item, reporter)) {
          reporter.reportError('must be of type TypeHierarchyItem');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeHierarchySupertypesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeHierarchySupertypesParams &&
        other.runtimeType == TypeHierarchySupertypesParams) {
      return item == other.item &&
          partialResultToken == other.partialResultToken &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        item,
        partialResultToken,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A diagnostic report indicating that the last returned report is still
/// accurate.
///  @since 3.17.0
class UnchangedDocumentDiagnosticReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    UnchangedDocumentDiagnosticReport.canParse,
    UnchangedDocumentDiagnosticReport.fromJson,
  );

  UnchangedDocumentDiagnosticReport({
    this.kind = 'unchanged',
    required this.resultId,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static UnchangedDocumentDiagnosticReport fromJson(Map<String, Object?> json) {
    if (WorkspaceUnchangedDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceUnchangedDocumentDiagnosticReport.fromJson(json);
    }
    if (RelatedUnchangedDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return RelatedUnchangedDocumentDiagnosticReport.fromJson(json);
    }
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    return UnchangedDocumentDiagnosticReport(
      kind: kind,
      resultId: resultId,
    );
  }

  /// A document diagnostic report indicating no changes to the last result. A
  /// server can only return `unchanged` if result ids are provided.
  final String kind;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  final String resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    result['resultId'] = resultId;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'unchanged') {
          reporter.reportError('must be the literal \'unchanged\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        if (!obj.containsKey('resultId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final resultId = obj['resultId'];
        if (resultId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type UnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is UnchangedDocumentDiagnosticReport &&
        other.runtimeType == UnchangedDocumentDiagnosticReport) {
      return kind == other.kind && resultId == other.resultId && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Moniker uniqueness level to define scope of the moniker.
class UniquenessLevel implements ToJsonable {
  const UniquenessLevel(this._value);
  const UniquenessLevel.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// The moniker is only unique inside a document
  static const document = UniquenessLevel('document');

  /// The moniker is globally unique
  static const global = UniquenessLevel('global');

  /// The moniker is unique inside the group to which a project belongs
  static const group = UniquenessLevel('group');

  /// The moniker is unique inside a project for which a dump got created
  static const project = UniquenessLevel('project');

  /// The moniker is unique inside the moniker scheme.
  static const scheme = UniquenessLevel('scheme');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is UniquenessLevel && other._value == _value;
}

/// General parameters to unregister a 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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['id'] = id;
    result['method'] = method;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final id = obj['id'];
        if (id == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (id is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('method');
      try {
        if (!obj.containsKey('method')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final method = obj['method'];
        if (method == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (method is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Unregistration');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['unregisterations'] =
        unregisterations.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('unregisterations');
      try {
        if (!obj.containsKey('unregisterations')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final unregisterations = obj['unregisterations'];
        if (unregisterations == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (unregisterations is! List<Object?> ||
            unregisterations
                .any((item) => !Unregistration.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Unregistration>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type UnregistrationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is UnregistrationParams &&
        other.runtimeType == UnregistrationParams) {
      return listEqual(unregisterations, other.unregisterations,
              (Unregistration a, Unregistration b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(unregisterations);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A versioned notebook document identifier.
///  @since 3.17.0
class VersionedNotebookDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    VersionedNotebookDocumentIdentifier.canParse,
    VersionedNotebookDocumentIdentifier.fromJson,
  );

  VersionedNotebookDocumentIdentifier({
    required this.uri,
    required this.version,
  });
  static VersionedNotebookDocumentIdentifier fromJson(
      Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return VersionedNotebookDocumentIdentifier(
      uri: uri,
      version: version,
    );
  }

  /// The notebook document's uri.
  final String uri;

  /// The version number of this notebook document.
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type VersionedNotebookDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is VersionedNotebookDocumentIdentifier &&
        other.runtimeType == VersionedNotebookDocumentIdentifier) {
      return uri == other.uri && version == other.version && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class VersionedTextDocumentIdentifier
    implements TextDocumentIdentifier, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    VersionedTextDocumentIdentifier.canParse,
    VersionedTextDocumentIdentifier.fromJson,
  );

  VersionedTextDocumentIdentifier({
    required this.uri,
    required this.version,
  });
  static VersionedTextDocumentIdentifier fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return VersionedTextDocumentIdentifier(
      uri: uri,
      version: version,
    );
  }

  /// The text document's URI.
  @override
  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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type VersionedTextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is VersionedTextDocumentIdentifier &&
        other.runtimeType == VersionedTextDocumentIdentifier) {
      return uri == other.uri && version == other.version && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WatchKind implements ToJsonable {
  const WatchKind(this._value);
  const WatchKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    return obj is int;
  }

  /// Interested in change events
  static const Change = WatchKind(2);

  /// Interested in create events.
  static const Create = WatchKind(1);

  /// Interested in delete events
  static const Delete = WatchKind(4);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is WatchKind && other._value == _value;
}

/// The parameters send in a will save text document notification.
class WillSaveTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WillSaveTextDocumentParams.canParse,
    WillSaveTextDocumentParams.fromJson,
  );

  WillSaveTextDocumentParams({
    required this.reason,
    required this.textDocument,
  });
  static WillSaveTextDocumentParams fromJson(Map<String, Object?> json) {
    final reasonJson = json['reason'];
    final reason = TextDocumentSaveReason.fromJson(reasonJson as int);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return WillSaveTextDocumentParams(
      reason: reason,
      textDocument: textDocument,
    );
  }

  /// The 'TextDocumentSaveReason'.
  final TextDocumentSaveReason reason;

  /// The document that will be saved.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['reason'] = reason.toJson();
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('reason');
      try {
        if (!obj.containsKey('reason')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final reason = obj['reason'];
        if (reason == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentSaveReason.canParse(reason, reporter)) {
          reporter.reportError('must be of type TextDocumentSaveReason');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final textDocument = obj['textDocument'];
        if (textDocument == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!TextDocumentIdentifier.canParse(textDocument, reporter)) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WillSaveTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WillSaveTextDocumentParams &&
        other.runtimeType == WillSaveTextDocumentParams) {
      return reason == other.reason &&
          textDocument == other.textDocument &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        reason,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WindowClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WindowClientCapabilities.canParse,
    WindowClientCapabilities.fromJson,
  );

  WindowClientCapabilities({
    this.showDocument,
    this.showMessage,
    this.workDoneProgress,
  });
  static WindowClientCapabilities fromJson(Map<String, Object?> json) {
    final showDocumentJson = json['showDocument'];
    final showDocument = showDocumentJson != null
        ? ShowDocumentClientCapabilities.fromJson(
            showDocumentJson as Map<String, Object?>)
        : null;
    final showMessageJson = json['showMessage'];
    final showMessage = showMessageJson != null
        ? ShowMessageRequestClientCapabilities.fromJson(
            showMessageJson as Map<String, Object?>)
        : null;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WindowClientCapabilities(
      showDocument: showDocument,
      showMessage: showMessage,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Client capabilities for the show document request.
  ///  @since 3.16.0
  final ShowDocumentClientCapabilities? showDocument;

  /// Capabilities specific to the showMessage request
  ///  @since 3.16.0
  final ShowMessageRequestClientCapabilities? showMessage;

  /// It indicates whether the client supports server initiated progress using
  /// the `window/workDoneProgress/create` request.
  ///
  /// The capability also controls Whether client supports handling of progress
  /// notifications. If set servers are allowed to report a `workDoneProgress`
  /// property in the request specific server capabilities.
  ///  @since 3.15.0
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (showDocument != null) {
      result['showDocument'] = showDocument?.toJson();
    }
    if (showMessage != null) {
      result['showMessage'] = showMessage?.toJson();
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('showDocument');
      try {
        final showDocument = obj['showDocument'];
        if (showDocument != null &&
            !ShowDocumentClientCapabilities.canParse(showDocument, reporter)) {
          reporter
              .reportError('must be of type ShowDocumentClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('showMessage');
      try {
        final showMessage = obj['showMessage'];
        if (showMessage != null &&
            !ShowMessageRequestClientCapabilities.canParse(
                showMessage, reporter)) {
          reporter.reportError(
              'must be of type ShowMessageRequestClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WindowClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WindowClientCapabilities &&
        other.runtimeType == WindowClientCapabilities) {
      return showDocument == other.showDocument &&
          showMessage == other.showMessage &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        showDocument,
        showMessage,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressBegin implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressBegin.canParse,
    WorkDoneProgressBegin.fromJson,
  );

  WorkDoneProgressBegin({
    this.cancellable,
    this.kind = 'begin',
    this.message,
    this.percentage,
    required this.title,
  }) {
    if (kind != 'begin') {
      throw 'kind may only be the literal \'begin\'';
    }
  }
  static WorkDoneProgressBegin fromJson(Map<String, Object?> json) {
    final cancellableJson = json['cancellable'];
    final cancellable = cancellableJson as bool?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final messageJson = json['message'];
    final message = messageJson as String?;
    final percentageJson = json['percentage'];
    final percentage = percentageJson as int?;
    final titleJson = json['title'];
    final title = titleJson as String;
    return WorkDoneProgressBegin(
      cancellable: cancellable,
      kind: kind,
      message: message,
      percentage: percentage,
      title: title,
    );
  }

  /// Controls if a cancel button should show to allow the user to cancel the
  /// long running operation. Clients that don't support cancellation are
  /// allowed to ignore the setting.
  final bool? cancellable;
  final String kind;

  /// Optional, more detailed associated progress message. Contains
  /// complementary information to the `title`.
  ///
  /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". If
  /// unset, the previous progress message (if any) is still valid.
  final String? message;

  /// Optional progress percentage to display (value 100 is considered 100%). If
  /// not provided infinite progress is assumed and clients are allowed to
  /// ignore the `percentage` value in subsequent in report notifications.
  ///
  /// The value should be steadily rising. Clients are free to ignore values
  /// that are not following this rule. The value range is [0, 100]
  final int? percentage;

  /// Mandatory title of the progress operation. Used to briefly inform about
  /// the kind of operation being performed.
  ///
  /// Examples: "Indexing" or "Linking dependencies".
  final String title;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cancellable != null) {
      result['cancellable'] = cancellable;
    }
    result['kind'] = kind;
    if (message != null) {
      result['message'] = message;
    }
    if (percentage != null) {
      result['percentage'] = percentage;
    }
    result['title'] = title;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cancellable');
      try {
        final cancellable = obj['cancellable'];
        if (cancellable != null && cancellable is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'begin') {
          reporter.reportError('must be the literal \'begin\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        final message = obj['message'];
        if (message != null && message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('percentage');
      try {
        final percentage = obj['percentage'];
        if (percentage != null && percentage is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('title');
      try {
        if (!obj.containsKey('title')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final title = obj['title'];
        if (title == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (title is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressBegin');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkDoneProgressBegin &&
        other.runtimeType == WorkDoneProgressBegin) {
      return cancellable == other.cancellable &&
          kind == other.kind &&
          message == other.message &&
          percentage == other.percentage &&
          title == other.title &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        cancellable,
        kind,
        message,
        percentage,
        title,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressCancelParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressCancelParams.canParse,
    WorkDoneProgressCancelParams.fromJson,
  );

  WorkDoneProgressCancelParams({
    required this.token,
  });
  static WorkDoneProgressCancelParams fromJson(Map<String, Object?> json) {
    final tokenJson = json['token'];
    final token = tokenJson is int
        ? Either2<int, String>.t1(tokenJson)
        : (tokenJson is String
            ? Either2<int, String>.t2(tokenJson)
            : (throw '''$tokenJson was not one of (int, String)'''));
    return WorkDoneProgressCancelParams(
      token: token,
    );
  }

  /// The token to be used to report progress.
  final Either2<int, String> token;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['token'] = token;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('token');
      try {
        if (!obj.containsKey('token')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final token = obj['token'];
        if (token == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (token is! int && token is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressCancelParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['token'] = token;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('token');
      try {
        if (!obj.containsKey('token')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final token = obj['token'];
        if (token == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (token is! int && token is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressCreateParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    if (message != null) {
      result['message'] = message;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'end') {
          reporter.reportError('must be the literal \'end\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        final message = obj['message'];
        if (message != null && message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressEnd');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 (DiagnosticOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticOptions.fromJson(json);
    }
    if (SemanticTokensOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensOptions.fromJson(json);
    }
    if (ExecuteCommandOptions.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandOptions.fromJson(json);
    }
    if (CompletionOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionOptions.fromJson(json);
    }
    if (CodeActionOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionOptions.fromJson(json);
    }
    if (SignatureHelpOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpOptions.fromJson(json);
    }
    if (CodeLensOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensOptions.fromJson(json);
    }
    if (DocumentLinkOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkOptions.fromJson(json);
    }
    if (DocumentSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolOptions.fromJson(json);
    }
    if (InlayHintOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintOptions.fromJson(json);
    }
    if (RenameOptions.canParse(json, nullLspJsonReporter)) {
      return RenameOptions.fromJson(json);
    }
    if (WorkspaceSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolOptions.fromJson(json);
    }
    if (CallHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOptions.fromJson(json);
    }
    if (DeclarationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationOptions.fromJson(json);
    }
    if (DefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionOptions.fromJson(json);
    }
    if (DocumentColorOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorOptions.fromJson(json);
    }
    if (DocumentFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingOptions.fromJson(json);
    }
    if (DocumentHighlightOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightOptions.fromJson(json);
    }
    if (DocumentRangeFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingOptions.fromJson(json);
    }
    if (FoldingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeOptions.fromJson(json);
    }
    if (HoverOptions.canParse(json, nullLspJsonReporter)) {
      return HoverOptions.fromJson(json);
    }
    if (ImplementationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationOptions.fromJson(json);
    }
    if (InlineValueOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueOptions.fromJson(json);
    }
    if (LinkedEditingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeOptions.fromJson(json);
    }
    if (MonikerOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerOptions.fromJson(json);
    }
    if (ReferenceOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceOptions.fromJson(json);
    }
    if (SelectionRangeOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeOptions.fromJson(json);
    }
    if (TypeDefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionOptions.fromJson(json);
    }
    if (TypeHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkDoneProgressOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    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 (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (DocumentRangeFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingParams.fromJson(json);
    }
    if (InlineValueParams.canParse(json, nullLspJsonReporter)) {
      return InlineValueParams.fromJson(json);
    }
    if (DocumentFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingParams.fromJson(json);
    }
    if (InlayHintParams.canParse(json, nullLspJsonReporter)) {
      return InlayHintParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (InitializeParams.canParse(json, nullLspJsonReporter)) {
      return InitializeParams.fromJson(json);
    }
    if (DocumentDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return DocumentDiagnosticParams.fromJson(json);
    }
    if (ExecuteCommandParams.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandParams.fromJson(json);
    }
    if (WorkspaceDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceDiagnosticParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (RenameParams.canParse(json, nullLspJsonReporter)) {
      return RenameParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (TypeHierarchySubtypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySubtypesParams.fromJson(json);
    }
    if (TypeHierarchySupertypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySupertypesParams.fromJson(json);
    }
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
      return PrepareRenameParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (TypeHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyPrepareParams.fromJson(json);
    }
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return WorkDoneProgressParams(
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report work done progress.
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkDoneProgressParams &&
        other.runtimeType == WorkDoneProgressParams) {
      return workDoneToken == other.workDoneToken && true;
    }
    return false;
  }

  @override
  int get hashCode => workDoneToken.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressReport.canParse,
    WorkDoneProgressReport.fromJson,
  );

  WorkDoneProgressReport({
    this.cancellable,
    this.kind = 'report',
    this.message,
    this.percentage,
  }) {
    if (kind != 'report') {
      throw 'kind may only be the literal \'report\'';
    }
  }
  static WorkDoneProgressReport fromJson(Map<String, Object?> json) {
    final cancellableJson = json['cancellable'];
    final cancellable = cancellableJson as bool?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final messageJson = json['message'];
    final message = messageJson as String?;
    final percentageJson = json['percentage'];
    final percentage = percentageJson as int?;
    return WorkDoneProgressReport(
      cancellable: cancellable,
      kind: kind,
      message: message,
      percentage: percentage,
    );
  }

  /// Controls enablement state of a cancel button. This property is only valid
  /// if a cancel button got requested in the `WorkDoneProgressBegin` payload.
  ///
  /// Clients that don't support cancellation or don't support control the
  /// button's enablement state are allowed to ignore the setting.
  final bool? cancellable;
  final String kind;

  /// Optional, more detailed associated progress message. Contains
  /// complementary information to the `title`.
  ///
  /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". If
  /// unset, the previous progress message (if any) is still valid.
  final String? message;

  /// Optional progress percentage to display (value 100 is considered 100%). If
  /// not provided infinite progress is assumed and clients are allowed to
  /// ignore the `percentage` value in subsequent in report notifications.
  ///
  /// The value should be steadily rising. Clients are free to ignore values
  /// that are not following this rule. The value range is [0, 100]
  final int? percentage;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cancellable != null) {
      result['cancellable'] = cancellable;
    }
    result['kind'] = kind;
    if (message != null) {
      result['message'] = message;
    }
    if (percentage != null) {
      result['percentage'] = percentage;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('cancellable');
      try {
        final cancellable = obj['cancellable'];
        if (cancellable != null && cancellable is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'report') {
          reporter.reportError('must be the literal \'report\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        final message = obj['message'];
        if (message != null && message is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('percentage');
      try {
        final percentage = obj['percentage'];
        if (percentage != null && percentage is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkDoneProgressReport &&
        other.runtimeType == WorkDoneProgressReport) {
      return cancellable == other.cancellable &&
          kind == other.kind &&
          message == other.message &&
          percentage == other.percentage &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        cancellable,
        kind,
        message,
        percentage,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceClientCapabilities.canParse,
    WorkspaceClientCapabilities.fromJson,
  );

  WorkspaceClientCapabilities({
    this.applyEdit,
    this.codeLens,
    this.configuration,
    this.diagnostics,
    this.didChangeConfiguration,
    this.didChangeWatchedFiles,
    this.executeCommand,
    this.fileOperations,
    this.inlayHint,
    this.inlineValue,
    this.semanticTokens,
    this.symbol,
    this.workspaceEdit,
    this.workspaceFolders,
  });
  static WorkspaceClientCapabilities fromJson(Map<String, Object?> json) {
    final applyEditJson = json['applyEdit'];
    final applyEdit = applyEditJson as bool?;
    final codeLensJson = json['codeLens'];
    final codeLens = codeLensJson != null
        ? CodeLensWorkspaceClientCapabilities.fromJson(
            codeLensJson as Map<String, Object?>)
        : null;
    final configurationJson = json['configuration'];
    final configuration = configurationJson as bool?;
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = diagnosticsJson != null
        ? DiagnosticWorkspaceClientCapabilities.fromJson(
            diagnosticsJson as Map<String, Object?>)
        : null;
    final didChangeConfigurationJson = json['didChangeConfiguration'];
    final didChangeConfiguration = didChangeConfigurationJson != null
        ? DidChangeConfigurationClientCapabilities.fromJson(
            didChangeConfigurationJson as Map<String, Object?>)
        : null;
    final didChangeWatchedFilesJson = json['didChangeWatchedFiles'];
    final didChangeWatchedFiles = didChangeWatchedFilesJson != null
        ? DidChangeWatchedFilesClientCapabilities.fromJson(
            didChangeWatchedFilesJson as Map<String, Object?>)
        : null;
    final executeCommandJson = json['executeCommand'];
    final executeCommand = executeCommandJson != null
        ? ExecuteCommandClientCapabilities.fromJson(
            executeCommandJson as Map<String, Object?>)
        : null;
    final fileOperationsJson = json['fileOperations'];
    final fileOperations = fileOperationsJson != null
        ? FileOperationClientCapabilities.fromJson(
            fileOperationsJson as Map<String, Object?>)
        : null;
    final inlayHintJson = json['inlayHint'];
    final inlayHint = inlayHintJson != null
        ? InlayHintWorkspaceClientCapabilities.fromJson(
            inlayHintJson as Map<String, Object?>)
        : null;
    final inlineValueJson = json['inlineValue'];
    final inlineValue = inlineValueJson != null
        ? InlineValueWorkspaceClientCapabilities.fromJson(
            inlineValueJson as Map<String, Object?>)
        : null;
    final semanticTokensJson = json['semanticTokens'];
    final semanticTokens = semanticTokensJson != null
        ? SemanticTokensWorkspaceClientCapabilities.fromJson(
            semanticTokensJson as Map<String, Object?>)
        : null;
    final symbolJson = json['symbol'];
    final symbol = symbolJson != null
        ? WorkspaceSymbolClientCapabilities.fromJson(
            symbolJson as Map<String, Object?>)
        : null;
    final workspaceEditJson = json['workspaceEdit'];
    final workspaceEdit = workspaceEditJson != null
        ? WorkspaceEditClientCapabilities.fromJson(
            workspaceEditJson as Map<String, Object?>)
        : null;
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = workspaceFoldersJson as bool?;
    return WorkspaceClientCapabilities(
      applyEdit: applyEdit,
      codeLens: codeLens,
      configuration: configuration,
      diagnostics: diagnostics,
      didChangeConfiguration: didChangeConfiguration,
      didChangeWatchedFiles: didChangeWatchedFiles,
      executeCommand: executeCommand,
      fileOperations: fileOperations,
      inlayHint: inlayHint,
      inlineValue: inlineValue,
      semanticTokens: semanticTokens,
      symbol: symbol,
      workspaceEdit: workspaceEdit,
      workspaceFolders: workspaceFolders,
    );
  }

  /// The client supports applying batch edits to the workspace by supporting
  /// the request 'workspace/applyEdit'
  final bool? applyEdit;

  /// Capabilities specific to the code lens requests scoped to the workspace.
  ///  @since 3.16.0
  final CodeLensWorkspaceClientCapabilities? codeLens;

  /// The client supports `workspace/configuration` requests.
  ///  @since 3.6.0
  final bool? configuration;

  /// Client workspace capabilities specific to diagnostics.
  ///  @since 3.17.0.
  final DiagnosticWorkspaceClientCapabilities? diagnostics;

  /// Capabilities specific to the `workspace/didChangeConfiguration`
  /// notification.
  final DidChangeConfigurationClientCapabilities? didChangeConfiguration;

  /// Capabilities specific to the `workspace/didChangeWatchedFiles`
  /// notification.
  final DidChangeWatchedFilesClientCapabilities? didChangeWatchedFiles;

  /// Capabilities specific to the `workspace/executeCommand` request.
  final ExecuteCommandClientCapabilities? executeCommand;

  /// The client has support for file requests/notifications.
  ///  @since 3.16.0
  final FileOperationClientCapabilities? fileOperations;

  /// Client workspace capabilities specific to inlay hints.
  ///  @since 3.17.0
  final InlayHintWorkspaceClientCapabilities? inlayHint;

  /// Client workspace capabilities specific to inline values.
  ///  @since 3.17.0
  final InlineValueWorkspaceClientCapabilities? inlineValue;

  /// Capabilities specific to the semantic token requests scoped to the
  /// workspace.
  ///  @since 3.16.0
  final SemanticTokensWorkspaceClientCapabilities? semanticTokens;

  /// Capabilities specific to the `workspace/symbol` request.
  final WorkspaceSymbolClientCapabilities? symbol;

  /// Capabilities specific to `WorkspaceEdit`s
  final WorkspaceEditClientCapabilities? workspaceEdit;

  /// The client has support for workspace folders.
  ///  @since 3.6.0
  final bool? workspaceFolders;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (applyEdit != null) {
      result['applyEdit'] = applyEdit;
    }
    if (codeLens != null) {
      result['codeLens'] = codeLens?.toJson();
    }
    if (configuration != null) {
      result['configuration'] = configuration;
    }
    if (diagnostics != null) {
      result['diagnostics'] = diagnostics?.toJson();
    }
    if (didChangeConfiguration != null) {
      result['didChangeConfiguration'] = didChangeConfiguration?.toJson();
    }
    if (didChangeWatchedFiles != null) {
      result['didChangeWatchedFiles'] = didChangeWatchedFiles?.toJson();
    }
    if (executeCommand != null) {
      result['executeCommand'] = executeCommand?.toJson();
    }
    if (fileOperations != null) {
      result['fileOperations'] = fileOperations?.toJson();
    }
    if (inlayHint != null) {
      result['inlayHint'] = inlayHint?.toJson();
    }
    if (inlineValue != null) {
      result['inlineValue'] = inlineValue?.toJson();
    }
    if (semanticTokens != null) {
      result['semanticTokens'] = semanticTokens?.toJson();
    }
    if (symbol != null) {
      result['symbol'] = symbol?.toJson();
    }
    if (workspaceEdit != null) {
      result['workspaceEdit'] = workspaceEdit?.toJson();
    }
    if (workspaceFolders != null) {
      result['workspaceFolders'] = workspaceFolders;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('applyEdit');
      try {
        final applyEdit = obj['applyEdit'];
        if (applyEdit != null && applyEdit is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeLens');
      try {
        final codeLens = obj['codeLens'];
        if (codeLens != null &&
            !CodeLensWorkspaceClientCapabilities.canParse(codeLens, reporter)) {
          reporter.reportError(
              'must be of type CodeLensWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('configuration');
      try {
        final configuration = obj['configuration'];
        if (configuration != null && configuration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('diagnostics');
      try {
        final diagnostics = obj['diagnostics'];
        if (diagnostics != null &&
            !DiagnosticWorkspaceClientCapabilities.canParse(
                diagnostics, reporter)) {
          reporter.reportError(
              'must be of type DiagnosticWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didChangeConfiguration');
      try {
        final didChangeConfiguration = obj['didChangeConfiguration'];
        if (didChangeConfiguration != null &&
            !DidChangeConfigurationClientCapabilities.canParse(
                didChangeConfiguration, reporter)) {
          reporter.reportError(
              'must be of type DidChangeConfigurationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didChangeWatchedFiles');
      try {
        final didChangeWatchedFiles = obj['didChangeWatchedFiles'];
        if (didChangeWatchedFiles != null &&
            !DidChangeWatchedFilesClientCapabilities.canParse(
                didChangeWatchedFiles, reporter)) {
          reporter.reportError(
              'must be of type DidChangeWatchedFilesClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executeCommand');
      try {
        final executeCommand = obj['executeCommand'];
        if (executeCommand != null &&
            !ExecuteCommandClientCapabilities.canParse(
                executeCommand, reporter)) {
          reporter
              .reportError('must be of type ExecuteCommandClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('fileOperations');
      try {
        final fileOperations = obj['fileOperations'];
        if (fileOperations != null &&
            !FileOperationClientCapabilities.canParse(
                fileOperations, reporter)) {
          reporter
              .reportError('must be of type FileOperationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlayHint');
      try {
        final inlayHint = obj['inlayHint'];
        if (inlayHint != null &&
            !InlayHintWorkspaceClientCapabilities.canParse(
                inlayHint, reporter)) {
          reporter.reportError(
              'must be of type InlayHintWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('inlineValue');
      try {
        final inlineValue = obj['inlineValue'];
        if (inlineValue != null &&
            !InlineValueWorkspaceClientCapabilities.canParse(
                inlineValue, reporter)) {
          reporter.reportError(
              'must be of type InlineValueWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('semanticTokens');
      try {
        final semanticTokens = obj['semanticTokens'];
        if (semanticTokens != null &&
            !SemanticTokensWorkspaceClientCapabilities.canParse(
                semanticTokens, reporter)) {
          reporter.reportError(
              'must be of type SemanticTokensWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('symbol');
      try {
        final symbol = obj['symbol'];
        if (symbol != null &&
            !WorkspaceSymbolClientCapabilities.canParse(symbol, reporter)) {
          reporter
              .reportError('must be of type WorkspaceSymbolClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceEdit');
      try {
        final workspaceEdit = obj['workspaceEdit'];
        if (workspaceEdit != null &&
            !WorkspaceEditClientCapabilities.canParse(
                workspaceEdit, reporter)) {
          reporter
              .reportError('must be of type WorkspaceEditClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceFolders');
      try {
        final workspaceFolders = obj['workspaceFolders'];
        if (workspaceFolders != null && workspaceFolders is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceClientCapabilities &&
        other.runtimeType == WorkspaceClientCapabilities) {
      return applyEdit == other.applyEdit &&
          codeLens == other.codeLens &&
          configuration == other.configuration &&
          diagnostics == other.diagnostics &&
          didChangeConfiguration == other.didChangeConfiguration &&
          didChangeWatchedFiles == other.didChangeWatchedFiles &&
          executeCommand == other.executeCommand &&
          fileOperations == other.fileOperations &&
          inlayHint == other.inlayHint &&
          inlineValue == other.inlineValue &&
          semanticTokens == other.semanticTokens &&
          symbol == other.symbol &&
          workspaceEdit == other.workspaceEdit &&
          workspaceFolders == other.workspaceFolders &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        applyEdit,
        codeLens,
        configuration,
        diagnostics,
        didChangeConfiguration,
        didChangeWatchedFiles,
        executeCommand,
        fileOperations,
        inlayHint,
        inlineValue,
        semanticTokens,
        symbol,
        workspaceEdit,
        workspaceFolders,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters of the workspace diagnostic request.
///  @since 3.17.0
class WorkspaceDiagnosticParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceDiagnosticParams.canParse,
    WorkspaceDiagnosticParams.fromJson,
  );

  WorkspaceDiagnosticParams({
    this.identifier,
    this.partialResultToken,
    required this.previousResultIds,
    this.workDoneToken,
  });
  static WorkspaceDiagnosticParams fromJson(Map<String, Object?> json) {
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String?;
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final previousResultIdsJson = json['previousResultIds'];
    final previousResultIds = (previousResultIdsJson as List<Object?>)
        .map((item) => PreviousResultId.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return WorkspaceDiagnosticParams(
      identifier: identifier,
      partialResultToken: partialResultToken,
      previousResultIds: previousResultIds,
      workDoneToken: workDoneToken,
    );
  }

  /// The additional identifier provided during registration.
  final String? identifier;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// The currently known diagnostic reports with their previous result ids.
  final List<PreviousResultId> previousResultIds;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (identifier != null) {
      result['identifier'] = identifier;
    }
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['previousResultIds'] =
        previousResultIds.map((item) => item.toJson()).toList();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('identifier');
      try {
        final identifier = obj['identifier'];
        if (identifier != null && identifier is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('previousResultIds');
      try {
        if (!obj.containsKey('previousResultIds')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final previousResultIds = obj['previousResultIds'];
        if (previousResultIds == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (previousResultIds is! List<Object?> ||
            previousResultIds
                .any((item) => !PreviousResultId.canParse(item, reporter))) {
          reporter.reportError('must be of type List<PreviousResultId>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceDiagnosticParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceDiagnosticParams &&
        other.runtimeType == WorkspaceDiagnosticParams) {
      return identifier == other.identifier &&
          partialResultToken == other.partialResultToken &&
          listEqual(previousResultIds, other.previousResultIds,
              (PreviousResultId a, PreviousResultId b) => a == b) &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        identifier,
        partialResultToken,
        lspHashCode(previousResultIds),
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A workspace diagnostic report.
///  @since 3.17.0
class WorkspaceDiagnosticReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceDiagnosticReport.canParse,
    WorkspaceDiagnosticReport.fromJson,
  );

  WorkspaceDiagnosticReport({
    required this.items,
  });
  static WorkspaceDiagnosticReport fromJson(Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => WorkspaceFullDocumentDiagnosticReport.canParse(
                item, nullLspJsonReporter)
            ? Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>.t1(
                WorkspaceFullDocumentDiagnosticReport.fromJson(
                    item as Map<String, Object?>))
            : (WorkspaceUnchangedDocumentDiagnosticReport.canParse(
                    item, nullLspJsonReporter)
                ? Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>.t2(
                    WorkspaceUnchangedDocumentDiagnosticReport.fromJson(
                        item as Map<String, Object?>))
                : (throw '''$item was not one of (WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport)''')))
        .toList();
    return WorkspaceDiagnosticReport(
      items: items,
    );
  }

  final List<
      Either2<WorkspaceFullDocumentDiagnosticReport,
          WorkspaceUnchangedDocumentDiagnosticReport>> items;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) =>
                !WorkspaceFullDocumentDiagnosticReport.canParse(
                    item, reporter) &&
                !WorkspaceUnchangedDocumentDiagnosticReport.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceDiagnosticReport &&
        other.runtimeType == WorkspaceDiagnosticReport) {
      return listEqual(
              items,
              other.items,
              (Either2<WorkspaceFullDocumentDiagnosticReport,
                              WorkspaceUnchangedDocumentDiagnosticReport>
                          a,
                      Either2<WorkspaceFullDocumentDiagnosticReport,
                              WorkspaceUnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(items);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A partial result for a workspace diagnostic report.
///  @since 3.17.0
class WorkspaceDiagnosticReportPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceDiagnosticReportPartialResult.canParse,
    WorkspaceDiagnosticReportPartialResult.fromJson,
  );

  WorkspaceDiagnosticReportPartialResult({
    required this.items,
  });
  static WorkspaceDiagnosticReportPartialResult fromJson(
      Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => WorkspaceFullDocumentDiagnosticReport.canParse(
                item, nullLspJsonReporter)
            ? Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>.t1(
                WorkspaceFullDocumentDiagnosticReport.fromJson(
                    item as Map<String, Object?>))
            : (WorkspaceUnchangedDocumentDiagnosticReport.canParse(
                    item, nullLspJsonReporter)
                ? Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>.t2(
                    WorkspaceUnchangedDocumentDiagnosticReport.fromJson(
                        item as Map<String, Object?>))
                : (throw '''$item was not one of (WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport)''')))
        .toList();
    return WorkspaceDiagnosticReportPartialResult(
      items: items,
    );
  }

  final List<
      Either2<WorkspaceFullDocumentDiagnosticReport,
          WorkspaceUnchangedDocumentDiagnosticReport>> items;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) =>
                !WorkspaceFullDocumentDiagnosticReport.canParse(
                    item, reporter) &&
                !WorkspaceUnchangedDocumentDiagnosticReport.canParse(
                    item, reporter))) {
          reporter.reportError(
              'must be of type List<Either2<WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceDiagnosticReportPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceDiagnosticReportPartialResult &&
        other.runtimeType == WorkspaceDiagnosticReportPartialResult) {
      return listEqual(
              items,
              other.items,
              (Either2<WorkspaceFullDocumentDiagnosticReport,
                              WorkspaceUnchangedDocumentDiagnosticReport>
                          a,
                      Either2<WorkspaceFullDocumentDiagnosticReport,
                              WorkspaceUnchangedDocumentDiagnosticReport>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(items);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceEdit.canParse,
    WorkspaceEdit.fromJson,
  );

  WorkspaceEdit({
    this.changeAnnotations,
    this.changes,
    this.documentChanges,
  });
  static WorkspaceEdit fromJson(Map<String, Object?> json) {
    final changeAnnotationsJson = json['changeAnnotations'];
    final changeAnnotations = (changeAnnotationsJson as Map<Object, Object?>?)
        ?.map((key, value) => MapEntry(key as String,
            ChangeAnnotation.fromJson(value as Map<String, Object?>)));
    final changesJson = json['changes'];
    final changes = (changesJson as Map<Object, Object?>?)?.map((key, value) =>
        MapEntry(
            key as String,
            (value as List<Object?>)
                .map((item) => TextEdit.fromJson(item as Map<String, Object?>))
                .toList()));
    final documentChangesJson = json['documentChanges'];
    final documentChanges = (documentChangesJson as List<Object?>?)
        ?.map((item) => CreateFile.canParse(item, nullLspJsonReporter)
            ? Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>.t1(
                CreateFile.fromJson(item as Map<String, Object?>))
            : (DeleteFile.canParse(item, nullLspJsonReporter)
                ? Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>.t2(
                    DeleteFile.fromJson(item as Map<String, Object?>))
                : (RenameFile.canParse(item, nullLspJsonReporter)
                    ? Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>.t3(
                        RenameFile.fromJson(item as Map<String, Object?>))
                    : (TextDocumentEdit.canParse(item, nullLspJsonReporter)
                        ? Either4<CreateFile, DeleteFile, RenameFile,
                                TextDocumentEdit>.t4(
                            TextDocumentEdit.fromJson(item as Map<String, Object?>))
                        : (throw '''$item was not one of (CreateFile, DeleteFile, RenameFile, TextDocumentEdit)''')))))
        .toList();
    return WorkspaceEdit(
      changeAnnotations: changeAnnotations,
      changes: changes,
      documentChanges: documentChanges,
    );
  }

  /// A map of change annotations that can be referenced in `AnnotatedTextEdit`s
  /// or create, rename and delete file / folder operations.
  ///
  /// Whether clients honor this property depends on the client capability
  /// `workspace.changeAnnotationSupport`.
  ///  @since 3.16.0
  final Map<String, ChangeAnnotation>? changeAnnotations;

  /// Holds changes to existing resources.
  final Map<String, List<TextEdit>>? changes;

  /// Depending on the client capability
  /// `workspace.workspaceEdit.resourceOperations` document changes are either
  /// an array of `TextDocumentEdit`s to express changes to n different text
  /// documents where each text document edit addresses a specific version of a
  /// text document. Or it can contain above `TextDocumentEdit`s mixed with
  /// create, rename and delete file / folder operations.
  ///
  /// Whether a client supports versioned document edits is expressed via
  /// `workspace.workspaceEdit.documentChanges` client capability.
  ///
  /// If a client neither supports `documentChanges` nor
  /// `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s
  /// using the `changes` property are supported.
  final List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>?
      documentChanges;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (changeAnnotations != null) {
      result['changeAnnotations'] = changeAnnotations;
    }
    if (changes != null) {
      result['changes'] = changes;
    }
    if (documentChanges != null) {
      result['documentChanges'] = documentChanges;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('changeAnnotations');
      try {
        final changeAnnotations = obj['changeAnnotations'];
        if (changeAnnotations != null &&
            (changeAnnotations is! Map ||
                (changeAnnotations.keys.any((item) =>
                    item is! String ||
                    changeAnnotations.values.any((item) =>
                        !ChangeAnnotation.canParse(item, reporter)))))) {
          reporter.reportError('must be of type Map<String, ChangeAnnotation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('changes');
      try {
        final changes = obj['changes'];
        if (changes != null &&
            (changes is! Map ||
                (changes.keys.any((item) =>
                    item is! String ||
                    changes.values.any((item) =>
                        item is! List<Object?> ||
                        item.any(
                            (item) => !TextEdit.canParse(item, reporter))))))) {
          reporter.reportError('must be of type Map<String, List<TextEdit>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentChanges');
      try {
        final documentChanges = obj['documentChanges'];
        if (documentChanges != null &&
            (documentChanges is! List<Object?> ||
                documentChanges.any((item) =>
                    !CreateFile.canParse(item, reporter) &&
                    !DeleteFile.canParse(item, reporter) &&
                    !RenameFile.canParse(item, reporter) &&
                    !TextDocumentEdit.canParse(item, reporter)))) {
          reporter.reportError(
              'must be of type List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceEdit && other.runtimeType == WorkspaceEdit) {
      return mapEqual(changeAnnotations, other.changeAnnotations,
              (ChangeAnnotation a, ChangeAnnotation b) => a == b) &&
          mapEqual(
              changes,
              other.changes,
              (List<TextEdit> a, List<TextEdit> b) =>
                  listEqual(a, b, (TextEdit a, TextEdit b) => a == b)) &&
          listEqual(
              documentChanges,
              other.documentChanges,
              (Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit> a,
                      Either4<CreateFile, DeleteFile, RenameFile,
                              TextDocumentEdit>
                          b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(changeAnnotations),
        lspHashCode(changes),
        lspHashCode(documentChanges),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceEditClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceEditClientCapabilities.canParse,
    WorkspaceEditClientCapabilities.fromJson,
  );

  WorkspaceEditClientCapabilities({
    this.changeAnnotationSupport,
    this.documentChanges,
    this.failureHandling,
    this.normalizesLineEndings,
    this.resourceOperations,
  });
  static WorkspaceEditClientCapabilities fromJson(Map<String, Object?> json) {
    final changeAnnotationSupportJson = json['changeAnnotationSupport'];
    final changeAnnotationSupport = changeAnnotationSupportJson != null
        ? WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson(
            changeAnnotationSupportJson as Map<String, Object?>)
        : null;
    final documentChangesJson = json['documentChanges'];
    final documentChanges = documentChangesJson as bool?;
    final failureHandlingJson = json['failureHandling'];
    final failureHandling = failureHandlingJson != null
        ? FailureHandlingKind.fromJson(failureHandlingJson as String)
        : null;
    final normalizesLineEndingsJson = json['normalizesLineEndings'];
    final normalizesLineEndings = normalizesLineEndingsJson as bool?;
    final resourceOperationsJson = json['resourceOperations'];
    final resourceOperations = (resourceOperationsJson as List<Object?>?)
        ?.map((item) => ResourceOperationKind.fromJson(item as String))
        .toList();
    return WorkspaceEditClientCapabilities(
      changeAnnotationSupport: changeAnnotationSupport,
      documentChanges: documentChanges,
      failureHandling: failureHandling,
      normalizesLineEndings: normalizesLineEndings,
      resourceOperations: resourceOperations,
    );
  }

  /// Whether the client in general supports change annotations on text edits,
  /// create file, rename file and delete file changes.
  ///  @since 3.16.0
  final WorkspaceEditClientCapabilitiesChangeAnnotationSupport?
      changeAnnotationSupport;

  /// The client supports versioned document changes in `WorkspaceEdit`s
  final bool? documentChanges;

  /// The failure handling strategy of a client if applying the workspace edit
  /// fails.
  ///  @since 3.13.0
  final FailureHandlingKind? failureHandling;

  /// Whether the client normalizes line endings to the client specific setting.
  /// If set to `true` the client will normalize line ending characters in a
  /// workspace edit to the client 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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (changeAnnotationSupport != null) {
      result['changeAnnotationSupport'] = changeAnnotationSupport?.toJson();
    }
    if (documentChanges != null) {
      result['documentChanges'] = documentChanges;
    }
    if (failureHandling != null) {
      result['failureHandling'] = failureHandling?.toJson();
    }
    if (normalizesLineEndings != null) {
      result['normalizesLineEndings'] = normalizesLineEndings;
    }
    if (resourceOperations != null) {
      result['resourceOperations'] =
          resourceOperations?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('changeAnnotationSupport');
      try {
        final changeAnnotationSupport = obj['changeAnnotationSupport'];
        if (changeAnnotationSupport != null &&
            !WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse(
                changeAnnotationSupport, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentChanges');
      try {
        final documentChanges = obj['documentChanges'];
        if (documentChanges != null && documentChanges is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('failureHandling');
      try {
        final failureHandling = obj['failureHandling'];
        if (failureHandling != null &&
            !FailureHandlingKind.canParse(failureHandling, reporter)) {
          reporter.reportError('must be of type FailureHandlingKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('normalizesLineEndings');
      try {
        final normalizesLineEndings = obj['normalizesLineEndings'];
        if (normalizesLineEndings != null && normalizesLineEndings is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resourceOperations');
      try {
        final resourceOperations = obj['resourceOperations'];
        if (resourceOperations != null &&
            (resourceOperations is! List<Object?> ||
                resourceOperations.any((item) =>
                    !ResourceOperationKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<ResourceOperationKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceEditClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceEditClientCapabilities &&
        other.runtimeType == WorkspaceEditClientCapabilities) {
      return changeAnnotationSupport == other.changeAnnotationSupport &&
          documentChanges == other.documentChanges &&
          failureHandling == other.failureHandling &&
          normalizesLineEndings == other.normalizesLineEndings &&
          listEqual(resourceOperations, other.resourceOperations,
              (ResourceOperationKind a, ResourceOperationKind b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        changeAnnotationSupport,
        documentChanges,
        failureHandling,
        normalizesLineEndings,
        lspHashCode(resourceOperations),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceEditClientCapabilitiesChangeAnnotationSupport
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse,
    WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson,
  );

  WorkspaceEditClientCapabilitiesChangeAnnotationSupport({
    this.groupsOnLabel,
  });
  static WorkspaceEditClientCapabilitiesChangeAnnotationSupport fromJson(
      Map<String, Object?> json) {
    final groupsOnLabelJson = json['groupsOnLabel'];
    final groupsOnLabel = groupsOnLabelJson as bool?;
    return WorkspaceEditClientCapabilitiesChangeAnnotationSupport(
      groupsOnLabel: groupsOnLabel,
    );
  }

  /// Whether the client groups edits with equal labels into tree nodes, for
  /// instance all edits labelled with "Changes in Strings" would be a tree
  /// node.
  final bool? groupsOnLabel;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (groupsOnLabel != null) {
      result['groupsOnLabel'] = groupsOnLabel;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('groupsOnLabel');
      try {
        final groupsOnLabel = obj['groupsOnLabel'];
        if (groupsOnLabel != null && groupsOnLabel is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceEditClientCapabilitiesChangeAnnotationSupport &&
        other.runtimeType ==
            WorkspaceEditClientCapabilitiesChangeAnnotationSupport) {
      return groupsOnLabel == other.groupsOnLabel && true;
    }
    return false;
  }

  @override
  int get hashCode => groupsOnLabel.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceFolder implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFolder.canParse,
    WorkspaceFolder.fromJson,
  );

  WorkspaceFolder({
    required this.name,
    required this.uri,
  });
  static WorkspaceFolder fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return WorkspaceFolder(
      name: name,
      uri: uri,
    );
  }

  /// The name of the workspace folder. Used to refer to this workspace folder
  /// in the user interface.
  final String name;

  /// The associated URI for this workspace folder.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['name'] = name;
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceFolder');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceFolder && other.runtimeType == WorkspaceFolder) {
      return name == other.name && uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        name,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The workspace folder change event.
class WorkspaceFoldersChangeEvent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFoldersChangeEvent.canParse,
    WorkspaceFoldersChangeEvent.fromJson,
  );

  WorkspaceFoldersChangeEvent({
    required this.added,
    required this.removed,
  });
  static WorkspaceFoldersChangeEvent fromJson(Map<String, Object?> json) {
    final addedJson = json['added'];
    final added = (addedJson as List<Object?>)
        .map((item) => WorkspaceFolder.fromJson(item as Map<String, Object?>))
        .toList();
    final removedJson = json['removed'];
    final removed = (removedJson as List<Object?>)
        .map((item) => WorkspaceFolder.fromJson(item as Map<String, Object?>))
        .toList();
    return WorkspaceFoldersChangeEvent(
      added: added,
      removed: removed,
    );
  }

  /// The array of added workspace folders
  final List<WorkspaceFolder> added;

  /// The array of the removed workspace folders
  final List<WorkspaceFolder> removed;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['added'] = added.map((item) => item.toJson()).toList();
    result['removed'] = removed.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('added');
      try {
        if (!obj.containsKey('added')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final added = obj['added'];
        if (added == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (added is! List<Object?> ||
            added.any((item) => !WorkspaceFolder.canParse(item, reporter))) {
          reporter.reportError('must be of type List<WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('removed');
      try {
        if (!obj.containsKey('removed')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final removed = obj['removed'];
        if (removed == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (removed is! List<Object?> ||
            removed.any((item) => !WorkspaceFolder.canParse(item, reporter))) {
          reporter.reportError('must be of type List<WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceFoldersChangeEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceFoldersChangeEvent &&
        other.runtimeType == WorkspaceFoldersChangeEvent) {
      return listEqual(added, other.added,
              (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
          listEqual(removed, other.removed,
              (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(added),
        lspHashCode(removed),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceFoldersServerCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFoldersServerCapabilities.canParse,
    WorkspaceFoldersServerCapabilities.fromJson,
  );

  WorkspaceFoldersServerCapabilities({
    this.changeNotifications,
    this.supported,
  });
  static WorkspaceFoldersServerCapabilities fromJson(
      Map<String, Object?> json) {
    final changeNotificationsJson = json['changeNotifications'];
    final changeNotifications = changeNotificationsJson == null
        ? null
        : (changeNotificationsJson is bool
            ? Either2<bool, String>.t1(changeNotificationsJson)
            : (changeNotificationsJson is String
                ? Either2<bool, String>.t2(changeNotificationsJson)
                : (throw '''$changeNotificationsJson was not one of (bool, String)''')));
    final supportedJson = json['supported'];
    final supported = supportedJson as bool?;
    return WorkspaceFoldersServerCapabilities(
      changeNotifications: changeNotifications,
      supported: supported,
    );
  }

  /// Whether the server wants to receive workspace folder change notifications.
  ///
  /// If a string is provided, the string is treated as an ID under which the
  /// notification is registered on the client side. The ID can be used to
  /// unregister for these events using the `client/unregisterCapability`
  /// request.
  final Either2<bool, String>? changeNotifications;

  /// The server has support for workspace folders
  final bool? supported;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (changeNotifications != null) {
      result['changeNotifications'] = changeNotifications;
    }
    if (supported != null) {
      result['supported'] = supported;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('changeNotifications');
      try {
        final changeNotifications = obj['changeNotifications'];
        if (changeNotifications != null &&
            changeNotifications is! bool &&
            changeNotifications is! String) {
          reporter.reportError('must be of type Either2<bool, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('supported');
      try {
        final supported = obj['supported'];
        if (supported != null && supported is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type WorkspaceFoldersServerCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceFoldersServerCapabilities &&
        other.runtimeType == WorkspaceFoldersServerCapabilities) {
      return changeNotifications == other.changeNotifications &&
          supported == other.supported &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        changeNotifications,
        supported,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A full document diagnostic report for a workspace diagnostic result.
///  @since 3.17.0
class WorkspaceFullDocumentDiagnosticReport
    implements FullDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFullDocumentDiagnosticReport.canParse,
    WorkspaceFullDocumentDiagnosticReport.fromJson,
  );

  WorkspaceFullDocumentDiagnosticReport({
    required this.items,
    this.kind = 'full',
    this.resultId,
    required this.uri,
    this.version,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static WorkspaceFullDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return WorkspaceFullDocumentDiagnosticReport(
      items: items,
      kind: kind,
      resultId: resultId,
      uri: uri,
      version: version,
    );
  }

  /// The actual items.
  @override
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  @override
  final String kind;

  /// An optional result id. If provided it will be sent on the next diagnostic
  /// request for the same document.
  @override
  final String? resultId;

  /// The URI for which diagnostic information is reported.
  final String uri;

  /// The version number for which the diagnostics are reported. If the document
  /// is not marked as open `null` can be provided.
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    result['kind'] = kind;
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('items');
      try {
        if (!obj.containsKey('items')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final items = obj['items'];
        if (items == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (items is! List<Object?> ||
            items.any((item) => !Diagnostic.canParse(item, reporter))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'full') {
          reporter.reportError('must be the literal \'full\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        final resultId = obj['resultId'];
        if (resultId != null && resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version != null && version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type WorkspaceFullDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceFullDocumentDiagnosticReport &&
        other.runtimeType == WorkspaceFullDocumentDiagnosticReport) {
      return listEqual(
              items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
          kind == other.kind &&
          resultId == other.resultId &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(items),
        kind,
        resultId,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A special workspace symbol that supports locations without a range
///  @since 3.17.0
class WorkspaceSymbol implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbol.canParse,
    WorkspaceSymbol.fromJson,
  );

  WorkspaceSymbol({
    this.containerName,
    required this.kind,
    required this.location,
    required this.name,
    this.tags,
  });
  static WorkspaceSymbol fromJson(Map<String, Object?> json) {
    final containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final locationJson = json['location'];
    final location = Location.canParse(locationJson, nullLspJsonReporter)
        ? Either2<Location, WorkspaceSymbolLocation>.t1(
            Location.fromJson(locationJson as Map<String, Object?>))
        : (WorkspaceSymbolLocation.canParse(locationJson, nullLspJsonReporter)
            ? Either2<Location, WorkspaceSymbolLocation>.t2(
                WorkspaceSymbolLocation.fromJson(
                    locationJson as Map<String, Object?>))
            : (throw '''$locationJson was not one of (Location, WorkspaceSymbolLocation)'''));
    final nameJson = json['name'];
    final name = nameJson as String;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return WorkspaceSymbol(
      containerName: containerName,
      kind: kind,
      location: location,
      name: name,
      tags: tags,
    );
  }

  /// The name of the symbol containing this symbol. This information is for
  /// user interface purposes (e.g. to render a qualifier in the user interface
  /// if necessary). It can't be used to re-infer a hierarchy for the document
  /// symbols.
  final String? containerName;

  /// The kind of this symbol.
  final SymbolKind kind;

  /// The location of this symbol. Whether a server is allowed to return a
  /// location without a range depends on the client capability
  /// `workspace.symbol.resolveSupport`.
  ///
  /// See also `SymbolInformation.location`.
  final Either2<Location, WorkspaceSymbolLocation> location;

  /// The name of this symbol.
  final String name;

  /// Tags for this completion item.
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (containerName != null) {
      result['containerName'] = containerName;
    }
    result['kind'] = kind.toJson();
    result['location'] = location;
    result['name'] = name;
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('containerName');
      try {
        final containerName = obj['containerName'];
        if (containerName != null && containerName is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!SymbolKind.canParse(kind, reporter)) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('location');
      try {
        if (!obj.containsKey('location')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final location = obj['location'];
        if (location == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!Location.canParse(location, reporter) &&
            !WorkspaceSymbolLocation.canParse(location, reporter)) {
          reporter.reportError(
              'must be of type Either2<Location, WorkspaceSymbolLocation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final name = obj['name'];
        if (name == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (name is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        final tags = obj['tags'];
        if (tags != null &&
            (tags is! List<Object?> ||
                tags.any((item) => !SymbolTag.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbol');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbol && other.runtimeType == WorkspaceSymbol) {
      return containerName == other.containerName &&
          kind == other.kind &&
          location == other.location &&
          name == other.name &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        containerName,
        kind,
        location,
        name,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilities.canParse,
    WorkspaceSymbolClientCapabilities.fromJson,
  );

  WorkspaceSymbolClientCapabilities({
    this.dynamicRegistration,
    this.resolveSupport,
    this.symbolKind,
    this.tagSupport,
  });
  static WorkspaceSymbolClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final resolveSupportJson = json['resolveSupport'];
    final resolveSupport = resolveSupportJson != null
        ? WorkspaceSymbolClientCapabilitiesResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    final symbolKindJson = json['symbolKind'];
    final symbolKind = symbolKindJson != null
        ? WorkspaceSymbolClientCapabilitiesSymbolKind.fromJson(
            symbolKindJson as Map<String, Object?>)
        : null;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? WorkspaceSymbolClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    return WorkspaceSymbolClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      resolveSupport: resolveSupport,
      symbolKind: symbolKind,
      tagSupport: tagSupport,
    );
  }

  /// Symbol request supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client support partial workspace symbols. The client will send the
  /// request `workspaceSymbol/resolve` to the server to resolve additional
  /// properties.
  ///  @since 3.17.0 - proposedState
  final WorkspaceSymbolClientCapabilitiesResolveSupport? resolveSupport;

  /// Specific capabilities for the `SymbolKind` in the `workspace/symbol`
  /// request.
  final WorkspaceSymbolClientCapabilitiesSymbolKind? symbolKind;

  /// The client supports tags on `SymbolInformation` and `WorkspaceSymbol`.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///  @since 3.16.0
  final WorkspaceSymbolClientCapabilitiesTagSupport? tagSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (resolveSupport != null) {
      result['resolveSupport'] = resolveSupport?.toJson();
    }
    if (symbolKind != null) {
      result['symbolKind'] = symbolKind?.toJson();
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('dynamicRegistration');
      try {
        final dynamicRegistration = obj['dynamicRegistration'];
        if (dynamicRegistration != null && dynamicRegistration is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveSupport');
      try {
        final resolveSupport = obj['resolveSupport'];
        if (resolveSupport != null &&
            !WorkspaceSymbolClientCapabilitiesResolveSupport.canParse(
                resolveSupport, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceSymbolClientCapabilitiesResolveSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('symbolKind');
      try {
        final symbolKind = obj['symbolKind'];
        if (symbolKind != null &&
            !WorkspaceSymbolClientCapabilitiesSymbolKind.canParse(
                symbolKind, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        final tagSupport = obj['tagSupport'];
        if (tagSupport != null &&
            !WorkspaceSymbolClientCapabilitiesTagSupport.canParse(
                tagSupport, reporter)) {
          reporter.reportError(
              'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolClientCapabilities &&
        other.runtimeType == WorkspaceSymbolClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          resolveSupport == other.resolveSupport &&
          symbolKind == other.symbolKind &&
          tagSupport == other.tagSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        resolveSupport,
        symbolKind,
        tagSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesResolveSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilitiesResolveSupport.canParse,
    WorkspaceSymbolClientCapabilitiesResolveSupport.fromJson,
  );

  WorkspaceSymbolClientCapabilitiesResolveSupport({
    required this.properties,
  });
  static WorkspaceSymbolClientCapabilitiesResolveSupport fromJson(
      Map<String, Object?> json) {
    final propertiesJson = json['properties'];
    final properties = (propertiesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return WorkspaceSymbolClientCapabilitiesResolveSupport(
      properties: properties,
    );
  }

  /// The properties that a client can resolve lazily. Usually `location.range`
  final List<String> properties;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['properties'] = properties;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('properties');
      try {
        if (!obj.containsKey('properties')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final properties = obj['properties'];
        if (properties == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (properties is! List<Object?> ||
            properties.any((item) => item is! String)) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesResolveSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolClientCapabilitiesResolveSupport &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesResolveSupport) {
      return listEqual(
              properties, other.properties, (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(properties);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesSymbolKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilitiesSymbolKind.canParse,
    WorkspaceSymbolClientCapabilitiesSymbolKind.fromJson,
  );

  WorkspaceSymbolClientCapabilitiesSymbolKind({
    this.valueSet,
  });
  static WorkspaceSymbolClientCapabilitiesSymbolKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => SymbolKind.fromJson(item as int))
        .toList();
    return WorkspaceSymbolClientCapabilitiesSymbolKind(
      valueSet: valueSet,
    );
  }

  /// The symbol kind values the client supports. When this property exists the
  /// client also guarantees that it will handle values outside its set
  /// gracefully and falls back to a default value when unknown.
  ///
  /// If this property is not present the client only supports the symbol kinds
  /// from `File` to `Array` as defined in the initial version of the protocol.
  final List<SymbolKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        final valueSet = obj['valueSet'];
        if (valueSet != null &&
            (valueSet is! List<Object?> ||
                valueSet.any((item) => !SymbolKind.canParse(item, reporter)))) {
          reporter.reportError('must be of type List<SymbolKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolClientCapabilitiesSymbolKind &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesSymbolKind) {
      return listEqual(valueSet, other.valueSet,
              (SymbolKind a, SymbolKind b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilitiesTagSupport.canParse,
    WorkspaceSymbolClientCapabilitiesTagSupport.fromJson,
  );

  WorkspaceSymbolClientCapabilitiesTagSupport({
    required this.valueSet,
  });
  static WorkspaceSymbolClientCapabilitiesTagSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return WorkspaceSymbolClientCapabilitiesTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<SymbolTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final valueSet = obj['valueSet'];
        if (valueSet == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (valueSet is! List<Object?> ||
            valueSet.any((item) => !SymbolTag.canParse(item, reporter))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolClientCapabilitiesTagSupport &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesTagSupport) {
      return listEqual(
              valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolLocation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolLocation.canParse,
    WorkspaceSymbolLocation.fromJson,
  );

  WorkspaceSymbolLocation({
    required this.uri,
  });
  static WorkspaceSymbolLocation fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return WorkspaceSymbolLocation(
      uri: uri,
    );
  }

  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolLocation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolLocation &&
        other.runtimeType == WorkspaceSymbolLocation) {
      return uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolOptions.canParse,
    WorkspaceSymbolOptions.fromJson,
  );

  WorkspaceSymbolOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static WorkspaceSymbolOptions fromJson(Map<String, Object?> json) {
    if (WorkspaceSymbolRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceSymbolRegistrationOptions.fromJson(json);
    }
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkspaceSymbolOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The server provides support to resolve additional information for a
  /// workspace symbol.
  ///  @since 3.17.0
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolOptions &&
        other.runtimeType == WorkspaceSymbolOptions) {
      return resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a Workspace Symbol Request.
class WorkspaceSymbolParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolParams.canParse,
    WorkspaceSymbolParams.fromJson,
  );

  WorkspaceSymbolParams({
    this.partialResultToken,
    required this.query,
    this.workDoneToken,
  });
  static WorkspaceSymbolParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : (partialResultTokenJson is int
            ? Either2<int, String>.t1(partialResultTokenJson)
            : (partialResultTokenJson is String
                ? Either2<int, String>.t2(partialResultTokenJson)
                : (throw '''$partialResultTokenJson was not one of (int, String)''')));
    final queryJson = json['query'];
    final query = queryJson as String;
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken = workDoneTokenJson == null
        ? null
        : (workDoneTokenJson is int
            ? Either2<int, String>.t1(workDoneTokenJson)
            : (workDoneTokenJson is String
                ? Either2<int, String>.t2(workDoneTokenJson)
                : (throw '''$workDoneTokenJson was not one of (int, String)''')));
    return WorkspaceSymbolParams(
      partialResultToken: partialResultToken,
      query: query,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final Either2<int, String>? partialResultToken;

  /// A query string to filter symbols by. Clients may send an empty string here
  /// to request all symbols.
  final String query;

  /// An optional token that a server can use to report work done progress.
  @override
  final Either2<int, String>? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['query'] = query;
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('partialResultToken');
      try {
        final partialResultToken = obj['partialResultToken'];
        if (partialResultToken != null &&
            partialResultToken is! int &&
            partialResultToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('query');
      try {
        if (!obj.containsKey('query')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final query = obj['query'];
        if (query == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (query is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        final workDoneToken = obj['workDoneToken'];
        if (workDoneToken != null &&
            workDoneToken is! int &&
            workDoneToken is! String) {
          reporter.reportError('must be of type Either2<int, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolParams &&
        other.runtimeType == WorkspaceSymbolParams) {
      return partialResultToken == other.partialResultToken &&
          query == other.query &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        query,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolRegistrationOptions
    implements WorkspaceSymbolOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolRegistrationOptions.canParse,
    WorkspaceSymbolRegistrationOptions.fromJson,
  );

  WorkspaceSymbolRegistrationOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static WorkspaceSymbolRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkspaceSymbolRegistrationOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The server provides support to resolve additional information for a
  /// workspace symbol.
  ///  @since 3.17.0
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('resolveProvider');
      try {
        final resolveProvider = obj['resolveProvider'];
        if (resolveProvider != null && resolveProvider is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        final workDoneProgress = obj['workDoneProgress'];
        if (workDoneProgress != null && workDoneProgress is! bool) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type WorkspaceSymbolRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolRegistrationOptions &&
        other.runtimeType == WorkspaceSymbolRegistrationOptions) {
      return resolveProvider == other.resolveProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An unchanged document diagnostic report for a workspace diagnostic result.
///  @since 3.17.0
class WorkspaceUnchangedDocumentDiagnosticReport
    implements UnchangedDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceUnchangedDocumentDiagnosticReport.canParse,
    WorkspaceUnchangedDocumentDiagnosticReport.fromJson,
  );

  WorkspaceUnchangedDocumentDiagnosticReport({
    this.kind = 'unchanged',
    required this.resultId,
    required this.uri,
    this.version,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static WorkspaceUnchangedDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return WorkspaceUnchangedDocumentDiagnosticReport(
      kind: kind,
      resultId: resultId,
      uri: uri,
      version: version,
    );
  }

  /// A document diagnostic report indicating no changes to the last result. A
  /// server can only return `unchanged` if result ids are provided.
  @override
  final String kind;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  @override
  final String resultId;

  /// The URI for which diagnostic information is reported.
  final String uri;

  /// The version number for which the diagnostics are reported. If the document
  /// is not marked as open `null` can be provided.
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    result['resultId'] = resultId;
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final kind = obj['kind'];
        if (kind == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (kind != 'unchanged') {
          reporter.reportError('must be the literal \'unchanged\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resultId');
      try {
        if (!obj.containsKey('resultId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final resultId = obj['resultId'];
        if (resultId == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (resultId is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final uri = obj['uri'];
        if (uri == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (uri is! String) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        final version = obj['version'];
        if (version != null && version is! int) {
          reporter.reportError('must be of type int');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceUnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceUnchangedDocumentDiagnosticReport &&
        other.runtimeType == WorkspaceUnchangedDocumentDiagnosticReport) {
      return kind == other.kind &&
          resultId == other.resultId &&
          uri == other.uri &&
          version == other.version &&
          true;
    }
    return false;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        resultId,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}
